简体   繁体   English

如何在WPF中的ViewModel之间进行通信以及如何控制视图生命周期

[英]How to communicate between ViewModels in WPF and how to control Views lifecycle

There are three windows MainWindow, FirstWindow and SecondWindow. MainWindow,FirstWindow和SecondWindow有三个窗口。 MainWindow can open FirstWindow and SecondWindow. MainWindow可以打开FirstWindow和SecondWindow。

Now my question is: 现在我的问题是:

  • How to open SecondWindow from FirstWindow, and close FirstWindow when the SecondWindow open. 如何从FirstWindow打开SecondWindow,并在SecondWindow打开时关闭FirstWindow。 At this time, I can control SecondWindow but can't control MainWindow, just like using SecondWindow.ShowDialog() from MainWindow. 这时,我可以控制SecondWindow但无法控制MainWindow,就像使用MainWindow中的SecondWindow.ShowDialog()一样。
  • After I click the "save" button on SecondWindow, the SecondWindow shall be closed and the DataGrid of MainWindow shall be updated. 单击SecondWindow上的“保存”按钮后,将关闭SecondWindow,并更新MainWindow的DataGrid。 How to update data from another ViewModel or how to return data when event was handled? 如何更新来自另一个ViewModel的数据或如何在处理事件时返回数据?

You are asking multiple for multiple things here. 你在这里问多个事情。

Basically you need 2 things. 基本上你需要2件事。 An event aggregator (also called messenger) to pass messages between view models. 用于在视图模型之间传递消息的事件聚合器(也称为messenger)。 There are different frameworks that implement it or they come as part of MVVM Frameworks. 有不同的框架可以实现它,或者它们是MVVM框架的一部分。

Second you need is a navigation service to decouple navigation from your view models, as navigation requires knowledge of the view related technology (WPF, UWP, Silverlight etc.) 其次,您需要的是导航服务,以便将导航与视图模型分离,因为导航需要了解视图相关技术(WPF,UWP,Silverlight等)

I'm agree with Tseng's answer and will try to extend his answer. 我同意Tseng的回答,并会尝试扩展他的答案。

First part 第一部分

For low-coupled communication between modules (not only ViewModels) we can try to implement EventAggregator pattern. 对于模块之间的低耦合通信(不仅是ViewModels),我们可以尝试实现EventAggregator模式。 Event aggregator helps to implement subscriber/publisher pattern in low-coupled app. 事件聚合器有助于在低耦合应用程序中实现订阅者/发布者模式。 I know few different implementations. 我知道几个不同的实现。

First one based on CodeProject post and uses WeakReference that will help you to prevent memory leak. 第一个基于CodeProject的帖子并使用WeakReference来帮助您防止内存泄漏。 I will not publish whole code because you can just download source code and use it. 我不会发布整个代码,因为您只需下载源代码并使用它。 In this implementation you must to implement ISubscriber interface for your subscribers. 在此实现中,您必须为订户实现ISubscriber接口。

The second is Microsoft Prism implementation. 第二个是Microsoft Prism实现。 This is an open source project then you can see interface , implementation and base event class . 这是一个开源项目,然后您可以看到接口实现基本事件类 In this implementation you must unsubscribe from the event manually. 在此实现中,您必须手动取消订阅该事件。

The third and the last is MVVMLight library and its Messenger class. 第三个也是最后一个是MVVMLight库及其Messenger类。

As you can see all of this implementations uses Singleton pattern for saving subscribers. 如您所见,所有这些实现都使用Singleton模式来保存订阅者。

Second part 第二部分

Second part is about navigation. 第二部分是关于导航。 The simpliest way is to use Page navigation infrastructure. 最简单的方法是使用页面导航基础结构。 But in MVVM-world we have many different concepts for navigation. 但是在MVVM世界中,我们有许多不同的导航概念。

The main purpose to use navigation abstractions is to separate navigation logic from concrete view rendering technology (WPF, Silverlight, WinRT, Xamarin). 使用导航抽象的主要目的是将导航逻辑与具体视图渲染技术(WPF,Silverlight,WinRT,Xamarin)分开。

For example, in Microsoft Prism we can use regions and RegionManager for navigation between views and windows. 例如,在Microsoft Prism中,我们可以使用区域和RegionManager在视图和窗口之间进行导航。 It's very ponderous navigation framework and it can be difficult to understand the concept after only one article. 这是非常笨重的导航框架,只有一篇文章后很难理解这个概念。

MVVM Light also have their own navigation mechanism . MVVM Light也有自己的导航机制

For my projects I use my own realization of navigation via Workspaces . 对于我的项目,我使用自己的工作空间导航实现。 It is a hybrid mechanism that combines Page navigation principes from .net and Regions concept from Prism. 它是一种混合机制,它结合了来自Prism的.net和Regions概念的页面导航原理。

Conclusions 结论

This post is not an answer to your questions. 这篇文章不是你问题的答案。 But I hope that it will be helpful to you to understanding MVVM concepts. 但我希望您了解MVVM概念会对您有所帮助。

As you can read above there are many MVVM-frameworks which contains infrastructure (not only Messenger and NavigationService, but also base command realisations, PopupService, converters, INotifyPropertyChanged -helpers and base ViewModel implementations) to implement typical scenarios in your application. 如上所述,有许多MVVM框架包含基础结构(不仅包括Messenger和NavigationService,还包括基本命令实现,PopupService,转换器, INotifyPropertyChanged -helpers和基本ViewModel实现),以实现应用程序中的典型方案。

You need to use an instance of the form class to pass data. 您需要使用表单类的实例来传递数据。 See my simple two form project below 请参阅下面的简单的两个表单项目

Form 1 表格1

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();
        }
    }
}
​

Form 2 表格2

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";
        }

    }
}
​

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM