2011-01-13 11 views
0

私はSilverlightアプリケーションを作成していますが、読み込み時間を改善しようとしています。私のページのロードが、私が最初に私のObservableCollectionを初期化要素が追加されるとObservableCollectionがUIを更新する

は:

 this.MyItems = new ObservableCollection<Item>(); 

私のUIは、私は、コードを通じてのObservableCollectionにバインドするリストボックスです。 In MainPage_Loaded:

 MyList.ItemsSource = App.ViewModel.MyItems; 

私はモデルを私のモデルにバインドします。私はコレクションが空で、残りのUIがロードされ続ける(私の前提が正しいかどうかわからない)ので効率的であると思います。

 DataContext = App.ViewModel; 

は今、私は私のコレクションに項目を追加する:

 for (int i = 0; i < number_of_items; i++) 
     { 
      this.MyItems.Add(myItems[i]); // myItems is a List<Item> already populated 
      Thread.Sleep(20); 
     } 

私の目標は、各リストボックス項目のUIをレンダリングする時間がなるようにスレッドの睡眠を聞かせすることでした。また、一度に1つのアイテムを表示するUIが必要になりました。

結果、リストボックスの要素はすべてまとめて表示されます。 Sleepを1秒に設定すると、ListBoxは要素の数に1秒を掛けた後に値が設定されます。

この操作を最適化するにはどうすればよいですか?無駄な場合は、ListBoxを完全に作成されたObservableCollectionにバインドすることもできます。ありがとう!

+0

VirtualizingStackPanelを使用していますか? – onmyway133

答えて

4

ループをバックグラウンドスレッドに移動してみてください。これを行う一つの方法があります。

Phạm Tiểu Giao - Threads in WP7

を使用すると、UIの更新を派遣する必要があります注意してください。何かのように

Dispatcher.BeginInvoke(() => { this.MyItems.Add(myItems[i]); }); 

一定の時間を使いたい場合はスリープします。期間がの場合、常にが表示の更新に要する時間よりも長いことを確認してください。そうしないと、処理できるよりも速く更新されたUIスレッドがオーバーロードされる可能性があります。

+0

ありがとう、それは私が欲しかったものです: – siger

+0

yw :) ../15char –

+0

私はそれを1000msの間スリープ状態にするとうまくいきますが、100msにすると幾分奇妙な動作が起こります - それはi =のfor(arguemntoutofrange例外がスローされます)、それは同じ時間を何度か追加します。これは100msの睡眠に期待されていますか? 100msでもリストボックスを作成するのが少し遅いので、私は20〜50msが必要だったので変です。 – siger

2

ObservableCollectionにバインドする理由は、INotifyPropertyChangedインターフェイス実装によるプロパティ更新のビルトイン通知が行われるためです。これにより、関連するUI要素(ここではListBox)の再描画が発生する、基礎となるコレクションへの各更新時にイベントが発生します。データテンプレートは、コレクション内の各アイテムに適用される再描画ごとに適用され、データバインディングによって自動的に行われます。あなたのコレクションにアイテムが追加される速度は、別のスレッド上で行うことができるため、すべてのアイテムが追加されるまで負荷が遅延するように見えます。新しいアイテムが追加されたときにスクリーン上に描かれ、無効にされているため、再描画サイクルは視覚的に画面に表示されません。

これは、追加された各アイテムの要素の完全な再描画を遅らせるだけであることを意味します(*追加されるアイテムの数によって、UI全体が各アイテムに再描画される理由が説明されますn * sleepValue時間の間UIスレッドをブロックするThread.Sleepコールがそれぞれ発生しています)。これは、これらの呼び出しが別のスレッドで行われるため、上記のDispatcherオブジェクトを使用する必要がある理由です。これにより、本質的にブロッキング呼び出しを同期させるUIスレッドから再描画することができます。

ここでDispatcherは冗長であり、ディスパッチャーがまだ作成されていない要素を参照している可能性があるため、ここでは絶対に使用しません。値を1000msに設定して20msに設定してください)。コレクションに含まれるすべてのアイテムを再描画して、睡眠呼出しを無効にしたり、機能不全にしたりすることがあります。

私が代替ソリューションとして提供しているのは、データテンプレートのルート要素の不透明度プロパティにストーリーボードアニメーションを追加して、何かを行うアイテムの視覚効果を作成することができるということです。 "この方法では、各アイテムが基になるコレクションに追加されると、不透明度フェードアニメーションで描画され、別々のアニメーションで(各アニメーション内の異なるオフセットで)各アイテムが一度に1つずつ追加される(そしてアニメーション表示される)定義されたアニメーション)。私はこれがあなたにあなたが探している効果を与えると信じています。しかし、描画呼び出しはアイテムのコレクションを保持しているListBoxから来るので、ViewModelアイテムObservableCollectionオブジェクトへの各.Add呼び出しでコレクション全体が無効になります。実際には、階層内の1つのレベル上流で発生するため、この動作を無効にする方法はありません。私は、提供されたアプローチに対してアドバイスをします。

+0

新しいアイテムがコレクションソースに追加されるたびにListBox自体が再描画されますか? – onmyway133

関連する問題