2009-06-16 19 views
2

MVVMを使用してwpfアプリケーションを構築しています。WPFデータバインディングのパフォーマンス

public class AssignmentsViewModel 
{ 

    List<AssignmentViewModel> _Assignments; 
    public List<AssignmentViewModel> Assignments 
    { 
     get 
     { 
      if (_Assignments == null) 
       _Assignments = new List<AssignmentViewModel>(Data.GetAssignments()); 
      return _Assignments; 
     } 
     set { _Assignments = value; } 
    } 
} 
public class AssignmentViewModel 
{ 
    List<NoteViewModel> _Notes; 
    public List<NoteViewModel> Notes 
    { 
     get 
     { 
      if (_Notes == null) 
       _Notes = new List<NoteViewModel>(Data.GetNotes()); 
      return _Notes; 
     } 
     set { _Notes = value; } 
    } 
} 

ビューはDataTemplateを持つリストボックスにListViewコントロールでAssignmentViewModelsとノートを持っている:私は以下のようなのviewmodels採用遅延ロードを持っています。

160個のアイテムを持つAssignmentViewModelsのいずれかを表示すると、読み込むのに1000ミリ秒かかります。私はそれが150万行のデータベーステーブルから取得するNotesプロパティのためだと考えました。私はそれをチェックし、ノーツリストを埋めるために60ミリ秒かかりました。だから私はそれがリストボックスに160項目を読み込むのデータバインディングだと思います。しかし、それはそうであってはならない。なぜなら、listBoxesはそのコンテンツを仮想化するからだ(私はそれをスヌープし、アイテムがバーチャライズのスタックパネルにあることを確認した)。

私は紛失しています。余分な940ミリ秒をどのように取っているかを知る方法はわかりません。

これを追跡するにはどうすればよいですか?パフォーマンスが重要であり、改善方法はわかりません。

答えて

3

UIがどのようなものかわからないと、UIからの何かがBitmapEffectsの大量使用のように減速する可能性があります。

また、リストをObservableCollectionに切り替えたい場合は、binding to that can be significantly faster then a Listとしてください。

また、あなたに役立つ良いperformance profilingツールがあります。

+0

これらのパフォーマンスプロファイリングリンクをありがとうございました。私は今それらを使う方法を学ぶ必要があります。 :) – Jose

2

XAMLが表示されますか?

リストボックスをスタックパネル(または同様のコントロール)内に置いている場合、リストボックスはそのエントリを仮想化しません。

これは、仮想化されます:

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <Label Grid.Row=0>Your label here</Label> 
    <ListBox Grid.Row=1 Your properties here... /> 

</Grid> 

これはしません:リストボックスは、その最大の高さにレンダリングしてスクロールするのStackPanelに依存しますStackPanelの内側

<StackPanel> 
    <Label>Your label here</Label> 
    <ListBox Your properties here... /> 
</StackPanel> 

を。 (仮想化なし)

グリッド内では、リストボックスはグリッドの行の高さにレンダリングされ、独自のスクロールバーを使用します。 (バーチャライズ)

リストボックスに高さプロパティまたはMaxHeightプロパティを設定することもできますが、スタックパネルを使用している場合は、何らかの自動サイズ設定が必要と思われます。

グリッドの内側にスタックパネルを置くことによって不正行為をすることはできません。あなたのリストボックスはどこかから最大の高さを引き出すことができなければなりません。

0

遅延ロードを使用せずにperf-testingを試しましたか?

また、アイテムのDataTemplates/Viewsはどれほど複雑ですか?シンプルなTextBlock表現を使ってテストを実行して、あなたのビューがどのくらい複雑でないかを確認してください。

0

SQLをもう一度見て、コレクションが充実していることを確認します。結果を列挙するまでL2Sは実際には入力されません。

private IEnumerable<Thing> Method1() 
{ 
    return _db.Things.Where(t => t.ID > 500); 
} 
private void Method2() 
{ 
    var things = Method1(); // here, 'things' doesn't really contain anything 
          // even though you've already done the db fetch 
    foreach (var thing in things) // 'things' gets populated here. 
    { 
     // do something 
    } 
} 

例:データが返された直後に.ToList()を呼び出します。データ層には、ビジネス層やUI層まではまだ起きていないアクティビティがたくさんあります。

+0

ええ、私は理解して、GetNotes関数は、リストを反復処理します。 – Jose

0

私はそれを理解しました。テキストラブを必要とするテキストブロックがありました。私は明示的にそれがラップされるように、データ・テンプレート内に幅を設定し、何らかの理由でListBox内のVirtualizingStackPanelがリスト内のすべての項目を認識するようにします。私は、これは、リストボックスがすぐにロードさせ

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="3*" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
    <Grid Grid.Column="0"> 
     .... 
    </Grid> 
    <ListBox Grid.Column="1" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" > 
     ...//DataTemplate 
    </ListBox> 
</Grid> 

...そうのようなグリッドにそれに合わせて、それを再加工しました。彼らが正しい道を私にもたらしたあなたの答えに感謝します。

関連する問題