我有一个窗口,它托管各种UserControl的页面。是否可以关闭用户控件的数据上下文中没有引用的窗口?简化细节:
设置窗口
public SetupWindow()
{
InitializeComponent();
Switcher.SetupWindow = this;
Switcher.Switch(new SetupStart());
}
public void Navigate(UserControl nextPage)
{
this.Content = nextPage;
}
设置启动用户控件
<UserControl x:Class="...">
<UserControl.DataContext>
<local:SetupStartViewModel/>
</UserControl.DataContext>
<Grid>
<Button Content="Continue" Command="{Binding ContinueCommand}"/>
</Grid>
</UserControl>
设置开始视图模型
public SetupStartViewModel()
{
}
private bool canContinueCommandExecute() { return true; }
private void continueCommandExectue()
{
Switcher.Switch(new SetupFinish());
}
public ICommand ContinueCommand
{
get { return new RelayCommand(continueCommandExectue, canContinueCommandExecute); }
}
我设法从这里的答案中找到了一个解决方案: 如何将关闭命令绑定到按钮
视图模型:
public ICommand CloseCommand
{
get { return new RelayCommand<object>((o) => ((Window)o).Close(), (o) => true); }
}
视图:
<Button Command="{Binding CloseCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Content="Close"/>
我通过在 ViewModel 中设置一个 RequestClose
事件来实现这一点,当它希望关闭视图时,它可以引发该事件。
然后,通过创建窗口的代码将其挂接到窗口的Close()
命令。
var window = new Window();
var viewModel = new MyViewModel();
window.Content = viewModel;
viewModel.RequestClose += window.Close;
window.Show()
这样,与窗口创建有关的所有事情都在一个地方处理。视图和视图模型都不知道窗口。
在用户控件中,可以找到对窗口的引用,该窗口使用 Window 类上的静态方法承载它。
var targetWindow = Window.GetWindow(this);
targetWindow.Close();
编辑:
如果您没有引用正在使用数据上下文的用户控件,那么您没有大量的选择,如果只有 1 个应用程序窗口,您可以侥幸逃脱
Application.Current.MainWindow.Close()
如果您的应用程序中有很多窗口,并且您要关闭的窗口是焦点,则可以找到类似
public Window GetFocusWindow()
{
Window results = null;
for (int i = 0; i < Application.Current.Windows.Count; i ++)
if (Application.Current.Windows[i].IsFocused)
{
results = Application.Current.Windows[i];
break;
}
return results;
}
最后,我想(尽管这很好)您可以遍历应用程序窗口类,检查可视化树中每个对象的数据上下文,直到找到所需的引用,窗口可以从那里关闭。