6

我正在寻找以下设置的最佳实践。

View 是绑定到 ViewModel 的数据(通过 WPF)。ViewModel 通过 INotifyPropertyChanged 更新 View。模型通过事件更新 ViewModel。模型知道来自外部世界的东西,比如如何通过 WebClient 从互联网获取东西,以及如何从数据库中检索数据。

向外部世界获取和发送内容应该异步完成,以便 UI(以及扩展,用户)不会因等待外部世界而受苦。

解决此问题的最佳实践方法是什么?

1. ViewModel 应该负责异步调用模型方法。
这将具有能够编写诸如

GetWebPage(string url) {
  var result = await Model.GetWebPageAsync(url);
  Url = result.Url;
}

在 ViewModel 中Url有一个 ViewModel 属性,它带有 INotifyPropertyChanged 来更新视图。甚至

GetWebPage(string url) {
  var result = await Model.GetWebPageAsync(url);
  _view.Url = result.Url;
}

我们可以一起避免 INotifyPropertyChanged 。您更喜欢这些方式中的哪一种?

然而,让模型本身来做异步工作可能更明智。我们可能希望能够在没有 View 和 ViewModel 的情况下使用 Model,同时仍然让它异步工作。另一个论点是,谁更清楚 Model 什么东西最好异步处理。

2.模型自己处理所有异步的东西。ViewModel 代码变得更像

GetWebPage(string url) {
  Model.GetWebPage(url);
}

在模型中

GetWebPage(string url) {
  var result = await Model.GetWebPageAsync(url);
  if (UrlChanged != null);
     UrlChanged(this, new UrlChangedEventArgs(url));
}

ViewModel 可以订阅,并相应地更新 View。

您认为哪种方式是最佳实践?

4

2 回答 2

3

第三种方式:视图模型进行异步调用,但是它使用客户端服务来检索网页,模型本身是贫血的(它对外部世界一无所知):

GetWebPage(string url) 
{
  var dataService = anyServiceLocator.GetService<IDataService>();
  var result = await dataService.GetWebPageAsync(url, Model);
  Url = result.Url;
}

这允许更改真实数据下载算法,例如用于测试目的。

于 2012-10-29T10:32:49.230 回答
0

我相信所描述场景的最佳实践将是您将提出的最佳实践 - 考虑每种方法的优缺点 - 这将特定于您的任务(随着任务之间的需求变化)。关于问题的实际答案,我相信没有太大区别。虽然我现在正在考虑另一种方法。考虑参数化 Helper(可能是 DownloadManager)对象的异步行为,该对象可以作为参数传递给 VM。这将允许您在不区分行为的情况下轻松测试 VM 和模型,并在 DownloadManager 上单独测试该行为。

于 2013-02-22T10:47:02.440 回答