在 WPF 应用程序中,通过 ViewModel 来关闭 View(窗口)是一种常见的需求,特别是在实现 MVVM(Model-View-ViewModel)模式时。实现这一目标的方法有多种,但最常见和优雅的方式是使用命令和事件,结合依赖注入或服务提供机制。以下是具体步骤:
1. 定义一个接口来关闭窗口
首先,定义一个接口 IWindowService
,用于关闭窗口。
public interface IWindowService
{
void Close();
}
2. 实现该接口的具体类
接下来,实现这个接口。具体类 WindowService
可以持有一个对窗口的引用,并在需要时关闭窗口。
public class WindowService : IWindowService
{
private readonly Window _window;
public WindowService(Window window)
{
_window = window;
}
public void Close()
{
_window.Close();
}
}
3. 在 ViewModel 中使用该服务
在 ViewModel 中使用依赖注入的方式注入 IWindowService
,并在需要关闭窗口的地方调用它的 Close
方法。
public class MyViewModel
{
private readonly IWindowService _windowService;
public MyViewModel(IWindowService windowService)
{
_windowService = windowService;
CloseCommand = new RelayCommand(CloseWindow);
}
public ICommand CloseCommand { get; }
private void CloseWindow()
{
_windowService.Close();
}
}
4. 定义 RelayCommand
类
定义一个 RelayCommand
类,它实现了 ICommand
接口,用于处理命令的执行逻辑。
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
}
5. 在 View 中设置 DataContext 并绑定命令
在窗口的代码隐藏文件(.xaml.cs)中,创建 ViewModel 实例,并将窗口传递给 WindowService
。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var windowService = new WindowService(this);
var viewModel = new MyViewModel(windowService);
this.DataContext = viewModel;
}
}
在 XAML 中绑定 CloseCommand
到按钮的 Command
属性。
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Close Window" Command="{Binding CloseCommand}" Width="150" Height="50" />
</Grid>
</Window>