MVVM模型中的非阻塞延迟加载属性

时间:2011-06-29 14:33:10

标签: wpf silverlight mvvm lazy-loading inotifypropertychanged

我是MVVM的新手,所以如果这个问题有一个众所周知的解决方案,请原谅。

我们正在构建一组模型类,它们具有一些预先加载的核心属性,以及一些可以通过进行Web API调用来按需延迟加载的其他属性(更新:澄清,它将是每个延迟加载的属性的Web API调用。)

而不是拥有多个模型,拥有一个带有延迟加载逻辑的单个模型似乎是明智的。但是,似乎懒惰加载的属性在访问时不应该阻塞,因此当View绑定到ViewModel并且它绑定到Model时,我们不会阻止UI线程。

因此,我正在考虑一种模式,当模型上的惰性属性被访问时,它开始异步提取,然后立即返回默认值(例如null)。异步提取完成后,它将引发PropertyChanged事件,以便ViewModel / View可以重新绑定到获取的值。

我已经尝试过了,它看起来效果很好,但是想知道:

  1. 这种方法是否有任何我尚未发现的陷阱,但随着应用程序复杂性的增加会遇到什么?
  2. 是否存在内置于框架中的此问题的现有解决方案,还是广泛用作第三方框架的一部分?

1 个答案:

答案 0 :(得分:7)

我过去做过类似的事情,我一直忘记的一件事是你不能通过任何类型的代码调用你的异步属性,并期望它有一个值。

因此,如果我懒惰加载Customer.Products列表,我无法在代码隐藏中引用Customer.Products.Count,因为第一次调用它的值为NULL或0(取决于我是否为是否创建空白集合)

除此之外,它对绑定非常有用。我正在使用Async CTP库来进行异步调用,我发现这对于像这样的事情来说非常棒。

public ObservableCollection<Products> Products
{
    get
    {
        if (_products == null)
            LoadProductsAsync();

        return _products;
    }
    set { ... }
}

private async void LoadProductsAsync()
{
    Products = await DAL.LoadProducts(CustomerId);
}

<强>更新

我记得我遇到的另一件事是实际上是NULL的数据。如果Customer.Products实际从服务器返回NULL值,我需要知道异步方法已正确运行,并且实际值为null,因此它不会重新运行异步方法。

如果有人在第一次异步调用完成之前第二次调用了Get方法,我也不希望异步方法运行两次。

我当时通过为每个异步属性设置Is[AsyncPropertyName]Loading/ed属性并在第一次异步调用期间将其设置为true来解决此问题,但是我不必为所有异步创建额外属性而感到高兴属性。