[英]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.