【问题标题】:Where to update WPF observables?在哪里更新 WPF 可观察对象?
【发布时间】:2018-05-22 12:39:03
【问题描述】:

假设我有一个 WPF 应用程序,它的 StudentView 绑定到 StudentViewModel 中的属性 (ObservableCollection)。我还有一个 StudentService,它依赖于我的 StudentRepository。 StudentService 提供从 UI 以外的不同上下文调用的 CRUD 操作。

我的第一个实现在 StudentService 中有一个 ObservableCollection。虽然它适用于异步调用和所有,但这种设置从许多方面都在反击,感觉不对。尤其是在从各种上下文更新 ObservableCollection 时。

所以我认为更好的方法是将 Observables 保留在表示层 (View/ViewModel) 中,让 StudentViewModel 订阅来自 StudentService 的事件,然后在它们所在的上下文中更新 Observables。

所以我的问题是,如果我修改后的方法更好,或者可能有第三种更好的选择?

编辑示例:

目前我有这个(简化但我认为重要的东西):

View 显示学生列表,DataSource 是我的 ViewModel:

ItemsControl ItemsSource="{Binding Students.Result, UpdateSourceTrigger=PropertyChanged}">..</ItemsControl>

视图模型:

public class MainViewModel : ViewModelBase
{
   public NotifyTaskCompletion<AsyncObservableCollection<Student>> Students { get; private set; }

   public MainViewModel(IStudentService service)
   {
      Students = new NotifyTaskCompletion<AsyncObservableCollection<Student>>(service.List());
   }
}

NotifyTaskCompletion 来自 Stephen Cleary 的文章 here。 AsyncObservableCollection 是从here 中获取的。

我的 StudentService 有这个接口:

public interface IStudentService
{
   Task<bool> Add(Student student);
   Task<AsyncObservableCollection<Student>> List();
}

从后台线程调用 IStudentService.Add(...),这必须在 UI 中发现。

现在所有这些都有效,但是 AsyncObservableCollection 的锁定(我认为)存在一些问题。所以我想我需要一个来自 UI 上下文的锁,但那感觉不对 - 不得不在我的服务中引用 UI。而我正在考虑的是拉出 AsyncObservableCollection(即 ObservableCollection)并从我的服务中返回 Task&lt;IEnumerable&lt;Student&gt;&gt; - 并从服务中触发一些“OnStudentAdded”事件......

希望这能让它更清楚吗?

谢谢。

【问题讨论】:

  • 你用这个活动做什么?您需要了解哪些变化?服务有哪些变化?
  • 通常,ObservableCollections 属于视图模型。我会犹豫是否将事件放入服务中。视图模型应该在控制之中。如果您正在轮询后端的某事,我会编写一个执行此操作的类,并且我会给视图模型一份它的副本。这不是圣旨,但我发现这种方法对我来说是最容易编写和维护的。
  • @FCin 我添加了更多解释和示例。
  • @EdPlunkett 为什么不在服务中使用事件?有没有更优雅的方式让 UI 知道变化?
  • @Werner “我想我需要一个来自 UI 上下文的锁,但那感觉不对 - 必须在我的服务中引用 UI” - 所以不要吨。按照我的做法,该服务只是将某人要求的数据拒之门外——List&lt;POCO&gt;。如果 VM 想在后台工作人员中请求它,或者将该 PCOO 的视图模型版本放在 observablecollection 中,这取决于 VM。正如我所说,这不是圣旨。如果您有很多需要彼此保持同步的客户端,我描述的方法可能过于粗略和准备就绪。但是,如果您不需要它,请不要承诺额外的复杂性。

标签: wpf observable


【解决方案1】:

无论何时添加或删除新项目,服务都需要以某种方式通知视图模型。我同意最好通过从服务类引发事件或公开视图模型可以订阅的IObservable&lt;T&gt; 来做到这一点。

如果您从视图直接绑定的服务公开ObservableCollection&lt;T&gt; 属性,您将无法从服务类中的后台线程更新此集合。该服务在一定程度上依赖于客户端。

直接绑定到服务类公开的属性很少是一个好主意。您可以在视图模型中创建集合的副本并绑定到这个集合,但是您仍然需要将此集合与服务中定义的集合同步,这并不比订阅事件或IObservable&lt;T&gt; 更简单并在视图模型中“手动”更新数据绑定源集合。

【讨论】:

  • 谢谢,我添加了一些示例代码,更能说明我的问题。在我的情况下,你会推荐 Rx 而不是普通事件吗?
  • 不,我不会。添加新学生时,您没有理由不能简单地引发事件。
猜你喜欢
  • 2017-03-30
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多