ContentControl не виден, когда приложение запускается с помощью теста автоматизации пользовательского интерфейса, но он виден, когда приложение запускается пользователем.

Мы используем призму и WPF для создания приложения. Недавно мы начали использовать UI Automation (UIA) для тестирования нашего приложения. Но какое-то странное поведение произошло, когда мы запускаем тест МАУ. Вот упрощенная оболочка:

<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>

В нашем приложении мы используем слои (Popup а такжеErrorPopup) прятатьсяMainViewArea, чтобы запретить доступ к элементам управления. ПоказыватьPopupМы используем следующий метод:

    //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;
        }
    }

Подобно этому, мы показываемErrorPopup по всем элементам нашего приложения:

    // 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...

Когда мы запускаем его так, как это делают пользователи (двойной щелчок по значку приложения), мы видим оба пользовательских элемента управления (используяAutomationElement.FindFirst метод или черезVisual UI Automation Verify). Но когда мы запускаем его с помощью теста автоматизации пользовательского интерфейса -ErrorPopup исчезает из дерева элементов управления. Мы пытаемся запустить приложение так:

System.Diagnostics.Process.Start(pathToExeFile);

Я думаю, что мы что-то упустили. Но что?

Edit #1

Как сказал @chrismead, мы пытались запустить наше приложение сUseShellExecute флаг установлен в true, но это не помогает. Но если мы начнем приложение сcmd линии и вручную нажмите кнопку,Popup а такжеErrorPopup видны в дереве элементов управления автоматизации.

    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();

Одно из наших предложений, когда мы используем методFindAll или жеFindFirst чтобы выполнить поиск по нажатой кнопке, окно как-то кэширует свое состояние автоматизации пользовательского интерфейса и не обновляет его.

Edit #2 Мы нашли, что метод расширения библиотеки призмыIRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView)) есть странное поведение. Если мы перестанем его использовать, это решит нашу проблему в частности. Теперь мы можем видеть ErrorView и любой вид вPopupContentControlи приложение обновляет древовидную структуру элементов МСА. Но это не ответ - "Просто прекратите использовать эту функцию"!

ВMainViewArea у нас естьContentControl, который обновляет его содержимое в зависимости от действий пользователя, и мы можем видеть только первый загруженныйUserControl к этомуContentControl.Content имущество. Это выполняется так:

IRegionManager regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri);

И если мы изменим представление, в дереве автоматизации пользовательского интерфейса обновления не будут выполняться - вместо него появится первое загруженное представление. Но визуально мы наблюдаем другоеView, а такжеWPFInspector показывает это правильно (его показывать не дерево автоматизации пользовательского интерфейса), но Inspect.exe - нет.

Также наше предложение о том, что окно использует какое-то кэширование, неверно - кэширование в клиенте UI Automation мы должны включить явно, но мы этого не делаем.

Ответы на вопрос(3)

Ваш ответ на вопрос