WPF中MVVM下的父和子视图通信

时间:2015-04-11 18:48:45

标签: c# wpf mvvm caliburn.micro

我一直在努力解决这个问题很长一段时间了。我正在构建我的第一个WPF MVVM应用程序。在这个应用程序中我有一个AppView(与它相对应的viewmodel)。子视图包含在选项卡中,由分离的视图(UserControl)表示,每个视图都有一个视图模型。到现在为止还挺好。

在一个视图中,a有一个客户列表和一个删除按钮。我在viewmodel上也有一个对应命令来实际删除记录,这个工作正常。现在我希望删除按钮创建一个带有两个按钮的新视图,一个用于确认,另一个用于取消,然后如果用户单击"确认"按钮执行删除。

这里的问题是每个视图及其对应的视图模型都与其他视图隔离(只要我理解),所以我无法访问第二个视图视图模型以查看是否单击了确认按钮。

到目前为止,我发现唯一可行的解​​决方案是在一个视图上添加一个事件,并为该事件订阅另一个视图。但是这项技术对于这样一项微不足道的任务来说非常复杂。还有其他选择吗?这两个视图不能共享相同的datacontext或viewmodel吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

var dialog = new DialogViewModel();// could be a DialogService if you wish

再次使用此DialogViewModel或DialogService,您可以选择实际操作方式。

dialog.Result在这种情况下会返回您的确认是真还是假

var settings = new Dictionary<string, object>(); settings["Owner"] = this; settings["WindowStartupLocation"] = WindowStartupLocation.CenterParent; windowManager.ShowDialog(dialog, null, settings);

if(dialog.Result == true) do the delete on the parent viewmodel.

或者您可以使用IEventAggregator和消息包完成所有操作。我亲自使用第一个来做很多事情。有时根据情况组合。

大多数人都喜欢SoC的IDialogService方法,并用它做DI,使用它进入viewmodel。然后每个viewmodel将负责自己的对话框。从那里你可以调用ShowDialog,因为它是WindowManager的一部分,你单击是或否,或者为你设置对话框视图。有很多方法可以让猫皮肤更好,但最终你想要KISS方法和一些不会破坏你试图遵循的模式的东西。对于所有重要的事情,你可以将它添加到viewmodelbase基类中您的viewmodel继承全局访问。无论如何,所有功能都是您希望应用程序最终运行的功能。

- 更新 -

public class YourViewModel(IWindowManager winMan)
{
     private readonly IWindowManager _winMan;
     public YourViewModel()
     {
       _winMan = winMan;
     }

     public void DeleteCustomer()
     {
        var dialog= new DialogViewModel(); // not best way but...
        var settings = new Dictionary<string, object>();
        settings["Owner"] = this;  //<< Parent
        settings["StartupLocation"] = WindowStartupLocation.CenterParent;
        _winMan.ShowDialog(dialog, null, settings);

        if(dialog.Result)
          //do delete
        else
          //do nothing
     }
}