ContentControl is not visible when application starts via UI Automation test, but its visible when application starts by user

c#, devexpress, ui-automation, wpf, xaml

Solution

I'm sorry that I've missed some detail, that was the key to the answer. I think that it was not important thing. Anyway.

We used `NavBar` from DevExpress controls library for WPF. What turns out, is when `NavBar` is present, dynamically created views are not appears on the UI Automation tree. When remove it from the window, there was an ability to see all dynamically loaded views. What does the `NavBar` - still mistic for me.

Here bright example to see what happened, if NavBar is present or absent on the Window (DevExpress is required).

MainWindow.xaml:

<Window xmlns:dxn="http://schemas.devexpress.com/winfx/2008/xaml/navbar"
        x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        >
    <Grid Name="ContentGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <!--Comment NavBar to see dynamic control in UI Automation tree-->
        <dxn:NavBarControl Name="asdasd">
            <dxn:NavBarControl.Groups>
                <dxn:NavBarGroup Header="asdasdasdasd" />
            </dxn:NavBarControl.Groups>
        </dxn:NavBarControl>
        <TextBox Grid.Column="1" Name="Statictb" Text="static is visible in ui automation tree" />
        <Button Grid.Row="1" Content="Create controls" Height="25"  Click="Button_Click"/>
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        TextBox tb = new TextBox();
        Grid.SetRow(tb, 1);
        Grid.SetColumn(tb, 1);
        tb.Text = "dynamic is not visible, if NavBar here...";
        ContentGrid.Children.Add(tb);
    }
}

Edit

According to the DevExpress answer on their support site:

After a peer is created, listening of automation events may cause performance issues. We have decided to clear invocation lists of automation events to resolve it. In your specific situation, you need to disabling clearing. To do it, please set the static DevExpress.Xpf.Core.ClearAutomationEventsHelper.IsEnabled property to False in the Window constructor.

This solve the problem.

Problem

We are using the prism and WPF to build application. Recently we started using UI Automation (UIA) to test our app. But some strange behavior occurred when we run UIA test. Here's simplified shell: ``` <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Name="loadingProgressText" VerticalAlignment="Center" HorizontalAlignment="Center" Text="Loading, please wait..."/> <Border Grid.Row="0" x:Name="MainViewArea"> <Grid> ... </Grid> </Border> <!-- Popup --> <ContentControl x:Name="PopupContentControl" Grid.Row="0" prism:RegionManager.RegionName="PopupRegion" Focusable="False"> </ContentControl> <!-- ErrorPopup --> <ContentControl x:Name="ErrorContentControl" Grid.Row="0" prism:RegionManager.RegionName="ErrorRegion" Focusable="False"> </ContentControl> </Grid> ``` In our app, we use layers (`Popup` and `ErrorPopup`) to hide MainViewArea, to deny access to the controls. To show `Popup`, we use next method: ``` //In constructor of current ViewModel we store _popupRegion instance to the local variable: _popupRegion = _regionManager.Regions["PopupRegion"]; //--- private readonly Stack<UserControl> _popups = new Stack<UserControl>(); public void ShowPopup(UserControl popup) { _popups.Push(popup); _popupRegion.Add(PopupView); _popupRegion.Activate(PopupView); } public UserControl PopupView { get { if (_popups.Any()) return _popups.Peek(); return null; } } ``` Similar to this, we show `ErrorPopup` over all elements of our application: ``` // In constructor we store _errorRegion: _errorRegion = _regionManager.Regions["ErrorRegion"] // --- private UserControl _error_popup; public void ShowError(UserControl popup) { if (_error_popup == null) { _error_popup = popup; _errorRegion.Add(_error_popup); _errorRegion.Activate(_error_popup); } } ``` Mistics... When we run it as users do it (double click on app icon), we can see both custom controls (using `AutomationElement.FindFirst` method, or through Visual UI Automation Verify). But when we start it using UI Automation test - `ErrorPopup` disapears from the tree of the controls. We trying to start the application like this: ``` System.Diagnostics.Process.Start(pathToExeFile); ``` I think that we missed something. But what? Edit #1 As @chrismead said, we tried to run our app with `UseShellExecute` flag set to true, but this does not help. But if we start app from cmd line, and manually click the button, `Popup` and `ErrorPopup` are visible in automation controls tree. ``` Thread appThread = new Thread(delegate() { _userAppProcess = new Process(); _userAppProcess.StartInfo.FileName = pathToExeFile; _userAppProcess.StartInfo.WorkingDirectory = System.IO.Directory.GetCurrentDirectory(); _userAppProcess.StartInfo.UseShellExecute = true; _userAppProcess.Start(); }); appThread.SetApartmentState(ApartmentState.STA); appThread.Start(); ``` One of our suggestion is when we use method `FindAll` or `FindFirst` to search the button to click, window somehow cached its UI Automation state, and does not update it. Edit #2 We have find, that extension method of prism library `IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView))` have some strange behavior. If we stopped use it, this solve our problem particulary. Now we able to see ErrorView and any kind of view in `PopupContentControl`, and application updates UIA elements tree structure. But this is not an answer - "Just stop use this feature"! In `MainViewArea` we have a `ContentControl`, which updates it content depending on user actions, and we are able to see only the first loaded `UserControl` to that `ContentControl.Content` property. This is performed like this: ``` IRegionManager regionManager = Container.Resolve<IRegionManager>(); regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri); ``` And if we change the view, no updates will performed in UI Automation tree - the first loaded view will be in it instead. But visually we observe another `View`, and WPFInspector shows it properly (its show not a UI Automation tree), but Inspect.exe - not. Also our suggestion that window use some kind of caching is wrong - caching in UI Automation client we have to turn on explicitly, but we don't do it.

Original source

Related problems