何时以及如何在Windows Phone wp8中的ViewModel中调用异步方法

时间:2014-03-02 15:43:55

标签: c# mvvm windows-phone-8 async-await

我有一个使用MVVM模式的Windows phone(wp8)应用程序,其中包含一个带有数据透视控件的视图,并绑定到ViewModel(PivotMainViewModel)。

每个数据透视表项包含一个不同的视图(datatemplate),并绑定到自己的viewmodel(PivotItemViewModel1,PivotItemViewModel1等等),所有这些都运行良好。

我的PivotMainViewModel是通过xaml绑定初始化的,但由于它需要一个参数,它也是通过视图的OnNavigatedTo事件“初始化”。

PivotItemViewModel4 pivotItemViewModel4 = Resources["PivotItemViewModel4"] as PivotItemViewModel4;
if (selectedRow.Id > 0)
{
    pivotItemViewModel4.InitializeDocumentDetails(selectedRow);

}

但我不确定如何处理我想异步制作的Web服务请求。我需要为每个透视项“视图”发出一个Web服务请求,并在返回的那一刻加载数据,但是我需要在初始化数据后立即执行此操作,但我不确定以下内容:

  1. 我需要填充每个数据透视表项“视图”中的数据,因此需要填充相关的视图模型,但我不确定是否应该从PivotMainViewModel或每个为每个视图模型定义的每个视图模型进行所有异步调用枢轴项目。

  2. 我是从PivotMainViewModel调用此函数还是从每个透视图项目视图模型中调用此函数,何时应该调用它?

  3. 我应该从构造函数中调用它:

    public PivotItemViewModel1
    {
      this.Document = GetDocument();
    }
    

    或者当我的内部变量为null时获取我的属性的一部分?即。

    public Document Document
    {
        get { return this._document ?? GetDocument(); }
    }
    

    或其他?

    如果我应该从单个viewmodel的构造函数中调用它,我该怎么做?我不能在构造函数上使用async,也不能在属性上设置async。

    在处理MVVM时,对Web服务进行异步调用的最佳方法是什么。

    1. 同样,我不确定哪个最好:

      • 4.1显示某种进度条,请求所有4个请求并等待所有这些请求完成,然后隐藏进度条

      • 4.2在每个单独的视图中显示某种进度条,并在每个请求完成后相应地隐藏它们

    2. 最后一个问题......挂。我已经准备了很多关于异步和挂起的文章,但是他们总是在处理点击事件时描述问题,但是当你没有点击事件但是你想打电话时我不明白如何处理这个问题这在初始化viewmodel时。如果您知道如何,请解释并提供一个简单的例子。

1 个答案:

答案 0 :(得分:2)

要记住不同的问题:

  1. 代码结构。通常,您希望为模块化结构限制视图和视图模型的范围。 (这也称为封装。)
  2. 用户体验响应能力。您不希望让用户等待,如果他们必须等待,则向他们显示进度条/状态指示器。
  3. 数据使用情况。用户可能处于数据连接状态,因此您希望保守数据使用。
  4. 所以,问题是:

    • 立即加载所有数据,或
    • 仅在用户滑动到给定视图时加载

    在#2和#3之间进行权衡。这真的是一个判断调用,取决于你希望应用程序有什么样的感觉。

      

    我不确定是否应该从PivotMainViewModel或为每个数据透视表项定义的每个单独的视图模型进行所有异步调用

    我认为上面的#1意味着后者 - 如果可能的话,每个视图模型应该拥有自己的数据,以便进行封装。


    编辑要在属性上使用async,您必须使用setter,而不是getter。挂钩到视图模型的“初始化”事件(或类似):

    public Document Document
    {
        get { return this._document; }
        set
        {
            if (this._document == value)
                return;
            this._document = value;
            RaisePropertyChanged("Document");
        }
    }
    
    public async Task<Document> GetDocument
    {
        // ...
    }
    
    private async Task LoadData()
    {
        Document = GetDocument();
    }
    
    public void Initialize() 
    {
        LoadData();
    }