簡體   English   中英

Microsoft Prism事件聚合器發送值或地址

[英]Microsoft Prism Event Aggregator send value or address

我是Prism的新手,並且對Event Aggregator有問題。 我修改了Microsoft給出的HelloWorld示例以顯示我的問題,該問題在最后進行了描述。

首先,我定義一個MyMessage類作為事件的有效負載發送,如下所示:

public class MyMessage
{
    public int id { get; set; }
    public string content { get; set; }

    public override string ToString()
    {
        return this.content;
    }
}

其次,我定義一個事件如下

public class MessageArrivedEvent : PubSubEvent<MyMessage>
{
}

之后,我向Shell.xaml添加一個按鈕,其單擊功能如下

private void button_Click(object sender, RoutedEventArgs e)
    { 
        message.content = message.content == "hello1" ? "hello2" : "hello1";

        ServiceLocator.Current.GetInstance<IEventAggregator>()
                .GetEvent<MessageArrivedEvent>()
                .Publish(message);
    }

在這里,message是公共局部類Shell:Window類中的一個屬性。

此外,我向HelloWorldView添加了一個組合框,並將ItemsSource綁定到其對應的viewmodel。

private ObservableCollection<MyMessage> _comboboxitemsource;

    public ObservableCollection<MyMessage> comboboxitemsource
    {
        get { return this._comboboxitemsource; }
        set
        {
            this._comboboxitemsource = value;
            this.OnPropertyChanged("comboboxitemsource");
        }
    }

我處理事件的方式如下:

public HelloWorldViewModel()
    {
        this.comboboxitemsource = new ObservableCollection<MyMessage>();
        ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<MessageArrivedEvent>().Subscribe(this.MessageArrived, ThreadOption.UIThread, false);
    }

    private void MessageArrived(MyMessage message)
    {
        for (int i = 0; i < this.comboboxitemsource.Count; i++)
        {
            if (this.comboboxitemsource[i].id == message.id)
            {
                this.comboboxitemsource[i].content = message.content;
                break;
            }
        }

        if (this.comboboxitemsource.Count == 0)
            this.comboboxitemsource.Add(message);

    }

現在,我將Shell部分中消息的內容設置為“ hello1”。 當我單擊按鈕時,其內容將更改為“ hello2”,然后消息將發送到HelloWorldModule。 由於此時,comboboxitemsource中沒有元素,因此消息將添加到此itemsource中。 再次單擊該按鈕時,消息的內容將更改為“ hello1”,並將消息發送到模塊。 問題是在MessageArrived函數中更改消息之前,內容已自動更改為“ hello1”。 運行MessageArrived之后,下拉列表中的內容仍然是“ hello2”,而不是“ hello1”。

誰能幫助解釋這個問題? 謝謝

真正的問題是您在整個應用程序中使用了一個消息對象,並且您正在更改該對象。 基本上,這就是引用類型的工作方式。

引用類型包含指向另一個保存數據的存儲位置的指針。 參考類型包括:

  • 所有數組,即使它們的元素是值類型
  • 類類型,例如Form
  • 代表們

資料來源: https : //msdn.microsoft.com/en-us/library/t63sy5hs.aspx

回顧一下您的實際操作:

  • 您創建一個消息對象( id=1 content="hello1" ),並將對它的引用存儲在Shell的屬性中。
  • 當您單擊按鈕時, content="hello2"並使用EventAggregator將消息的(引用)發送到模塊。
  • 由於ComboBox為空,因此請添加此消息。

現在,您將獲得多個指針(屬性中的一個指針,ObservableCollection中的一個指針指向內存中的同一Message對象。

  • 您再次單擊該按鈕,然后更新content="hello1" 由於它是在各處引用的1個對象,因此所有變量都已經看到content="hello1"

請注意,如果沒有INotifyPropertyChanged,則不會在ComboBox的UI上看到它,但是在調試代碼時,該值已經更改(因為我們仍在談論相同的1個單個消息對象)。


如何解決?

  • 將屬性放在擁有對Message對象的引用的外殼上,在上述情況下,保留對它的引用是沒有用的。 如果要跟蹤是否必須發送hello1或hello2,則可以使用簡單的布爾值或字符串標志來實現。
  • 通過EventAggregator發送消息時,請始終創建一個新對象,因為它是您要發送的新消息。

這樣,您最終將獲得ObservableCollection中不同項目的列表。 然后由您決定是要為發送的每條消息顯示一個項目(簡單地添加每條傳入的消息)還是過濾出重復的字符串(應用檢查)。

暫無
暫無

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

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