簡體   English   中英

使用 Prism 事件聚合器從背后的代碼到視圖模型進行通信

[英]Use Prism Event Aggregator to Communicate from Code Behind to View Model

我正在使用 MVVM 模式開發 WPF 應用程序。 此外,我一直在利用 Prism Event Aggregator 功能在視圖模型之間進行通信。

我們正在使用一個控件庫,我們正在使用的一個控件(一個更改/自定義的數據網格)具有庫作者創建的事件。 例如,當一個單元格結束編輯時……類似於失去焦點。 我面臨的問題是庫控件使用了背后的代碼而不是事件方法的視圖模型。

我想我會簡單地利用事件聚合器讓 VM 從背后的代碼中了解事件。 它不工作。 我的虛擬機在構造函數中使用了一個簡單的訂閱...

_eventAggregator.GetEvent<AfterLineAmountPaidEvent>().Subscribe(OnLineAmountPaidChanged);

OnLineAmountPaidChanged 方法永遠不會被命中。

在代碼隱藏中,我正在發布事件...

_eventAggregator.GetEvent<AfterLineAmountPaidEvent>().Publish(
                    new AfterLineAmountPaidEventArgs
                    {
                        InvoiceLinesSelectedAmount = InvoiceLinesDataGrid.ItemsSource
                    });

我想知道它是否與 Prism 庫和事件聚合器的實例化有關。 在 VM 中,我通過構造函數創建它...

IEventAggregator eventAggregator

我正在使用基本虛擬機擴展虛擬機...

: base(eventAggregator, messageDialogService)

然后我將實例化分配給我使用的私有,如前面的代碼所示......

private readonly IEventAggregator _eventAggregator;

在代碼隱藏中,我按如下方式實例化事件聚合器...

private readonly IEventAggregator _eventAggregator = new EventAggregator();

當我使用斷點單步執行代碼時,我注意到一旦代碼命中代碼隱藏,訂閱就會從 2(二)變為 0(零)。 這就是為什么我認為它正在通過我使用庫的方式在后面的代碼中為應用程序重新實例化。

是否有不同/更好的方式來完成這種溝通? 我是否錯誤地實例化了事件聚合器?

任何建議都是有幫助的。

你的猜測是正確的。 問題是您有兩個EventAggregator對象。 您的代碼不應實例化 EventAggregator。 它應該是從 Prism 給你的。 您的代碼隱藏需要獲得與您的視圖模型相同的EventAggregator實例。

好消息是,您可以將相同的EventAggregator注入到與您的視圖模型一起使用的視圖中,就像視圖模型獲取它的方式一樣。 通過構造函數注入。 然后將它傳遞給任何其他代碼隱藏程序。

這是一個例子。 我有一個名為我的ExploreModule的 Prism 模塊。 在模塊派生類中,我的 RegisterTypes 函數如下所示:

public void RegisterTypes(IContainerRegistry reg)
{
    reg.RegisterForNavigation<ExploreView>(ModuleKey.Explore);
}

在我的應用程序中,與我的ExploreView一起使用的視圖模型稱為ExploreVm 您沒有看到它在此處列出,因為我使用 Prism 的“視圖-模型-定位器”方法。 但基本上,無論何時 Prism 創建我的ExploreView ,它都會創建一個ExploreVm來配合它。

這意味着我可以將任何我想要的注冊服務添加到ExploreVmExploreView的構造函數中。 包括IEventAggregator

所以我編輯我的ExploreVm以獲取IEventAggregator 這是我使用的一種。 它添加了IEventAggregator以及我個人創建和注冊的另一個服務。 由於 Prism 為我創建了這個視圖模型,它只為我提供了兩個服務。

public ExploreVm(ICaptureService  capSvc, IEventAggregator agg)
{
    // ...
}

如果我願意,我也可以以相同的方式編輯我的ExploreView

public ExploreView(IEventAggregator aggregator)
{
    Aggregator = aggregator;
    InitializeComponent();
}

您應該有一個類似的視圖/視圖-模型對,您可以在其中執行相同的操作。

現在,如果我有一些需要訪問IEventAggregator子視圖/控件(不是由 Prism 創建的),那么我將在屬性中公開IEventAggregator或使用其他方式將其傳遞下去。 但是這個 Prism 創建的視圖/視圖模型是入口點。

無論如何,關鍵是您沒有創建 EventAggregator。 棱鏡可以。

@喬...

我想發表評論,以便我可以展示更多代碼,您可能會指出我哪里出錯了。

我的 VM 是使用 VM 工廠類創建的。 這是一個片段...

public IReceiptDetailViewModel CreateReceiptDetailViewModel(
            int? customerId,
            Action<Guid> onTabClosed,
            Action onReloadCustomerInvoicesRequested)
        {
            IReceiptDetailViewModel viewModel = new ReceiptDetailViewModel(
                customerId,
                _mapper,
                _customerDataProvider,
                _invoiceDataProvider,
                _receiptDataProvider,
                this,
                _eventAggregator,
                _messageDialogService,
                onTabClosed,
                onReloadCustomerInvoicesRequested,
                _windowService);

            return viewModel;
        }

使用傳遞給我的 ConfigureServices 方法的 IServiceCollection 接口從我的 App.xaml.cs 引用 VM 工廠代碼。

services.AddTransient<IViewModelFactory, ViewModelFactory>();

我的應用程序構造函數如下...

   ConfigureServices(serviceCollection);
   _serviceProvider = serviceCollection.BuildServiceProvider();

我還在那里添加了一個事件聚合器的單例......

services.AddSingleton<IEventAggregator, EventAggregator>();

所以我接線錯誤嗎? 我應該以不同的方式做嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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