프리즘과 WPF를 사용하여 응용 프로그램을 작성합니다. 최근 우리는 UI 자동화 (UIA)를 사용하여 앱을 테스트하기 시작했습니다. 그러나 UIA 테스트를 실행할 때 이상한 행동이 발생했습니다. 여기에 단순화 된 것 쉘 : 우리의 응용 프로그램에서ContentControl은 UI Automation 테스트를 통해 응용 프로그램이 시작될 때 보이지 않지만 응용 프로그램이 사용자에 의해 시작될 때 표시됩니다
<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>
, 우리는 컨트롤에 대한 액세스를 거부, MainViewArea을 숨길 층 (Popup
및 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
을 : 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
을 보여 사용자가 (앱 아이콘을 두 번 클릭하면) 사용자 정의 컨트롤 (AutomationElement.FindFirst
메소드 또는 Visual UI Automation Verify을 사용)을 볼 수 있습니다. 그러나 UI 자동화 테스트를 사용하여 시작할 때 - ErrorPopup
은 컨트롤 트리에서 사라집니다. 다음과 같이 애플리케이션을 시작하려고합니다 :
System.Diagnostics.Process.Start(pathToExeFile);
뭔가를 놓친 것 같습니다. 근데 뭐? @chrismead 말했듯이
편집 # 1
, 우리는 true로 설정 UseShellExecute
플래그와 함께 우리의 응용 프로그램을 실행하려고했으나이 도움이되지 않습니다. 그러나 cmd 행에서 앱을 시작하고 버튼을 수동으로 클릭하면 Popup
및 ErrorPopup
이 자동화 컨트롤 트리에 표시됩니다. 우리가 클릭 버튼을 검색하는 방법 FindAll
또는 FindFirst
를 사용할 때 우리의 제안의
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();
하나는, 윈도우는 어떻게 든 자사의 UI 자동화 상태를 캐시하고 업데이트하지 않습니다.
우리가 발견 한 편집 # 2 는, 프리즘 라이브러리 IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView))
의 확장 방법은 몇 가지 이상한 행동을합니다. 우리가 그것을 사용을 중단하면, 이것은 우리의 문제를 해결합니다. 이제 우리는 PopupContentControl
에서 ErrorView 및 모든 종류의보기를 볼 수 있었고 응용 프로그램은 UIA 요소 트리 구조를 업데이트했습니다. 그러나 이것은 대답이 아닙니다. "그냥이 기능 사용을 중지하십시오!" MainViewArea
에서
우리는 사용자의 행동에 따라 컨텐츠를 업데이트하는 ContentControl
을 가지고 있고, 우리는 첫 번째가 ContentControl.Content
속성에 UserControl
로드 만 볼 수 있습니다.
IRegionManager regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri);
을 우리가보기를 변경하는 경우에는 업데이트는 UI 자동화 트리에 수행되지 않습니다 - 최초의로드 뷰는 대신에있을 것입니다 : 이것은 다음과 같이 수행한다. 그러나 시각적으로 우리는 또 다른 View
을 관찰하고 WPFInspector은 제대로 표시합니다 (UI 자동화 트리가 아닌). 그러나 Inspect.exe는 그렇지 않습니다.
또한 윈도우가 일종의 캐싱을 사용한다는 제안은 잘못되었습니다. 우리는 명시 적으로 켜야하는 UI 자동화 클라이언트에서 캐싱을하지만 캐싱하지는 않습니다.
그렇다면 응용 프로그램을 두 번 클릭하면 컨트롤이 트리에 있지만 Process.Start는 실행되지 않습니다. – chrismead
예, 맞습니다. 그러나 우리는 코드에서 앱을 시작하는 3 가지 방법을 시도했습니다. 아무도 올바른 솔루션을 얻지 못했습니다 ... – stukselbax
cmd 창에서 앱을 시작하려 했습니까? 그런 다음 ProcessStartInfo.UseShellExecute 플래그를 사용하면 작동합니다. – chrismead