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