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 wPopupContentControl
i 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.