DataGridView があり、AllowUserToOrderColumns プロパティを有効にして、ユーザーがドラッグ アンド ドロップを使用して列を並べ替えることができるようにしました。ColumnDisplayIndexChanged イベントのハンドラーを作成しました。DataGridView は DataTable にバインドされます。ユーザーが DataGridView でその列を並べ替えたときに、DataTable の列を並べ替えたいと思います。
これは私がこれまでに得たものです:
private void dataGridView_Main_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
if(!_isDatabinding)
{
if(_data.Columns[columnName].Ordinal != e.Column.DisplayIndex)
{
_data.Columns[e.Column.DataPropertyName].SetOrdinal(e.Column.DisplayIndex);
}
}
}
問題は、これにより次の例外が発生することです。
「コレクションが変更されました。列挙操作が実行されない可能性があります。」
DataTable が DataGridView にバインドされているため、SetOrdinal メソッドを呼び出すとイベント ハンドラーが再度呼び出されるため、これが発生していることに気付きました。そこで、次のように変更しました。
private void dataGridView_Main_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
if(!_isDatabinding && !_isChangingColumnOrder)
{
if(_data.Columns[columnName].Ordinal != e.Column.DisplayIndex)
{
_isChangingColumnOrder = true;
_data.Columns[e.Column.DataPropertyName].SetOrdinal(e.Column.DisplayIndex);
_isChangingColumnOrder = false;
}
}
}
これにより、DataGridViewColumn::DisplayIndex プロパティ セッター内で NullReferenceException がスローされるようになりました。コールスタックは次のとおりです。
System.Windows.Forms.dll!System.Windows.Forms.DataGridViewColumn.DisplayIndex.set(int value) + 0xc5 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.EndColumnRelocation(System.Windows.Forms.MouseEventArgs e, System.Windows.Forms.DataGridView.HitTestInfo hti) + 0x27f bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnMouseUp(System.Windows.Forms.MouseEventArgs e) + 0x3a6 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseUp(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x48b bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0xe14 bytes
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.WndProc(ref System.Windows.Forms.Message m) + 0x134 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 514, System.IntPtr wparam, System.IntPtr lparam) + 0x14c bytes
この例外の原因がわかりません。
また、SetOrdinal を呼び出す前にイベント ハンドラーで DataGridView の DataSource プロパティを null に設定し、メソッドの最後で再バインドしようとしました。並べ替え時に DataTable が DataGridView にバインドされる問題を回避するため。しかし、それでも同じ NullReferenceException がスローされます。影響を受ける列ごとにハンドラーが 1 回 (つまり、常に複数回) 呼び出され、列の並べ替えがいつ開始されたかを通知するために処理できるイベントがないように見えるため、これはおそらく理想的ではありません。そして終了しました。
これを機能させる唯一の方法は、次のことです(コピーに注意してください):
private void dataGridView_Main_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
if(!_isDatabinding)
{
if(_data.Columns[columnName].Ordinal != e.Column.DisplayIndex)
{
var newData = _data.Copy();
newData.Columns[e.Column.DataPropertyName].SetOrdinal(e.Column.DisplayIndex);
_data = newData;
}
}
}
ただし、データが非常に大きくなる可能性があるため、このコピーを実行する必要はありません。
コピーなしでこれを行う方法はありますか?