こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

[C#]DataGridViewのVirtual Modeについて

DataGridViewのVirtual Modeをtrueにしてデータを表示させています。
DataGridViewのRowCountを設定すると、件数が多い(数万件以上)場合に、CPUの使用率が高くなり、動作が遅くなってしまいます。

例:
Dgview.RowCount = 100000;

画面に表示されているセルに関係なく、すべてのセルについてCellValueNeededイベントが発生してしまっているようなのですが、その原因がつかめません。

画面に表示されているセルのCellValueNeededが優先的に発生するようで、データ自体は正常に表示されます。
しかし、画面上のセル分のイベントが終わると、また続きからCellValueNeededイベントが再開されてしまいます。
セルの値はDataTable変数に一度値を格納したものをセルごとに取得しています。

試しに、100000件のDataGridViewのみを表示するプログラムを作成した場合、正常に動作しました。
現在作成中のプログラムでのバグ?のようです。
他に特別なイベントが発生している形跡は自分の確認した限りでは見られません。

説明下手で申し訳ありませんが、原因のわかる方、回答お願いします。

投稿日時 - 2009-07-22 16:16:16

QNo.5146395

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

RowCountを設定する前に、一旦DataGridView.Rows.Clear()でRowsコレクションを空にします。
そうすれば仮想行に関連する不必要なイベントが起こりません。
質問の目的が、行数設定(変更)による遅延の解消なら、これで解決すると思います。
ただし、行選択の状態も消失してしまいます。
仮想行数変更後も行選択の状態を維持する必要があるなら、別途実装する必要があります。

投稿日時 - 2009-07-30 23:00:23

お礼

回答ありがとうございました。

投稿日時 - 2009-08-04 13:26:29

ANo.1

 こんばんは。
 断言は出来ませんが、実行中に
 Dgview.RowCount = 100000;
 を実行すると、拡大されたセルの分だけCellValueNeededイベントが発生しています。
 その際、帳尻あわせをする為にデータテーブルの件数も拡大する処理をしていませんか(要は其処が重たい原因ではないかと)。
 以下の様にしてボタンを押した瞬間にセルとデータテーブルを10万件まで拡大して見ましたが、一定時間重たくなります。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication
{
public partial class Form1 : Form
{
DataTable dataTable1;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//テーブルの作成
dataTable1 = new DataTable();
dataTable1.Columns.Add();
dataTable1.Columns.Add();

//テーブルにデータを25件まで拡大
ExpandRowRange(25);

//セルを50件まで拡大
dataGridView1.ColumnCount = 2;
dataGridView1.RowCount = 50;
}

private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
//セルの位置がテーブル件数を超えているので引き返す
if (e.RowIndex >= dataTable1.Rows.Count ||
e.ColumnIndex >= dataTable1.Columns.Count)
return;

e.Value = dataTable1.Rows[e.RowIndex][e.ColumnIndex];
}

private void dataGridView1_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
{
if (e.Value == null)
return;

//セルの位置がテーブル件数を超えているので、テーブル件数を拡大する
if (e.RowIndex >= dataTable1.Rows.Count)
ExpandRowRange(e.RowIndex + 1);

dataTable1.Rows[e.RowIndex][e.ColumnIndex] = e.Value;
}

private void button1_Click(object sender, EventArgs e)
{
//テーブル件数を10万件まで拡大する(重たい)
ExpandRowRange(100000);

//セルを10万件まで拡大する
dataGridView1.RowCount = 100000;
}

private void ExpandRowRange(int index)
{
for (int i = dataTable1.Rows.Count; i < index; ++i)
dataTable1.Rows.Add(new Object[] { i.ToString(), "データ" + i.ToString() });
}
}
}

 データテーブルの代わりに
 http://msdn.microsoft.com/ja-jp/library/3eayzh46(VS.80).aspx
 を使えば負担が軽減するかもしれません。

投稿日時 - 2009-07-22 20:50:36

お礼

遅レスですが、自己解決したので、一応原因を書き留めておきます。

DataGridViewの「ColumnHeaderHeightSizeMode」プロパティと「AutoSizeColumnMode」プロパティを初期値から変更すると、すべてのセルで「CellValueNeeded」イベントが発生してしまうようでした。
この2つを初期値に戻すことで、画面に表示されるセルのみについて「CellValueNeeded」プロパティが発生するようになりました。

データテーブルには、RowCountを設定する前に値を10万件分保存していて、その際の処理は必要なものだと認識していましたが、リンク先も参考にさせていただきます。

投稿日時 - 2009-08-04 13:25:59

あなたにオススメの質問