WPF:以符合MVVM规范的方式从ViewModel关闭窗口
在VM-first模式下从ViewModel关闭窗口的MVVM合规方案
核心思路
通过定义视图无关的接口让ViewModel发出关闭请求,由WindowService负责监听并执行窗口关闭操作,完全遵循MVVM的解耦原则,ViewModel无需依赖任何WPF视图层类型。
具体实现步骤
1. 定义关闭请求接口
创建通用接口标记需要触发窗口关闭的ViewModel:
namespace DevPortal.Interfaces { public interface ICloseableViewModel { // 触发关闭请求的事件 event EventHandler RequestClose; } }
2. 让ViewModel实现接口并触发关闭请求
在EditTicketViewModel中实现接口,在业务逻辑完成后(比如保存操作)触发关闭事件:
public class EditTicketViewModel : ViewModelBase, ICloseableViewModel { // 实现接口的事件 public event EventHandler RequestClose; [RelayCommand] private void SaveAndClose() { // 执行保存等业务逻辑... // 触发窗口关闭请求 RequestClose?.Invoke(this, EventArgs.Empty); } // 其他ViewModel逻辑... }
3. 修改WindowService监听关闭请求
更新WindowService,在创建窗口时检查ViewModel是否实现了ICloseableViewModel,订阅事件并处理窗口关闭:
public void ShowWindow(object viewModel, bool showDialog) { var window = new ChromelessWindow(); window.ResizeMode = ResizeMode.NoResize; SfSkinManager.SetTheme(window, new Theme("FluentDark")); window.Content = viewModel; window.SizeToContent = SizeToContent.WidthAndHeight; window.Title = viewModel.GetType().GetProperty("Title").GetValue(viewModel).ToString(); window.ShowIcon = false; // 监听ViewModel的关闭请求 if (viewModel is ICloseableViewModel closeableVm) { void OnRequestClose(object sender, EventArgs e) { window.Close(); // 取消订阅避免内存泄漏 closeableVm.RequestClose -= OnRequestClose; } closeableVm.RequestClose += OnRequestClose; // 窗口关闭时再次取消订阅,双重保障 window.Closed += (s, e) => closeableVm.RequestClose -= OnRequestClose; } if (showDialog) { window.ShowDialog(); } else { window.Show(); } }
方案优势
- 严格遵循MVVM:ViewModel仅负责业务逻辑和发出请求,不依赖任何WPF视图组件,可独立测试、复用。
- 职责清晰:窗口关闭的具体操作由WindowService统一处理,视图层与ViewModel层完全解耦。
- 避免内存泄漏:通过双重取消订阅逻辑,防止ViewModel与窗口的引用残留导致内存泄漏。
内容的提问来源于stack exchange,提问作者f.lechleitner
相关产品推荐
相关产品推荐

