Chúng tôi đang sử dụng lăng kính và WPF để xây dựng ứng dụng. Gần đây, chúng tôi đã bắt đầu sử dụng Giao diện người dùng Tự động hóa (UIA) để thử nghiệm ứng dụng của chúng tôi. Nhưng một số hành vi lạ xảy ra khi chúng tôi chạy thử nghiệm UIA. vỏ Dưới đây là đơn giản:ContentControl không hiển thị khi ứng dụng bắt đầu qua kiểm tra Tự động hóa giao diện người dùng, nhưng hiển thị khi ứng dụng bắt đầu bằng người dùng
<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>
Trong ứng dụng của chúng tôi, chúng tôi sử dụng các lớp (Popup
và ErrorPopup
) để ẩn MainViewArea, để từ chối quyền truy cập vào các điều khiển. Để hiển thị Popup
, chúng tôi sử dụng phương pháp tiếp theo:
//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;
}
}
Tương tự như này, chúng tôi hiển thị ErrorPopup
khắp các yếu tố của ứng dụng của chúng tôi:
// 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 ...
Khi chúng tôi chạy khi người dùng làm điều đó (nhấp đúp vào biểu tượng ứng dụng), chúng tôi có thể thấy cả hai điều khiển tùy chỉnh (sử dụng phương thức AutomationElement.FindFirst
hoặc thông qua Visual UI Automation Verify). Nhưng khi chúng tôi bắt đầu nó bằng cách sử dụng kiểm tra tự động hóa giao diện người dùng - ErrorPopup
disapears từ cây điều khiển. Chúng tôi đang cố gắng bắt đầu ứng dụng như thế này:
System.Diagnostics.Process.Start(pathToExeFile);
Tôi nghĩ rằng chúng tôi đã bỏ lỡ điều gì đó. Nhưng cái gì?
Chỉnh sửa # 1
Như @chrismead nói, chúng tôi đã cố gắng để chạy ứng dụng của chúng tôi với UseShellExecute
cờ thiết lập là true, nhưng điều này không giúp đỡ. Nhưng nếu chúng ta bắt đầu ứng dụng từ cmd dòng và nhấp vào nút thủ công, Popup
và ErrorPopup
hiển thị trong cây điều khiển tự động.
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();
Một trong những gợi ý của chúng tôi là khi chúng ta sử dụng phương pháp FindAll
hoặc FindFirst
để tìm kiếm trên nút bấm, cửa sổ bằng cách nào đó được lưu trữ nhà nước UI Automation của nó, và không cập nhật nó.
Chỉnh sửa # 2 Chúng tôi đã tìm thấy, phương pháp mở rộng của thư viện lăng kính IRegionManager.RegisterViewWithRegion(RegionNames.OurRegion, typeof(Views.OurView))
có một số hành vi lạ. Nếu chúng ta ngừng sử dụng nó, điều này giải quyết vấn đề của chúng ta. Bây giờ chúng ta có thể thấy ErrorView và bất kỳ dạng xem nào trong PopupContentControl
và ứng dụng cập nhật cấu trúc cây phần tử UIA. Nhưng đây không phải là câu trả lời - "Chỉ cần ngừng sử dụng tính năng này"!
Trong MainViewArea
chúng tôi có một ContentControl
, cập nhật nội dung nó tùy thuộc vào hành động của người dùng, và chúng tôi có thể chỉ nhìn thấy đầu tiên nạp UserControl
đó ContentControl.Content
tài sản. Điều này được thực hiện như sau:
IRegionManager regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate(RegionNames.MainContentRegion, this.Uri);
Và nếu chúng ta thay đổi chế độ xem, sẽ không có cập nhật nào được thực hiện trong cây Tự động hóa giao diện người dùng. Nhưng trực quan, chúng tôi quan sát một số khác View
và WPFInspector hiển thị chính xác (chương trình của nó không phải là cây Tự động hóa giao diện người dùng), nhưng Inspect.exe - không.Ngoài ra gợi ý của chúng tôi rằng cửa sổ sử dụng một số loại bộ nhớ đệm là sai - bộ nhớ đệm trong khách hàng tự động hóa giao diện người dùng, chúng tôi phải bật một cách rõ ràng, nhưng chúng tôi không làm điều đó.
Vì vậy, có chính xác khi nói rằng việc khởi chạy nhấp đúp đơn giản của kết quả ứng dụng trong điều khiển nằm trong cây, nhưng khởi chạy Process.Start không? – chrismead
Vâng, đúng. Nhưng chúng tôi đã thử 3 cách để bắt đầu ứng dụng từ mã - không ai đưa chúng ta đến giải pháp đúng ... – stukselbax
Bạn đã thử khởi chạy ứng dụng từ cửa sổ cmd chưa? Nếu nó hoạt động thì sử dụng cờ ProcessStartInfo.UseShellExecute có thể hoạt động. – chrismead