ViewModel 到 ViewModel 的通信通常由事件聚合器模式的实现来处理。
MVVM Light 使用 Messenger
类,Prism 有另一种实现方式,但基本上这是一种在 View Model 之间发送消息而不耦合的方法。
有一些示例和 文章 描述了使用方法。我建议你去看一下。
关于 WPF 中的控制器问题,我不清楚。
关于示例:
- 我有一个带有其 WindowsViewModel 的窗口。这个类应该有一个绑定到按钮的命令。
- 用户点击按钮。执行命令。
- 命令打开一个新窗口。
在这里,你应该创建对话框视图模型,并以某种方式创建窗口。或者用 ViewModel 创建窗口,但 ViewModel 不应该过多地了解 View,否则就无法进行测试。
我们使用类似这样的东西,因为我们有一些要求,但它可以更简单,恰好这是我手头唯一的示例:
bool? ShowDialogImpl<TViewModel>(Action<TViewModel> setup) where TViewModel : ViewModel
{
return (bool?)DispatcherHelper.UIDispatcher.Invoke(
(Func<bool?>)(() =>
{
var viewModel = viewModelFactory.Get<TViewModel>();
viewModel.ViewService = this;
setup(viewModel);
var window = new Window
{
Owner = this,
SizeToContent = SizeToContent.WidthAndHeight,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Content = ViewFactory.CreateView<TViewModel>(),
DataContext = viewModel,
WindowStyle = WindowStyle.ToolWindow,
ShowInTaskbar = false
};
window.SetBinding(TitleProperty, new Binding("Title"));
openDialogs.Push(window);
window.Activated += (sender, args) => window.SizeToContent = SizeToContent.Manual;
var result = window.ShowDialog();
openDialogs.Pop();
viewModelFactory.Release(viewModel);
return result;
}));
}
基本上:我们创建一个窗口和一个视图模型。
视图模型是使用容器从工厂创建的。
设置操作委托是我们数据的入口点。
第一个窗口是网格,第二个对话框用于编辑网格数据。
在窗口中,我们有:
messenger.Register<EntityUpdated<FooClass>>(this, message => UpdateItem(message.Entity));
在对话框中:
messenger.Send(new EntityUpdated<FooClass>(subject));
这样,我们就知道在编辑对话框中更新了什么内容,以便刷新网格。
希望这能帮到你 :)