DataGrid への表示は、VB6 の頃から遅くて、表示更新をしないと早くなるという噂(けど真実)があったりします。
で、.NET になって DataGridView への DataSource プロパティへのバインドをすると早くなる、ってのが定番なんですが(セルへちまちま貼り付けるよりも早くなります…が、測定はしてないので、そのうちに)、なぜか、DataSource プロパティへのバインドをしているのに、とてつもなく遅くなる現象が発覚したので、晒します。
1.10 カラムある DataGridView を作ります。
2.データを作成
/// <summary> /// データ作成 /// </summary> /// <returns></returns> private List<Data> MakeData() { List<Data> lst = new List<Data>(); for (int i = 0; i < 3000; i++) { Data d = new Data(); d.Col1 = i.ToString(); d.Col2 = DateTime.Now.ToString(); d.Col3 = DateTime.Now.ToString(); d.Col4 = DateTime.Now.ToString(); d.Col5 = DateTime.Now.ToString(); d.Col6 = DateTime.Now.ToString(); d.Col7 = DateTime.Now.ToString(); d.Col8 = DateTime.Now.ToString(); d.Col9 = DateTime.Now.ToString(); d.Col10= DateTime.Now.ToString(); lst.Add(d); } return lst;
3.データバインド
private void button1_Click(object sender, EventArgs e) { var lst = MakeData(); // 自動でカラムを作らない dataGridView1.AutoGenerateColumns = false; // 列幅はそのまま dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing; Stopwatch sw = new Stopwatch(); sw.Start(); dataGridView1.DataSource = lst; sw.Stop(); MessageBox.Show(string.Format("経過時間:{0} msec", sw.ElapsedMilliseconds)); // 10 msec 程度 }
普通に作るととても早いのですが…
dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
このように、AutoSizeToAllHeaders を指定して列幅を自動で作成しようとすると。
private void button1_Click(object sender, EventArgs e) { var lst = MakeData(); // 自動でカラムを作らない dataGridView1.AutoGenerateColumns = false; // 列幅を自動調節する dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; Stopwatch sw = new Stopwatch(); sw.Start(); dataGridView1.DataSource = lst; sw.Stop(); MessageBox.Show(string.Format("経過時間:{0} msec", sw.ElapsedMilliseconds)); // 4 分経ってもまだ終わりません。 }
ってな具合に、1000 倍ぐらい遅くなります。
想像するに、DataSource プロパティでバインドしたデータが、1 件加わるごとに AutoSizeToAllHeaders で列幅を調節している感じなんですよね。なので、一度、EnableResizing で計算しないようにしてから、後で AutoSizeToAllHeaders を指定します。
private void button1_Click(object sender, EventArgs e) { var lst = MakeData(); // 自動でカラムを作らない dataGridView1.AutoGenerateColumns = false; // 列幅はそのままに変える dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing; Stopwatch sw = new Stopwatch(); sw.Start(); dataGridView1.DataSource = lst; // 全て入力した後に列幅を自動調節する dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; sw.Stop(); MessageBox.Show(string.Format("経過時間:{0} msec", sw.ElapsedMilliseconds)); // 108 msec 高速に動作する }
解決しました。ありがとうm(__)m
解決してよかったです。
テストのときに数十行では大したことがなくて、実際のデータで数千行を表示させたらとてつもなく遅くなった、というパターンに陥ります。
なぜか、DataGridView って1行追加するごとにヘッダの幅を再計算&再描画しているんですよね。。。ってことで、意外とハマります。