ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

WPF入门到跪下 第九章 MVVM-跨模块交互

2026/9/13 22:12:35 拓冰建站 浏览量
WPF入门到跪下 第九章 MVVM-跨模块交互

MVVM模式下的跨模块交互

在实际开发过程中,经常会遇到多个窗口对象,随之而来的就是对应的多个ViewModel对象,这些对象在一定条件下会发生相互访问的情况,例如VM与不同窗口交互、VM与不同VM交互,这些不同模块对象之间的交互,就是跨模块交互。

MVVM模式下跨模块交互解决方案
面对跨模块交互,常规的解决方案是创建一个“第三方”来作为交互的中转站。

创建一个窗体管理类型,作为第三方

public class WindowManager
{private static Dictionary<string, WinEntity> _windows = new Dictionary<string, WinEntity>();/// <summary>/// 窗体类型注册/// </summary>/// <param name="type"></param>/// <param name="owner"></param>public static void Register(Type type, Window owner){_windows.Add(type.Name, new WinEntity { Type = type,Owner = owner});}//展示对应的窗口public static bool ShowDialog(string winKey, object dataContext){if (_windows.ContainsKey(winKey)){Type type = _windows[winKey].Type;var win = (Window)Activator.CreateInstance(type);//指定所展示的窗口对象的拥有者,设置后子窗口跟主窗口会关联展示win.Owner = _windows[winKey].Owner;//传递上下文参数win.DataContext = dataContext;return win.ShowDialog()==true?true:false;}return false;}
}class WinEntity
{public Type Type { get; set; }public Window Owner { get; set; }
}

主窗口做窗口类型注册

public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();//进行窗体对象类型的注册,后面通过反射获得对应的窗体对象,这里的SecondWindow只是一个简单的显示Hello的窗口WindowManager.Register(typeof(SecondWindow), this);}
}

命令类型创建

public class CommandBase : ICommand
{public event EventHandler CanExecuteChanged;public void DoCanExecuteChanged(){CanExecuteChanged?.Invoke(this, EventArgs.Empty);}public Func<object, bool> DoCanExecute { get; set; }public bool CanExecute(object parameter){return DoCanExecute(parameter);}public Action<object> DoExecute { get; set; }public void Execute(object parameter){DoExecute(parameter);}
}

ViewModel层

public class MainViewModel
{public MainModel MainModel { get; set; }public CommandBase CommandBase { get; set; }public MainViewModel(){CommandBase = new CommandBase{DoExecute = DoExecute,DoCanExecute = DoCanExecute};MainModel = new MainModel();}private void DoExecute(object obj){//创建并设置VM对象,传递给所访问的窗体对象MainViewModel mainViewModel = new MainViewModel();mainViewModel.MainModel.Value = 123;//跨模块调用窗体对象if (WindowManager.ShowDialog("SecondWindow", mainViewModel)){//根据窗口的操作结果来进行不同的业务逻辑}else{}}private bool DoCanExecute(object obj){Debug.WriteLine("DoCanExecute......");return true;}
}

Model层

public class MainModel
{public int Value { get; set; }
}

以上的做法,将对应的窗口类型剥离出来,由WindowManager统一管理,实现各个模块之间的相互隔离。这个方式不仅仅用于ViewModel层访问窗口对象,还能针对不同的跨模块访问情况做出不同的调整。例如跨模块访问方法的ActionManager可以如下编写:

public class MethodManager<T>
{private Dictionary<string, Func<T>> _methods = new Dictionary<string, Func<T>>();public void Register(string name, Func<T> func){_methods.Add(name, func);}public T Invoke(string name){return _methods[name].Invoke();}
}