C# WPF上MVVM下的父视图和子视图通信

C# WPF上MVVM下的父视图和子视图通信,c#,wpf,mvvm,caliburn.micro,C#,Wpf,Mvvm,Caliburn.micro,我为这个问题奋斗了很长时间。我正在构建我的第一个WPF MVVM应用程序。在这个应用程序中,我有一个AppView(及其相应的viewmodel)。子视图包含在选项卡中,由单独的视图(UserControl)表示,每个视图有一个viewmodel。到目前为止还不错 在一个视图中,用户有一个客户列表和一个删除按钮。我在viewmodel上还有一个相应的ig命令,可以实际删除该记录,而且效果很好。现在我希望删除按钮创建一个新视图,其中有两个按钮,一个用于确认,另一个用于取消,如果用户单击“确认”按钮

我为这个问题奋斗了很长时间。我正在构建我的第一个WPF MVVM应用程序。在这个应用程序中,我有一个AppView(及其相应的viewmodel)。子视图包含在选项卡中,由单独的视图(UserControl)表示,每个视图有一个viewmodel。到目前为止还不错

在一个视图中,用户有一个客户列表和一个删除按钮。我在viewmodel上还有一个相应的ig命令,可以实际删除该记录,而且效果很好。现在我希望删除按钮创建一个新视图,其中有两个按钮,一个用于确认,另一个用于取消,如果用户单击“确认”按钮,则执行删除

这里的问题是,每个视图及其对应的IG viewmodel彼此隔离(只要我理解),因此我无法访问第二个视图viewmodel以查看是否单击了确认按钮

到目前为止,我找到的唯一可行的解决方案是在一个视图上添加一个事件,并向另一个视图订阅该事件。但这项技术对于如此琐碎的任务来说相当复杂。还有其他选择吗?这两个视图不能共享相同的datacontext或viewmodel吗


谢谢

var dialog=new DialogViewModel();//如果您愿意,可以是DialogService

在这个DialogViewModel或DialogService中,您可以再次选择实际操作的方式

对话框。结果,在这种情况下,将返回您的确认为真或假

var设置=新字典();
设置[“所有者”]=此;
设置[“WindowsStartUplocation”]=WindowsStartUplocation.CenterParent;
windowManager.ShowDialog(对话框,空,设置)

if(dialog.Result==true)
在父视图模型上执行删除操作。

或者你可以用IEventAggregator和一个消息包来完成这一切。我个人在很多事情上使用第一个。有时,这取决于具体情况

大多数人会支持面向SoC的IDialogService方法,并使用它进行DI,以将其引入到使用它的viewmodel中。然后,每个viewmodel将负责自己的对话框。从那里,您可以调用ShowDialog,因为它是WindowManager的一部分,您可以单击“是”或“否”,或者您为dialogview设置的内容。给猫剥皮的方法有很多种,但最后你想要的是接吻方法和一些不会打破你试图坚持的模式的东西。。无论如何,您可以将其添加到viewmodelbase基类中,以便所有viewmodels继承以全局访问。所有这些都是你希望你的应用程序最终如何运行的函数

--更新--

public类YourViewModel(IWindowManager-winMan)
{
私有只读IWindowManager_winMan;
公共视图模型()
{
_温曼=温曼;
}
公共客户()
{
var dialog=new DialogViewModel();//这不是最好的方法,但。。。
var settings=newdictionary();

设置[“所有者”]=this;//新视图应该是模态视图,并且应该从一个函数调用,该函数将返回一个值到原始视图。a是最简单的方法。谢谢@RobertHarvey。是的,我的想法是第二个视图是模态视图到第一个视图。我已经解决了这一部分。但是我的第二个视图是一个分离的XAML,具有相应的viewmodel。所以我如何“顶嘴”从视图2 viewmodel到视图1 viewmodel?有一个很好的例子。视图模型与mvvm light提供的消息传递框架进行通信效果最好。一开始它可能看起来有点过度设计,但由于您刚刚开始,值得了解和研究。下面是一个类似的问题,我用一个例子回答了…好的。我是using Caliburn.Micro在这里,但原理是一样的。因此@RobertHarvey的链接建议,使用某种事件触发器和侦听器。正如我提到的,我已经找到了这个解决方案,但对于这个简单的任务来说似乎有些过火了。我想让两个视图在所有属性中使用同一个viewModel实例和方法,但我不知道这是否可行,因为ech视图是从它的viewmodel创建的。谢谢你的回答。我正在尝试测试它,在最后一行代码中得到一个错误:WindowManager.ShowDialog(dialog,null,settings);它是错误1非静态字段“Caliburn.Micro.WindowManager.ShowDialog(对象、对象、系统、集合、通用、IDictionary)”需要对象引用“MEF或SimpleContainer当前为您提供的容器?或任何容器?很抱歉,我完全不明白您的要求。我使用:var p=new WindowManager();p.ShowDialog(dialog,null,settings)进行了一些测试并使其正常工作。”;而且工作正常。唯一的问题是它会打开一个新窗口,我需要在同一个视图中进行操作。类似于ContentPresenter。我只是演示了一个您可以使用Caliburn进行操作的示例。Micro,它仍然需要一些基础设施才能将其用于应用程序所需的位置。windowmanager只是Andres向对话演示如何处理该对话取决于您。我想帮您做一些“分离关注点”的事情,看看您是如何得到“是否要删除?是/否”的答案的Caliburn.Micro可以用我指出的几种方法来完成。2.即使是MVVMLite选项也是完成任务的类似示例。最后,您将需要一个自定义视图“您的对话框”与该对话框关联的viewmodel.Caliburn.Micro在WindowManager中有许多这样的示例,或者如果您想真正参与到该对话框中,也可以使用它
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
     }
}