【问题标题】:ObservableCollection not changing in MVVM when using NServiceBus使用 NServiceBus 时,MVVM 中的 ObservableCollection 不会改变
【发布时间】:2017-02-12 16:24:24
【问题描述】:

我的 MVVM 应用程序中的 ObservableCollection 有一个奇怪的行为,更确切地说是在负责从 NServiceBus 接收消息的代码部分:

public class MyViewModel: ViewModelBase, IHandleMessages<CarMoved>
{
 public ObservableCollection<CarData> Cars= new ObservableCollection<CarData>();


 public Task Handle(CarMoved message, IMessageHandlerContext context)
 {
   ...
   Cars.Add(new Car());

   return Task.CompletedTask;
 }

}

所以我希望 Handle 方法将一个新对象添加到我的 ObservableCollection 中,但对象的数量保持不变。 我创建了测试按钮来检查是否可以使用按钮添加新对象,并且此测试按钮工作正常。 我还调试了 Handle 方法,我可以看到当我在 Handle 方法中时 Observable 集合中的对象数量增加了,但是一旦我离开该方法,所有这些都会改变 - 对象的数量返回到旧的数字.

我尝试使用 Task.Run(..); 添加对象任务.Wait();假设它可能需要一些时间。它没有帮助。

请告诉我如何解决这个问题以及为什么会发生?

【问题讨论】:

  • 如果您不希望有人能够在不看代码的情况下猜出它是如何定义的,请发布您的 Handle 方法的完整实现。
  • 这是一个完整的方法:我创建一个新对象的实例并将其添加到列表中
  • 您是否尝试过我回答中的建议或发生了什么?

标签: c# wpf mvvm messaging nservicebus


【解决方案1】:

好的,所以这里的问题是 NServiceBus 将创建一个新的 ViewModel 实例来处理消息。这显然不是你想要的。

ViewModel 和消息Handler 应该是单独的对象。然后处理程序可以将消息告诉ViewModel

我不确定您使用的是什么 MVVM 框架,但通常有某种事件聚合器用于从 NServiceBus 处理程序和 ViewModel 等系统组件传递消息。

【讨论】:

    【解决方案2】:

    确保您使用调度程序访问 UI 线程上的 ObservableCollection

    public Task Handle(CarMoved message, IMessageHandlerContext context)
    {
        Application.Current.Dispatcher.BeginInvoke(new Action(() => { Cars.Add(new Car()); }));
    
        return Task.CompletedTask;
    }
    

    或者,您可以尝试使用BindingOperations.EnableCollectionSynchronization 方法来启用跨多个线程访问集合:

    public class MyViewModel : ViewModelBase, IHandleMessages<CarMoved>
    {
        private readonly object _lock = new object();
        public ObservableCollection<CarData> Cars = new ObservableCollection<CarData>();
    
        public MyViewModel()
        {
            Application.Current.Dispatcher.Invoke(() => BindingOperations.EnableCollectionSynchronization(Cars, _lock));
        }
    
        public Task Handle(CarMoved message, IMessageHandlerContext context)
        {
            Cars.Add(new Car());
            return Task.CompletedTask;
        }
    }
    

    如果您仍然无法做到,请阅读以下内容:https://stackoverflow.com/help/mcve

    【讨论】:

    • 我找到了它不起作用的原因:您在 ViewModel 中扩展 IHandleMessages 接口的方法导致每次收到消息时都重新创建 ViewModel。所以现在除了糟糕的代码之外,它还会破坏应用程序的工作。
    猜你喜欢
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 2023-03-08
    • 2016-09-08
    • 2018-08-04
    • 1970-01-01
    • 2014-02-14
    • 2021-07-21
    相关资源
    最近更新 更多