Stiamo utilizzando il prisma e WPF per creare un'applicazione. Recentemente abbiamo iniziato a utilizzare UI Automation (UIA) per testare la nostra app. Ma qualche strano comportamento si è verificato durante l'esecuzione del test UIA. shell Ecco semplificata:ContentControl non è visibile all'avvio dell'applicazione tramite test di automazione interfaccia utente, ma è visibile all'avvio dell'applicazione da parte dell'utente
<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>
Nella nostra applicazione, usiamo strati (Popup
e ErrorPopup
) per nascondere MainViewArea, per negare l'accesso ai comandi. Per mostrare Popup
, usiamo metodo successivo:
//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;
}
}
Simile a questo, mostriamo ErrorPopup
su tutti gli elementi della nostra applicazione:
// 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);
}
}
mistici ...
Quando corriamo come fanno gli utenti (doppio clic sull'icona dell'app), possiamo vedere entrambi i controlli personalizzati (utilizzando il metodo AutomationElement.FindFirst
o tramite Visual UI Automation Verify). Ma quando lo iniziamo usando il test di automazione dell'interfaccia utente - ErrorPopup
scompare dall'albero dei controlli. Stiamo cercando di avviare l'applicazione in questo modo:
System.Diagnostics.Process.Start(pathToExeFile);
Penso che ci siamo persi qualcosa. Ma cosa?
Modifica # 1
Come ha detto @chrismead, abbiamo cercato di eseguire la nostra applicazione con UseShellExecute
bandiera impostato su true, ma questo non aiuta. Ma se iniziamo l'app dalla riga cmd e facciamo clic manualmente sul pulsante, Popup
e ErrorPopup
sono visibili nella struttura dei controlli di automazione.
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();
Uno dei nostro suggerimento è quando usiamo il metodo FindAll
o FindFirst
per cercare il pulsante per fare clic, la finestra in qualche modo il suo stato memorizzato nella cache di automazione interfaccia utente, e non aggiorna esso.
Modifica # 2 Abbiamo trovare, che metodo di estensione della biblioteca prisma IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView))
hanno una qualche strano comportamento. Se smettiamo di usarlo, questo risolve il nostro problema in particolare. Ora siamo in grado di vedere ErrorView e qualsiasi tipo di vista in PopupContentControl
e la struttura ad albero degli elementi UIA degli aggiornamenti dell'applicazione. Ma questa non è una risposta - "Basta smettere di usare questa funzione"!
In MainViewArea
abbiamo un ContentControl
, che aggiorna i contenuti a seconda delle azioni degli utenti, e noi siamo in grado di vedere solo il primo caricato UserControl
a quella ContentControl.Content
proprietà. Questa operazione viene eseguita in questo modo:
IRegionManager regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri);
E se cambiamo la vista, nessun aggiornamento sarà eseguita in albero UI Automation - la prima vista caricata sarà in esso, invece. Ma visivamente osserviamo un altro e WPFInspector lo mostra correttamente (il suo show non è un albero di automazione dell'interfaccia utente), ma Inspect.exe - non.
Anche la nostra ipotesi che la finestra utilizzare una sorta di caching è sbagliato - caching nel client di automazione interfaccia utente dobbiamo attivare in modo esplicito, ma noi non lo facciamo.
Quindi, è corretto dire che un semplice doppio clic sull'avvio dell'app determina che il controllo si trova nell'albero, ma un avvio Process.Start no? – chrismead
Sì, è corretto. Ma abbiamo provato 3 modi per avviare l'app dal codice: nessuno ci porta alla soluzione giusta ... – stukselbax
Hai provato a lanciare l'app da una finestra di cmd? Se funziona, utilizzare il flag ProcessStartInfo.UseShellExecute potrebbe funzionare. – chrismead