2011-06-29 10 views
10

私はMVVMをかなり使い慣れているので、この問題によく知られている解決策があればよろしくお願いいたします。MVVMモデルのノンブロッキング遅延ロードプロパティ

私たちは、いくつかの追加のプロパティだけでなく、必要に応じてWeb API呼び出しを行うことで遅延ロードすることができるいくつかのコアプロパティを持つモデルクラスを構築しています(更新: lazily-loadedプロパティごとのWeb APIコールとなります)。

複数のモデルを用意するのではなく、そこにレイジーロードロジックを持つ単一のモデルを用意することが賢明です。しかし、レイジーロードされたプロパティは、ViewModelにバインドしてモデルにバインドするときにUIスレッドをブロックしないように、アクセス時にブロックするべきではないようです。

このように、モデルの遅延プロパティにアクセスすると、非同期フェッチを開始してすぐにデフォルト値(たとえばnull)が返されるようなパターンが考えられました。非同期フェッチが完了すると、PropertyChangedイベントが発生し、ViewModel/Viewはフェッチされた値に再バインドできます。

は、私はこれを試してみたのだが、非常にうまく動作するようだが、思っていた:

  1. が、私はまだ知ったしていないこのアプローチのいずれかの落とし穴がありますが、ように実行されますアプリは複雑になりますか?
  2. フレームワークに組み込まれている、または第三者フレームワークの一部として広く使用されているこの問題に対する既存のソリューションはありますか?
+0

これらのローズローダーのすべてでPropertyChangedイベントをリッスンする必要があります。つまり、これらのローダーの複数に依存するプロパティまたは関数がある場合、独自のコードを実行する前に、依存するすべてのローダーが終了するまで待ちます。 これは、そうでなければ、別のスレッド内で "同期的に"レイジーローダをフェッチすることを組み合わせた単一のスレッドコールとして記述された多くのロジックを記述しなければならなくなる可能性があります。 –

+0

@ティモシー - 良い点。私はすでにそれについて考えていましたが、遅れてロードされたデータの性質上、何かが遅延データの複数の部分に依存する可能性は低いと感じています。 1つの遅延データに複数のものが依存する可能性は高いですが、問題はないと思います。 –

+0

私はあなたが上で説明した正確なアプローチを使用し、それは非常にうまくいっています。 – Jeff

答えて

6

これまで私はこのようなことをしていましたが、私が忘れていたことは、非同期プロパティを呼び出すことができず、値を持つことを期待しています。

Customer.Productsのリストを遅延ロードすると、最初に値がNULLまたは0(ブランクコレクションを作成するかどうかによって異なります)と呼ばれるため、Customer.Products.Countをコードビハインドで参照することはできません。

これ以外にも、バインディングには効果的でした。私は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メソッドを2回呼び出すと、asyncメソッドが2回実行されることを望みませんでした。

すべての非同期プロパティに対してIs[AsyncPropertyName]Loading/edプロパティを設定し、最初の非同期呼び出し中にtrueに設定することでこれを解決しましたが、すべての非同期プロパティの追加プロパティを作成する必要はありませんでした。

+0

*(構文の強調表示を追加)* –