2017年5月5日金曜日

[メモ] C#.net/VB.net DataGridViewが遅い・部分的に更新したい

個人的メモ。
現在帰宅してから個人的に使用するファイル整理ソフト作成中&使用中(要は行き当たりばったりで開発)に行き当たった事象と調べた内容に対する対応策。
この手の事ってアプリを作り始めの時しか気にしないことがほとんどなので毎回調べる事になるんだよね…

[環境]
アプリはSSD上で実行。開発はvmware-ESXi上のWindows10/VisualStudioCommunity2015をリモートデスクトップ経由。DBにSQLite。

[事象]
10列10万行ほどあるdatagridviewの表示・スクロールなどいろいろ遅い


[対応]
下記の組み合わせ。とりあえずコレでチェックボックス付き10列10万行が読み込み一瞬(こっちは主にSSDのおかげ)、スクロールも快適。
実際に対応した順は4→1→3→2の順。

1.Virtual=true
datagridviewにbindしたdatasourceへの値取得が表示時に都度取得されるようになる。
なので初期表示が速くなる。が、そのままだと当然スクロール時に遅くなる。

2.DoubleBuffered=true
デフォルトの状態だとdatagridの描画が値取得の度に更新される。
trueの場合、描画範囲の値を取得し終わってから画面が更新される。
virtual=trueに寄り値の取得が都度行われる+描画も値取得の都度行われるため、DoubleBufferd=trueにすることにより描画を値取得後一度のみにする。
ただし、リモートデスクトップ経由で操作する場合、trueじゃない方が的な話も海外の掲示版に記述が見られる。
が、テストで数十~数百いじる分には気にする必要なし。そもそも外部公開されてないプロパティなので変更することによる不都合に気がつかなくなるリスクの方が大きい。
このプロパティはprotectedなので外部から無理矢理たたく。
this.dataGrid.GetType().InvokeMember("DoubleBuffered",BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,null,this.dataGrid,new object[] { true });

3.datagridにbindするソースをList<Object>にする
Virtual=trueで値の取得が描画時になるため、よく使われる(中身が複雑怪奇な)datatable/datarowは都合がよろしくない。処理量を削るため、シンプルにする。

4.AutoGenerateColumns=false/AutoSizeColumnsMode=None/AutoSizeRowsMode=None
全部無効。
この手のauto物は何かする度に評価されるのでこれらが有効だと劇的に遅くなる。


[やりたいこと]
行の値更新時、その内容をピンポイントで反映する。いちいち読み込み直しだとスクロールバーの位置制御がめんどくさすぎる

[対応]
BindingSourceを間に挟む。
例)一覧の設定
BindingSourceはクラス変数として定義。(datagridからいちいち取得しなおすのめんどくさい)
this.filesBindingSource = new BindingSource();
this.filesBindingSource.DataSource = new List<String>();
this.dataGrid.DataSource = this.filesBindingSource;

例)値の加工と反映時
値の更新はBindingSouceに対し指示する。このとき何番目のという内容が必要なのでいきなり行に紐付いた実際に使用するオブジェクトではなく、行番号を持っているDataGridViewRowを取得しておく。
var list = (from DataGridViewRow a in this.dataGrid.SelectedRows where ((aaa)a.DataBoundItem).selected select a).ToList();
foreach (var _elem in list)
{
var elem = (aaa)_elem.DataBoundItem;
//elemに対して値更新
//datagridviewに更新を通知
this.filesBindingSource.ResetItem(_elem.Index);
}



…どうでもいいけどdatatableは…あまり便利だとは思わない…まぁこれだけあればいいだろう的な機能は一通り乗ってるけどいろいろ汎用化のおかげか使い方が妙にめんどくさいし何よりでかくて重い

0 件のコメント:

コメントを投稿