[英]How to communicate between ViewModels? ( Prism event aggregator?)
我是C#和WPF的新手,我正在制作一个小型应用程序,所以我认为这是学习和使用MVVM模式的好机会。
这肯定使事情比我对小型应用程序的预期要困难一些,但这是一种很好的学习体验。 到目前为止,我一直可以跟进。 我似乎完全不知道如何正确实现ViewModels彼此交互的方式。
我有MainWindowView和OverlayView,我希望能够从主ViewModel在覆盖视图上绘制一个矩形。 我想要一种方法,能够从MainViewModel广播事件,并让OverlayView听到它并按指定方式绘制矩形。 我还认为,一旦工作正常,添加“ CloseAllWindows”广播会很方便。
根据我的研究,最简单的方法是使用Prism这样的框架。 我一直在尝试从Prism框架设置一个Event Aggregator,但是无论我如何尝试,我都无法使其正常工作。 我到处都在寻找文章或教程,但它们似乎都已过时,链接断开,或者我似乎无法理解它们并使它们正常工作。
这是到目前为止我得到的:
Events.cs :
using System.Windows;
using Prism.Events;
namespace Application.Overlay {
public class DrawRectEvent : PubSubEvent<Rect> {
}
}
MainWindowViewModel.cs
namespace Application.ViewModels {
public class MainWindowViewModel : BindableBase {
private IEventAggregator eventAggregator;
public MainWindowViewModel(IEventAggregator eventAggregator) {
this.eventAggregator = eventAggregator;
WindowLoadedCommand = new RelayCommand(WindowLoaded);
TestDrawCommand = new RelayCommand(TestDraw);
}
public RelayCommand TestDrawCommand { get; set; }
public void TestDraw() {
Console.WriteLine("Publishing DrawRect Broadcast");
Size size = new Size(100, 100);
Point point = new Point(50, 50);
Rect rect = new Rect(point, size);
eventAggregator.GetEvent<DrawRectEvent>().Publish(rect);
}
}
MainWindow.xaml.cs
namespace Application {
public partial class MainWindow : Window {
private IEventAggregator eventAggregator;
TextBoxOutputter outputter;
public MainWindow() {
this.DataContext = new ViewModels.MainWindowViewModel(eventAggregator);
InitializeComponent();
// Route console output to ConsoleOutput TextBox
outputter = new TextBoxOutputter(ConsoleOutput);
Console.SetOut(outputter);
}
OverlayViewModel.cs
namespace Application.Overlay : BindableBase {
public class OverlayViewModel {
private IEventAggregator eventAggregator;
public OverlayViewModel(IEventAggregator eventAggregator) {
this.eventAggregator = eventAggregator;
this.eventAggregator.GetEvent<DrawRectEvent>().Subscribe(DrawRectEventHandler);
}
private void DrawRectEventHandler(Rect rect) {
Console.WriteLine("Signal Received, Drawing Rectangle!");
}
OverlayView.xaml.cs
namespace Application.Overlay {
public partial class Overlay : Window {
private IEventAggregator eventAggregator;
public Overlay() {
InitializeComponent();
Top = 0;
Left = 0;
this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
this.WindowStyle = WindowStyle.None;
this.DataContext = new OverlayViewModel(eventAggregator);
}
使用此代码,它可以很好地编译,但是在运行它时会收到“空引用异常”“对象引用未设置为对象的实例”,它引用了OverlayViewModel中的第9行:
this.eventAggregator.GetEvent<DrawRectEvent>().Subscribe(DrawRectEventHandler);
我不确定是否要在后面的代码中将正确的东西传递给新的ViewModel实例,但是我不确定您还会传递什么。
如果您发现我做错了什么,或者您有一份最新指南显示了比我做的事更有效的方法,那么我将不胜感激。 谢谢!
既然您才刚刚起步,我就不会花太多时间解释基础知识,我将直接跳到“如何使您的当前代码得以构建和运行”这一部分,您可以继续前进在学习上。
据我提供的代码可以看出,您似乎从未真正创建过EventAggregator
的实例(除非您已经设置了IoC容器,但我看不到任何表明您拥有已经做到了)。
所以在你的代码中:
public partial class MainWindow : Window {
private IEventAggregator eventAggregator;
TextBoxOutputter outputter;
public MainWindow() {
this.DataContext = new ViewModels.MainWindowViewModel(eventAggregator);
InitializeComponent();
// Route console output to ConsoleOutput TextBox
outputter = new TextBoxOutputter(ConsoleOutput);
Console.SetOut(outputter);
}
您正在创建ViewModels.MainWindowViewModel
的实例,并传递空字段eventAggregator
。 在此之前,您需要使用实际实例填充该字段。 所以试试这个:
public partial class MainWindow : Window {
private IEventAggregator eventAggregator;
TextBoxOutputter outputter;
public MainWindow() {
this.eventAggregator = new EventAggregator(); //<---
this.DataContext = new ViewModels.MainWindowViewModel(eventAggregator);
InitializeComponent();
// Route console output to ConsoleOutput TextBox
outputter = new TextBoxOutputter(ConsoleOutput);
Console.SetOut(outputter);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.