Windows フォーム DataGridView コントロールを拡張するための推奨される手順
更新 : 2007 年 11 月
DataGridView コントロールは、最大のスケーラビリティを提供するようにデザインされています。大量のデータを表示する必要がある場合は、このトピックのガイドラインに従って、大量のメモリ消費やユーザー インターフェイス (UI) の応答速度低下を回避することが必要です。このトピックでは、次の項目について説明します。
セル スタイルの効率的な使用
ショートカット メニューの効率的な使用
自動サイズ変更の効率的な使用
選択されているセル、行、および列のコレクションの効率的な使用
共有行の使用
行が非共有になることの防止
特別なパフォーマンス要件がある場合には、仮想モードを実装し、独自のデータ管理操作を提供できます。詳細については、「Windows フォーム DataGridView コントロールでのデータ表示モード」を参照してください。
セル スタイルの効率的な使用
各セル、各行、および各列に、個別のスタイル情報を設定できます。スタイル情報は、DataGridViewCellStyle オブジェクトに格納されます。多数の DataGridView 要素それぞれについてセル スタイル オブジェクトを作成することは、特に大量のデータを処理する場合、非効率的です。パフォーマンスへの影響を回避するには、次のガイドラインに従います。
個々の DataGridViewCell オブジェクトまたは DataGridViewRow オブジェクトにセル スタイル プロパティを設定することは避けます。これには、RowTemplate プロパティで指定された行オブジェクトも含まれます。行テンプレートから新しい行を複製すると、それぞれの行にテンプレートのセル スタイル オブジェクトのコピーが作成されます。スケーラビリティを最大にするには、セル スタイル プロパティの設定を DataGridView レベルで行います。たとえば、DataGridViewCell.Style プロパティではなく DataGridView.DefaultCellStyle プロパティを設定します。
既定の書式設定以外の書式設定を必要とするセルがある場合、セル、行、または列の複数のグループで同じ DataGridViewCellStyle インスタンスを使用します。個別のセル、行、および列で DataGridViewCellStyle 型プロパティを直接設定することは避けます。セル スタイルを共有する例については、「方法 : Windows フォーム DataGridView コントロールの既定のセル スタイルを設定する」を参照してください。CellFormatting イベント ハンドラを処理してセル スタイルを個別に設定することでも、パフォーマンス低下を回避できます。カスタマイズ例については、「方法 : Windows フォーム DataGridView コントロールのデータの書式設定をカスタマイズする」を参照してください。
セルのスタイルを確認するときは、DataGridViewCell.Style プロパティではなく DataGridViewCell.InheritedStyle プロパティを使用します。Style プロパティにアクセスすると、そのプロパティがまだ使用されていない場合は DataGridViewCellStyle クラスの新しいインスタンスが作成されます。また、行、列、またはコントロールからスタイルを継承している場合は、このオブジェクトにセルの一部のスタイル情報が含まれないことがあります。セル スタイルの継承の詳細については、「Windows フォーム DataGridView コントロールでのセルのスタイル」を参照してください。
ショートカット メニューの効率的な使用
各セル、各行、および各列に、個別のショートカット メニューを設定できます。DataGridView コントロールのショートカット メニューは、ContextMenuStrip コントロールで表されます。セル スタイル オブジェクトと同様、多数の DataGridView 要素それぞれについてショートカット メニューを作成すると、パフォーマンスの低下を招きます。このような影響を回避するには、次のガイドラインに従います。
個々のセルおよび行にショートカット メニューを作成することは避けます。行テンプレートも同様です。行テンプレートは、コントロールに新しい行が追加されるときに複製され、このときショートカット メニューも同時に複製されます。スケーラビリティを最大にするには、コントロールの ContextMenuStrip プロパティのみを使用して、コントロール全体に単一のショートカット メニューを指定します。
複数の行またはセルについて複数のショートカット メニューが必要な場合は、CellContextMenuStripNeeded イベントまたは RowContextMenuStripNeeded イベントを処理します。これらのイベントでショートカット メニュー オブジェクトを操作することで、パフォーマンスを調整できます。
自動サイズ変更の効率的な使用
セルの内容を変更すると、内容全体が欠けることなく表示されるように、行、列、およびヘッダーのサイズが自動的に変更されることがあります。サイズ変更モードを変更した場合も、行、列、およびヘッダーのサイズが変更される場合があります。DataGridView コントロールは、正しいサイズを決定するために、各セルが格納する値を調べます。大量のデータを処理する場合には、自動サイズ変更が発生してこの解析が行われることによって、パフォーマンスが低下する可能性があります。パフォーマンスの低下を回避するには、次のガイドラインに従います。
大量の行セットを処理する DataGridView コントロールでは、自動サイズ変更の使用を避けます。自動サイズ変更を使用する場合も、表示されている行に基づくサイズ変更のみにします。仮想モードでも、表示されている行のみを使用します。
行および列に対して、DataGridViewAutoSizeRowsMode、DataGridViewAutoSizeColumnsMode、および DataGridViewAutoSizeColumnMode の各列挙値の DisplayedCells フィールドまたは DisplayedCellsExceptHeaders フィールドを使用します。
行ヘッダーに、DataGridViewRowHeadersWidthSizeMode 列挙値の AutoSizeToDisplayedHeaders フィールドまたは AutoSizeToFirstHeader フィールドを使用します。
スケーラビリティを最大にするには、自動サイズ変更を無効にし、プログラムによるサイズ変更を使用します。
詳細については、「Windows フォーム DataGridView コントロールのサイズ変更オプション」を参照してください。
選択されているセル、行、および列のコレクションの効率的な使用
SelectedCells コレクションは、選択範囲のサイズが大きいと効率が低下します。SelectedRows コレクションおよび SelectedColumns コレクションの効率も低下する場合がありますが、通常の DataGridView コントロールではセルの数よりも行の数が少なく、行の数よりも列の数が少ないため、低下の度合いは小さくなります。これらのコレクション処理時のパフォーマンスの低下を回避するには、次のガイドラインに従います。
SelectedCells コレクションの内容にアクセスする前に DataGridView 内のすべてのセルが選択されているかどうかを確認するには、AreAllCellsSelected メソッドの戻り値をチェックします。ただし、このメソッドを使用すると、行が非共有になることがあります。詳細については、次のセクションを参照してください。
選択されているセルの数を調べる場合は、System.Windows.Forms.DataGridViewSelectedCellCollection の Count プロパティの使用を避けます。代わりに、DataGridView.GetCellCount メソッドを使用して、DataGridViewElementStates.Selected 値を渡します。同様に、選択されている要素の数を調べる場合は、選択されている行および列のコレクションにアクセスするのではなく、DataGridViewRowCollection.GetRowCount メソッドおよび DataGridViewColumnCollection.GetColumnCount メソッドを使用します。
セルに基づく選択を行うモードの使用を避けます。代わりに、DataGridView.SelectionMode プロパティを DataGridViewSelectionMode.FullRowSelect または DataGridViewSelectionMode.FullColumnSelect に設定します。
共有行の使用
共有行を使用すると、DataGridView コントロールでメモリを効率的に使用できます。複数の行で DataGridViewRow クラスのインスタンスを共有すると、行の表示形式と動作に関する情報が最大限共有されます。
行のインスタンスを共有するとメモリを節約できる一方、行は非共有になりやすくなります。たとえば、ユーザーがセルを直接操作すると、そのセルの行は非共有になります。この動作は避けられないので、このトピックで示すガイドラインが役立つのは、大量のデータを処理する場合、およびプログラムを実行するたびにユーザーが操作するデータの割合が比較的小さい場合に限られます。
バインドされていない DataGridView コントロール内で、値を含むセルがある行は共有できません。DataGridView コントロールを外部データ ソースにバインドしている場合、または仮想モードを実装して独自のデータ ソースを指定している場合は、セルの値はセル オブジェクトではなくコントロールの外部に格納されるので、行を共有できます。
行オブジェクトは、その行のすべてのセルの状態が、それらのセルを含む行の状態および列の状態から決定できる場合に限り、共有できます。セルの状態が変更され、そのセルの行および列の状態からセルの状態を推測できなくなった場合は、行を共有できません。
たとえば、次のいずれかの状況にある行は共有できません。
選択されている列に含まれていない、単一選択されたセルを含む行。
ToolTipText プロパティまたは ContextMenuStrip プロパティが設定されているセルを含む行。
Items プロパティが設定されている DataGridViewComboBoxCell を含む行。
バインド モードまたは仮想モードでは、CellToolTipTextNeeded イベントおよび CellContextMenuStripNeeded イベントを処理することで、ツールヒントおよびショートカット メニューを個別のセルに指定できます。
DataGridView コントロールは、DataGridViewRowCollection に行が追加されるたびに、自動的に共有行を使用しようとします。行が確実に共有されるようにするには、次のガイドラインに従います。
DataGridView.Rows コレクションの Add メソッドの Add(Object[]) オーバーロードおよび Insert メソッドの Insert(Object[]) オーバーロードを呼び出さないようにします。これらのオーバーロードは、自動的に非共有行を作成します。
DataGridView.RowTemplate プロパティに指定されている行は、次の場合に共有できます。
DataGridView.Rows コレクションの Add メソッドの Add() オーバーロードまたは Add(Int32) オーバーロード、または Insert メソッドの Insert(Int32,Int32) オーバーロードを呼び出すとき。
DataGridView.RowCount プロパティの値を増加させるとき。
DataGridView.DataSource プロパティを設定するとき。
DataGridView.Rows コレクションの AddCopy、AddCopies、InsertCopy、および InsertCopies の各メソッドを呼び出す場合は、indexSource パラメータで指定される行が共有可能であることを確認してください。
DataGridView.Rows コレクションの Add メソッドの Add(DataGridViewRow) オーバーロード、AddRange メソッド、Insert メソッドの Insert(Int32,DataGridViewRow) オーバーロード、および InsertRange メソッドを呼び出す場合は、指定される行が共有可能であることを確認してください。
行が共有されているかどうかを確認するには、DataGridViewRowCollection.SharedRow メソッドを使用して行オブジェクトを取得し、そのオブジェクトの Index プロパティを調べます。共有行の Index プロパティの値は常に –1 です。
行が非共有になることの防止
共有行がコードまたはユーザー操作の結果として非共有行になることがあります。パフォーマンスへの影響を回避するには、行が非共有にならないようにする必要があります。アプリケーション開発時に RowUnshared イベントを使用すると、行が非共有行になるときを確認できます。これは、行の共有の問題をデバッグする際に便利です。
行が非共有にならないようにするには、次のガイドラインに従います。
Rows コレクションに対して、インデックスを指定したり、foreach ループで反復処理したりすることを避けます。通常は、行に直接アクセスする必要はありません。行を操作する DataGridView のメソッドは、行のインスタンスではなく行インデックスを引数として使用します。また、行に関連するイベントのハンドラは、行プロパティを持つイベント引数オブジェクトを受け取ります。これを使用することで、行を非共有にすることなく操作できます。
行オブジェクトにアクセスする必要がある場合は、DataGridViewRowCollection.SharedRow メソッドを使用し、行の実際のインデックスを渡します。ただし、このメソッドで取得した共有行オブジェクトを変更すると、そのオブジェクトを共有するすべての行が変更されます。一方、新しいレコードの行は、他の行と共有されないため、他のいずれかの行を変更しても影響を受けません。また、同じ共有行で表される複数の行が、それぞれ異なるショートカット メニューを持つ場合があります。共有行のインスタンスから正しいショートカット メニューを取得するには、GetContextMenuStrip メソッドを使用し、行の実際のインデックスを渡します。そうせずに、共有行の ContextMenuStrip プロパティにアクセスすると、共有行のインデックス -1 が使用され、正しいショートカット メニューを取得できません。
DataGridViewRow.Cells コレクションにインデックスを指定しないようにします。セルに直接アクセスすると、そのセルの親となる行が非共有になり、新しい DataGridViewRow のインスタンスが作成されます。セルに関連するイベントのハンドラは、セル プロパティを持つイベント引数オブジェクトを受け取ります。これを使用することで、行を非共有にすることなくセルを操作できます。また、CurrentCellAddress プロパティを使用すると、セルに直接アクセスすることなく、現在のセルの行と列のインデックスを取得できます。
セルに基づく選択を行うモードの使用を避けます。このようなモードでは、行が非共有になります。代わりに、DataGridView.SelectionMode プロパティを DataGridViewSelectionMode.FullRowSelect または DataGridViewSelectionMode.FullColumnSelect に設定します。
DataGridViewRowCollection.CollectionChanged イベントまたは DataGridView.RowStateChanged イベントを処理しないでください。これらのイベントでは、行が非共有になります。また、DataGridViewRowCollection.OnCollectionChanged メソッドまたは DataGridView.OnRowStateChanged メソッドを呼び出さないでください。呼び出すと、これらのイベントが発生します。
DataGridView.SelectionMode プロパティの値が FullColumnSelect、ColumnHeaderSelect、FullRowSelect、または RowHeaderSelect の場合は、DataGridView.SelectedCells コレクションにアクセスしないでください。アクセスすると、選択されているすべての行が非共有になります。
DataGridView.AreAllCellsSelected メソッドを呼び出さないでください。このメソッドを呼び出すと、行が非共有になります。
DataGridView.SelectionMode プロパティの値が CellSelect の場合は、DataGridView.SelectAll メソッドを呼び出さないでください。呼び出すと、すべての行が非共有になります。
セルの ReadOnly プロパティまたは Selected プロパティは、その列の対応するプロパティが true に設定されているときは false に設定しないでください。そのように設定すると、すべての行が非共有になります。
DataGridViewRowCollection.List プロパティにアクセスしないでください。アクセスすると、すべての行が非共有になります。
Sort メソッドの Sort(IComparer) オーバーロードを呼び出さないでください。カスタム比較で並べ替えを行うと、すべての行が非共有になります。
参照
処理手順
方法 : Windows フォーム DataGridView コントロールの既定のセル スタイルを設定する
概念
Windows フォーム DataGridView コントロールでの仮想モード
Windows フォーム DataGridView コントロールでのデータ表示モード
Windows フォーム DataGridView コントロールでのセルのスタイル
Windows フォーム DataGridView コントロールのサイズ変更オプション