WPF ViewModel打开窗体方法总结

在WPF的MVVM模式中,ViewModel不应直接操作视图(如窗体),以保持关注点分离。以下是几种推荐方法:

方法1:使用消息传递(推荐)

步骤:

  1. 安装NuGet包:CommunityToolkit.Mvvm
  2. 在ViewModel中发送消息:
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.ComponentModel;

public class MyViewModel : ObservableObject
{
    public void OpenNewWindow()
    {
        // 发送打开窗口的消息(可包含参数)
        WeakReferenceMessenger.Default.Send(new OpenWindowMessage());
    }
}

// 自定义消息类
public sealed class OpenWindowMessage { }
  1. 在视图层(如主窗口)接收消息:
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        // 注册消息处理器
        WeakReferenceMessenger.Default.Register<OpenWindowMessage>(this, (r, m) =>
        {
            var newWindow = new TargetWindow(); // 你的目标窗体
            newWindow.Show();
            // 或 newWindow.ShowDialog();
        });
    }
}

方法2:通过服务抽象(依赖注入)

步骤:

  1. 定义窗口服务接口:
public interface IWindowService
{
    void ShowWindow<T>() where T : Window, new();
}
  1. 实现服务:
public class WindowService : IWindowService
{
    public void ShowWindow<T>() where T : Window, new()
    {
        var window = new T();
        window.Show();
    }
}
  1. 在ViewModel中使用服务:
public class MyViewModel
{
    private readonly IWindowService _windowService;

    // 通过构造函数注入
    public MyViewModel(IWindowService windowService)
    {
        _windowService = windowService;
    }

    public void OpenTargetWindow()
    {
        _windowService.ShowWindow<TargetWindow>();
    }
}
  1. 注册服务(在App.xaml.cs):
protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    
    var services = new ServiceCollection();
    services.AddSingleton<IWindowService, WindowService>();
    services.AddTransient<MyViewModel>();
    
    var provider = services.BuildServiceProvider();
    
    var mainWindow = new MainWindow
    {
        DataContext = provider.GetRequiredService<MyViewModel>()
    };
    mainWindow.Show();
}

方法3:事件聚合器(Prism库)

若使用Prism框架:

// 1. 发布事件
public class MyViewModel
{
    private readonly IEventAggregator _eventAggregator;

    public MyViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void RaiseOpenEvent()
    {
        _eventAggregator.GetEvent<OpenWindowEvent>().Publish();
    }
}

// 2. 订阅事件(在需要响应的地方)
_eventAggregator.GetEvent<OpenWindowEvent>().Subscribe(() => 
{
    new TargetWindow().Show();
});

⚠️ 避免直接操作视图

不推荐的做法(破坏MVVM):

// ViewModel中直接创建窗口 - 避免!
new TargetWindow().Show(); 

总结

方法 优点 适用场景
消息传递 低耦合,无需依赖注入 简单通信,CommunityToolkit用户
窗口服务 高可测试性,明确依赖 需要依赖注入的项目
Prism事件聚合 企业级解决方案,功能强大 使用Prism框架的大型应用

选择合适的方法保持ViewModel的纯洁性,确保视图逻辑由视图层处理。

posted on 2025-06-28 18:45  平凡码农  阅读(107)  评论(0)    收藏  举报