[英]Using WPF/MVVM, how do I immediately restore focus to my application after closing extnernal process?
I have a full screen WPF application that launches external processes when the user selects an item from a listbox. 我有一个全屏WPF应用程序,当用户从列表框中选择一个项目时,该应用程序将启动外部进程。 Navigation with the listbox is done primarily with the keyboard and not the mouse.
使用列表框的导航主要通过键盘而不是鼠标完成。 What is the cleanest way to immediately return focus to the listbox once the user closes the external app?
用户关闭外部应用程序后立即将焦点立即返回到列表框的最干净的方法是什么? I've got it working, but the solution is not ideal as far as I'm concerned and is a bit "hacky".
我已经开始工作了,但是就我而言,该解决方案并不理想,有点“棘手”。
Here's the XAML: 这是XAML:
<ListBox SelectedIndex="{Binding ActiveSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True" x:Name="ListBoxSelector">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
And the code: 和代码:
private void Button_Click(object sender, RoutedEventArgs e)
{
var process = Process.Start(@"C:\Windows\system32\mspaint.exe");
process.WaitOnExit()
ActiveSelection += 1;
ActiveSelection -= 1;
}
So basically changing the ActiveSelection (and then back again so the same thing is still selected) seems to focus the listbox instantly once the MSPaint program closes. 因此,基本上更改ActiveSelection(然后再次返回,以便仍然选择相同的内容)似乎在MSPaint程序关闭后立即将列表框聚焦。 So I've achieved the desired outcome, but I think there's probably a better and cleaner solution.
因此,我已经达到了预期的结果,但是我认为可能存在更好,更清洁的解决方案。
Focus is a view concern. 关注是关注的焦点。
So a direct approach would be to have whatever model/service your Process.Start
is raise an event when the process exits, have the VM pick that up and raise an event in turn, and finally have the view react by setting the focus. 因此,一种直接的方法是让您的
Process.Start
具有任何模型/服务,即在流程退出时引发一个事件,让VM进行处理并依次引发一个事件,最后通过设置焦点使视图做出反应。
Alternatively, the VM could set a property say CurrentlyInExternalApplication
that when set to false by the aforementioned event would cause a trigger (similar to your existing one) to fire. 另外,VM可以设置一个属性“
CurrentlyInExternalApplication
,当上述事件将其设置为false时,将触发触发器(类似于您现有的触发器)。
You can try to run child process in a new thread and call process.WaitForExit()
after it is started. 您可以尝试在新线程中运行子进程并在启动后调用
process.WaitForExit()
。 Then, after child process is closed you can make your app focus using Dispatcher
since the current thread is not a UI thread. 然后,在关闭子进程之后,由于当前线程不是UI线程,因此可以使用
Dispatcher
来使应用程序成为焦点。
var process = Process.Start(@"C:\Windows\system32\mspaint.exe");
process.WaitForExit();
Dispatcher.Invoke(() => MainWindow.Current.MakeFocus()); // sample line
Your MainWindow should have a static property Current
and it should be set when your main app is started. 您的MainWindow应该具有静态属性
Current
,并且应在启动主应用程序时进行设置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.