问题
There are three windows MainWindow, FirstWindow and SecondWindow. MainWindow can open FirstWindow and SecondWindow.
Now my question is:
- How to open SecondWindow from FirstWindow, and close FirstWindow when the SecondWindow open. At this time, I can control SecondWindow but can't control MainWindow, just like using SecondWindow.ShowDialog() from MainWindow.
- After I click the "save" button on SecondWindow, the SecondWindow shall be closed and the DataGrid of MainWindow shall be updated. How to update data from another ViewModel or how to return data when event was handled?
回答1:
You are asking multiple for multiple things here.
Basically you need 2 things. An event aggregator (also called messenger) to pass messages between view models. There are different frameworks that implement it or they come as part of MVVM Frameworks.
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.)
回答2:
I'm agree with Tseng's answer and will try to extend his answer.
First part
For low-coupled communication between modules (not only ViewModels) we can try to implement EventAggregator pattern. 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. 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.
The second is Microsoft Prism implementation. 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.
As you can see all of this implementations uses Singleton pattern for saving subscribers.
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.
The main purpose to use navigation abstractions is to separate navigation logic from concrete view rendering technology (WPF, Silverlight, WinRT, Xamarin).
For example, in Microsoft Prism we can use regions and RegionManager for navigation between views and windows. 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.
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.
Conclusions
This post is not an answer to your questions. But I hope that it will be helpful to you to understanding MVVM concepts.
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.
回答3:
You need to use an instance of the form class to pass data. See my simple two form project below
Form 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
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";
}
}
}
来源:https://stackoverflow.com/questions/34258994/how-to-communicate-between-viewmodels-in-wpf-and-how-to-control-views-lifecycle