我是Prism的新手,并且遇到了Event Aggregator的问题。我修改了微软给出的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”。
任何人都可以帮忙解释一下这个问题吗?谢谢
答案 0 :(得分:1)
真正的问题是,您在整个应用程序中使用了单个消息对象,并且您正在更改该单个对象。这基本上就是参考类型的工作原理。
引用类型包含指向另一个内存位置的指针 保存数据。参考类型包括以下内容:
- 字符串
- 所有数组,即使它们的元素是值类型
- 类类型,例如Form
- 代表
来源:https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
回顾一下你实际做的事情:
id=1 content="hello1"
)并将其引用存储在您的Shell上的属性中。content="hello2"
并使用EventAggregator
将消息(参考)发送给模块时。现在你最终得到了多个指针(一个在你的属性中,一个在你的ObservableCollection中,指向内存中的同一个Message对象。
content="hello1"
。由于它在任何地方引用了1个对象,因此所有变量都已经看到content="hello1"
。请注意,如果没有INotifyPropertyChanged,您在ComboBox的UI上看不到它,但是当您调试代码时,该值已经更改(因为我们仍在讨论相同的单个消息对象) )。
如何解决?
这样,您最终会得到ObservableCollection中不同项的列表。然后由您来决定是否要为每个消息发送显示一个项目(只需添加每个传入的消息)或过滤掉重复的字符串(应用检查)。