C# 如何在WPF中的视图模型之间通信以及如何控制视图生命周期

C# 如何在WPF中的视图模型之间通信以及如何控制视图生命周期,c#,wpf,mvvm,navigation,eventaggregator,C#,Wpf,Mvvm,Navigation,Eventaggregator,主窗口、第一窗口和第二窗口共有三个窗口。主窗口可以打开第一个窗口和第二个窗口 现在我的问题是: 如何从第一个窗口打开第二个窗口,以及在第二个窗口打开时关闭第一个窗口。此时,我可以控制SecondWindow,但无法控制MainWindow,就像在MainWindow中使用SecondWindow.ShowDialog()一样 在我点击SecondWindow上的“保存”按钮后,SecondWindow将被关闭,MainWindow的DataGrid将被更新。如何从另一个ViewModel更新数

主窗口、第一窗口和第二窗口共有三个窗口。主窗口可以打开第一个窗口和第二个窗口

现在我的问题是:

  • 如何从第一个窗口打开第二个窗口,以及在第二个窗口打开时关闭第一个窗口。此时,我可以控制SecondWindow,但无法控制MainWindow,就像在MainWindow中使用SecondWindow.ShowDialog()一样
  • 在我点击SecondWindow上的“保存”按钮后,SecondWindow将被关闭,MainWindow的DataGrid将被更新。如何从另一个ViewModel更新数据,或者如何在处理事件时返回数据

您需要使用表单类的实例来传递数据。请参阅下面我的简单的两个表单项目

表格一

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Form2 form2;
        public Form1()
        {
            InitializeComponent();
            form2 = new Form2(this);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            form2.Show();
            string  results = form2.GetData();
        }
    }
}
​
表格二

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        Form1 form1;
        public Form2(Form1 nform1)
        {
            InitializeComponent();

            this.FormClosing +=  new FormClosingEventHandler(Form2_FormClosing);
            form1 = nform1;
            form1.Hide();
        }
        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            //stops form from closing
            e.Cancel = true;
            this.Hide();
        }
        public string GetData()
        {
            return "The quick brown fox jumped over the lazy dog";
        }

    }
}
​

你在这里要求多件事

基本上你需要两样东西。在视图模型之间传递消息的事件聚合器(也称为messenger)。有不同的框架实现它,或者它们是MVVM框架的一部分

第二,您需要一个导航服务,将导航与视图模型分离,因为导航需要视图相关技术(WPF、UWP、Silverlight等)的知识。

我同意,并将尝试扩展他的答案

第一部分

对于模块之间的低耦合通信(不仅仅是视图模型),我们可以尝试实现模式。事件聚合器有助于在低耦合应用程序中实现订阅者/发布者模式。我知道很少有不同的实现

第一个基于并使用WeakReference,这将帮助您防止内存泄漏。我不会发布整个代码,因为您可以下载源代码并使用它。在此实现中,您必须为订阅服务器实现ISubscriber接口

二是实施。这是一个开源项目,您可以看到,并且。在此实现中,您必须手动取消订阅事件

第三个也是最后一个是MVVMLight库及其类

正如您所看到的,所有这些实现都使用单例模式来保存订阅者

第二部分

第二部分是关于导航。最简单的方法是使用基础设施。但在MVVM世界中,我们有许多不同的导航概念

使用导航抽象的主要目的是将导航逻辑与具体的视图渲染技术(WPF、Silverlight、WinRT、Xamarin)分离

例如,在中,我们可以使用区域和在视图和窗口之间进行导航。这是一个非常冗长的导航框架,仅仅一篇文章就很难理解它的概念

MVVM灯也有自己的

对于我的项目,我使用自己的导航实现。它是一种混合机制,结合了.net的页面导航原理和Prism的区域概念

结论

这篇文章不是对你问题的回答。但我希望这将有助于您理解MVVM的概念


如上所述,有许多MVVM框架包含基础设施(不仅包括Messenger和NavigationService,还包括基本命令实现、PopupService、转换器、帮助程序和实现),用于在应用程序中实现典型场景

问题被标记为WPF和MVVM,而不是WinForms。MVVM旨在解耦代码,以避免紧密耦合和易于测试,并避免几乎所有代码落后。完全不同的设计理念,而不是使用多窗口->使用一个窗口和多个用户控件,它们将代表第一、第二和第三视图。例如,使用TabItems的TabControl在使用Prism的PubSubEvents时不必取消订阅,除非使用
KeepSubscriberReferenceal
作为
true
订阅。Prism设置为false时将使用弱事件。棱镜5和6也是如此。不知道框架的旧版本