You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM:不使用Prism/MVVM Light,如何向第二个窗口ViewModel传两个参数?

无框架实现跨ViewModel参数传递的几种方案

方案1:构造函数直接传递参数

这是最直观的方式,通过第二个ViewModel的带参构造函数完成参数注入,适合简单的参数传递场景。

步骤:

  1. 为第二个ViewModel定义包含目标参数的构造函数
  2. 在第一个窗口打开第二个窗口前,实例化第二个ViewModel并传入参数
  3. 将实例化后的ViewModel绑定到第二个窗口的DataContext

代码示例:

// 第一个窗口的ViewModel
public class FirstViewModel
{
    public ICommand OpenSecondWindowCommand { get; }

    public FirstViewModel()
    {
        OpenSecondWindowCommand = new RelayCommand(OpenSecondWindow);
    }

    private void OpenSecondWindow()
    {
        // 准备要传递的两个参数
        string param1 = "来自第一个VM的参数1";
        int param2 = 123;

        // 实例化第二个ViewModel并传入参数
        var secondVm = new SecondViewModel(param1, param2);
        var secondWindow = new SecondWindow
        {
            DataContext = secondVm
        };
        secondWindow.Show();
    }
}

// 第二个窗口的ViewModel
public class SecondViewModel
{
    public string ReceivedParam1 { get; }
    public int ReceivedParam2 { get; }

    // 带参构造函数接收参数
    public SecondViewModel(string param1, int param2)
    {
        ReceivedParam1 = param1;
        ReceivedParam2 = param2;
    }
}

// 自定义RelayCommand(不依赖框架需自行实现基础命令)
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool>? _canExecute;

    public event EventHandler? CanExecuteChanged;

    public RelayCommand(Action execute, Func<bool>? canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true;

    public void Execute(object? parameter) => _execute();
}

方案2:使用共享数据容器

通过全局可访问的共享类存储参数,适合需要在多个ViewModel间共享数据的场景。

步骤:

  1. 创建单例模式的共享数据类,定义需要传递的参数属性
  2. 第一个ViewModel将参数赋值给共享类的属性
  3. 第二个ViewModel在初始化时从共享类读取参数

代码示例:

// 共享数据容器(单例模式)
public class SharedDataContainer
{
    private static SharedDataContainer? _instance;
    public static SharedDataContainer Instance => _instance ??= new SharedDataContainer();

    // 私有构造函数确保单例
    private SharedDataContainer() { }

    // 定义要传递的参数
    public string? Param1 { get; set; }
    public int Param2 { get; set; }
}

// 第一个窗口的ViewModel
public class FirstViewModel
{
    public ICommand OpenSecondWindowCommand { get; }

    public FirstViewModel()
    {
        OpenSecondWindowCommand = new RelayCommand(OpenSecondWindow);
    }

    private void OpenSecondWindow()
    {
        // 将参数存入共享容器
        var sharedData = SharedDataContainer.Instance;
        sharedData.Param1 = "共享参数1";
        sharedData.Param2 = 456;

        // 打开第二个窗口
        var secondWindow = new SecondWindow();
        secondWindow.Show();
    }
}

// 第二个窗口的ViewModel
public class SecondViewModel
{
    public string? ReceivedParam1 { get; }
    public int ReceivedParam2 { get; }

    public SecondViewModel()
    {
        // 从共享容器读取参数
        var sharedData = SharedDataContainer.Instance;
        ReceivedParam1 = sharedData.Param1;
        ReceivedParam2 = sharedData.Param2;
    }
}

方案3:通过事件与委托传递

利用C#事件机制,让第一个ViewModel触发事件传递参数,第二个ViewModel订阅事件接收参数,适合松耦合的场景。

步骤:

  1. 在第一个ViewModel中定义带参数的事件
  2. 打开第二个窗口后,让第二个ViewModel订阅该事件
  3. 第一个ViewModel触发事件时传递参数

代码示例:

// 定义事件参数类,包含要传递的参数
public class ParamEventArgs : EventArgs
{
    public string Param1 { get; }
    public int Param2 { get; }

    public ParamEventArgs(string param1, int param2)
    {
        Param1 = param1;
        Param2 = param2;
    }
}

// 第一个窗口的ViewModel
public class FirstViewModel
{
    public ICommand OpenSecondWindowCommand { get; }
    // 定义传递参数的事件
    public event EventHandler<ParamEventArgs>? ParamPassed;

    public FirstViewModel()
    {
        OpenSecondWindowCommand = new RelayCommand(OpenSecondWindow);
    }

    private void OpenSecondWindow()
    {
        var secondVm = new SecondViewModel();
        var secondWindow = new SecondWindow
        {
            DataContext = secondVm
        };

        // 让第二个ViewModel订阅事件
        ParamPassed += secondVm.ReceiveParams;

        secondWindow.Show();

        // 触发事件传递参数
        ParamPassed?.Invoke(this, new ParamEventArgs("事件传递参数1", 789));
    }
}

// 第二个窗口的ViewModel
public class SecondViewModel
{
    public string? ReceivedParam1 { get; private set; }
    public int ReceivedParam2 { get; private set; }

    // 事件处理方法,接收参数
    public void ReceiveParams(object? sender, ParamEventArgs e)
    {
        ReceivedParam1 = e.Param1;
        ReceivedParam2 = e.Param2;
    }
}

注意事项:

  • 方案1属于紧耦合,若后续参数变化需要修改构造函数,适合简单场景
  • 方案2的单例容器要注意线程安全,多线程场景需加锁;同时要避免内存泄漏,不需要时可重置参数
  • 方案3的事件订阅要记得在第二个窗口关闭时取消订阅,防止内存泄漏

内容的提问来源于stack exchange,提问作者Laos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 21:06:15