ContentControl nie jest widoczny, gdy aplikacja uruchamia się za pomocą testu automatyzacji interfejsu użytkownika, ale jest widoczna, gdy aplikacja uruchamia użytkownika

Używamy pryzmatu i WPF do budowania aplikacji. Niedawno zaczęliśmy używać UI Automation (UIA) do testowania naszej aplikacji. Ale niektóre dziwne zachowania wystąpiły podczas uruchamiania testu UIA. Oto uproszczona powłoka:

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

W naszej aplikacji używamy warstw (Popup iErrorPopup) ukryćMainViewArea, odmówić dostępu do kontroli. PokazywaćPopup, używamy następnej metody:

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

Podobne do tego, pokazujemyErrorPopup nad wszystkimi elementami naszej aplikacji:

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

Logistyka ...

Gdy uruchamiamy go jako użytkownicy (podwójnie kliknij ikonę aplikacji), możemy zobaczyć oba niestandardowe elementy sterujące (za pomocąAutomationElement.FindFirst metoda lub przezVisual UI Automation Verify). Ale kiedy zaczynamy za pomocą testu automatyzacji interfejsu użytkownika -ErrorPopup znika z drzewa kontrolek. Próbujemy uruchomić aplikację w ten sposób:

System.Diagnostics.Process.Start(pathToExeFile);

Myślę, że coś przeoczyliśmy. Ale co?

Edytuj # 1

Jak powiedział @chrismead, próbowaliśmy uruchomić naszą aplikację za pomocąUseShellExecute flaga ustawiona na true, ale to nie pomaga. Ale jeśli zaczniemy aplikację odcmd i ręcznie kliknij przycisk,Popup iErrorPopup są widoczne w drzewie kontroli automatyki.

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

Jedną z naszych sugestii jest użycie metodyFindAll lubFindFirst aby przeszukać przycisk, aby kliknąć, okno w jakiś sposób buforowało stan automatyzacji interfejsu użytkownika i nie aktualizuje go.

Edytuj # 2 Znaleźliśmy tę metodę rozszerzenia biblioteki pryzmatówIRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView)) mieć jakieś dziwne zachowanie. Jeśli przestaniemy go używać, rozwiąże to nasz problem szczególnie. Teraz możemy zobaczyć ErrorView i dowolny widok wPopupContentControli aplikacja aktualizuje strukturę drzewa elementów UIA. Ale to nie jest odpowiedź - „Po prostu przestań korzystać z tej funkcji”!

WMainViewArea mamyContentControl, która aktualizuje zawartość w zależności od działań użytkownika, i widzimy tylko pierwszy załadowanyUserControl do tegoContentControl.Content własność. Jest to wykonywane w następujący sposób:

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

A jeśli zmienimy widok, żadne aktualizacje nie zostaną wykonane w drzewie automatyzacji interfejsu użytkownika - zamiast tego pojawi się pierwszy załadowany widok. Ale wizualnie obserwujemy innegoView, iWPFInspector pokazuje go poprawnie (nie pokazuje drzewa automatyzacji interfejsu użytkownika), ale Inspect.exe - nie.

Również nasza sugestia, że ​​okno używa pewnego rodzaju buforowania jest niewłaściwa - buforowanie w kliencie automatyzacji interfejsu użytkownika musimy włączyć jawnie, ale tego nie robimy.

questionAnswers(3)

yourAnswerToTheQuestion