簡體   English   中英

如何在ViewModel之間進行通信? (棱鏡事件聚合器?)

[英]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容器,但我看不到任何表明您擁有已經做到了)。

所以在你的代碼中:

MainWindow.xaml.cs

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM