ContentControl ist nicht sichtbar, wenn die Anwendung über den UI-Automatisierungstest gestartet wird. Es ist jedoch sichtbar, wenn die Anwendung vom Benutzer gestartet wird

Wir verwenden das Prisma und WPF, um Anwendungen zu erstellen. Vor kurzem haben wir begonnen, UI Automation (UIA) zum Testen unserer App zu verwenden. Beim Ausführen des UIA-Tests ist jedoch ein merkwürdiges Verhalten aufgetreten. Hier ist die vereinfachte 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 unserer App verwenden wir Ebenen (Popup undErrorPopup) versteckenMainViewArea, um den Zugriff auf die Steuerelemente zu verweigern. ZeigenPopupverwenden wir folgende Methode:

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

Ähnlich zeigen wirErrorPopup über alle Elemente unserer Anwendung:

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

Wenn wir es als Benutzer ausführen (Doppelklick auf das App-Symbol), sehen wir beide benutzerdefinierten Steuerelemente (mitAutomationElement.FindFirst Methode oder durchVisual UI Automation Verify). Aber wenn wir es mit UI Automation Test starten -ErrorPopup verschwindet aus dem Baum der Steuerelemente. Wir versuchen die Anwendung so zu starten:

System.Diagnostics.Process.Start(pathToExeFile);

Ich denke, dass wir etwas verpasst haben. Aber was?

Bearbeiten Sie # 1

Wie @chrismead sagte, haben wir versucht, unsere App mit auszuführenUseShellExecute flag auf true gesetzt, aber das hilft nicht. Aber wenn wir von App startencmd Linie, und klicken Sie manuell auf die Schaltfläche,Popup undErrorPopup sind im Automatisierungssteuerungsbaum sichtbar.

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

Einer unserer Vorschläge ist, wann wir die Methode anwendenFindAll oderFindFirst Um die Schaltfläche zum Klicken zu durchsuchen, hat window den UI-Automatisierungsstatus zwischengespeichert und aktualisiert ihn nicht.

Bearbeiten Sie # 2 Wir haben diese Erweiterungsmethode der Prismenbibliothek gefundenIRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView)) habe ein seltsames Verhalten. Wenn wir es nicht mehr benutzen, löst dies unser Problem. Jetzt können wir ErrorView und jede Art von Ansicht in sehenPopupContentControlund Anwendungsaktualisierungen UIA-Elementbaumstruktur. Dies ist jedoch keine Antwort - "Hören Sie einfach auf, diese Funktion zu verwenden"!

ImMainViewArea wir haben einContentControl, wodurch der Inhalt abhängig von den Benutzeraktionen aktualisiert wird und wir nur den ersten geladenen sehen könnenUserControl dazuContentControl.Content Eigentum. Dies wird folgendermaßen durchgeführt:

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

Wenn wir die Ansicht ändern, werden in der UI-Automatisierungsstruktur keine Aktualisierungen durchgeführt. Stattdessen wird die erste geladene Ansicht darin gespeichert. Aber visuell beobachten wir einen anderenView, undWPFInspector zeigt es richtig (es zeigt keinen UI-Automatisierungsbaum), aber Inspect.exe - nicht.

Auch unser Vorschlag, dass Fenster eine Art Caching verwenden, ist falsch - das Caching im UI Automation-Client müssen wir explizit aktivieren, aber wir tun es nicht.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage