

現在、WPF+XAML+MVVMでアプリケーションを開発しています。

WPFのDataGridコントロールは大量のデータをBindすると描画に時間がかかるという既知の問題(仕様…)があります。

そのため、仮想化(VirtualMode)の機能が提供されていますが、ある程度は速くなったものの、それでも画期的に速くはできませんでした。  
そこで割り切って、DataGridの描画中はインジケーターを表示して、ユーザーに可能な限り遅く見せないような工夫をしようと考えているのですが、  
UIスレッドがDataGridによって占有されるためか、インジケーターまで固まってしまう問題が発生します。

[![サンプルプログラム](https://i.stack.imgur.com/JnXRd.gif)](https://i.stack.imgur.com/JnXRd.gif)  
(↑検証用に作ったプログラムを動かしているところ。「実行」ボタンをクリックすると、画面右側のDataGridにBindします。この時、画面左側のインジケーターに見立てたImageコントロールのアニメーションが一瞬固まってしまいます)

[![画像の説明をここに入力](https://i.stack.imgur.com/3k7yL.png)](https://i.stack.imgur.com/3k7yL.png)  
(↑パフォーマンスプロファイラーの結果もUPします。DataGridのレイアウト処理だけで1秒かかり、UIスレッドが占有されてしまっています）

インジケーターを固まらないようにする、良いアイデアはございますでしょうか？  
UIスレッドを並列化できる方法があれば一番望ましいのですが...

サードパーティー製のDataGridを使うという方法もありますが(某C社などは30%速くなるみたいなことを謳っていたりもしますが)、標準のコントロールで済ませたいです。  
また、DataGridに大量のデータをBindする行為自体はマストです。データ量を減らせ等の御意見はあるかと思いますが…。

ご教示よろしくお願いいたします。


CC BY-SA 3.0
2017-03-17T07:33:12.453
33386
2017-03-27T16:28:36.857
2017-03-17T07:59:43.413
20991
20991
question
c# wpf xaml mvvm
DataGridによって、他のコントロールの描画が固まってしまうのを回避する方法はありますか？


はじめまして。  
DataGrid にデータを表示するだけなら、データテンプレートでカスタマイズした ListBox
等を使えば、コントロールが軽量な分、よりパフォーマンスが向上するのではないでしょうか。


CC BY-SA 3.0
2017-03-22T05:19:26.960
33450
2017-03-22T05:19:26.960
19617
33386
answer


全件挿入が終わるまでの時間は伸びてしまいますが、  
`ObservableCollection<>`に1件ずつ`Dispatcher.BeginInvoke`して追加してみてはどうでしょうか。

例えばボタンのクリック時に以下のようなコードを書いてみます。  
別スレッドから`Dispatcher.BeginInvoke`で適当なViewModelの`ObservableCollection<>`に追加しています。  
`DispatcherPriority.Background`ならUIの応答性をそこまで阻害しないかと。

[code]

    Thread thread = new Thread(new ThreadStart(delegate
    {
        for (int i = 0; i < 100000; ++i)
        {
            int count = i;
            Dispatcher.BeginInvoke(
                (Action)delegate
                {
                    // ObservableCollection<DummyRow> に挿入
                    viewModel.DummyCollection.Add(new DummyRow
                    {
                        Key = @"Key" + count,
                        Name = @"Name" + count,
                        Value = @"Value" + count,
                        Comment = @"Comment" + count,                            
                    });
                }, 
                DispatcherPriority.Background);
        }
    }));
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    
[/code]


CC BY-SA 3.0
2017-03-27T16:28:36.857
33588
2017-03-27T16:28:36.857
70
33386
answer