0

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;
        }
    }
}

ただし、データが非常に大きくなる可能性があるため、このコピーを実行する必要はありません。

コピーなしでこれを行う方法はありますか?

4

1 に答える 1

0

datagridviewをdatatableに再バインドする

 DataTable dt = new DataTable();
 foreach(DataGridViewColumn col in dgv.Columns)
    {
   dt.Columns.Add(col.HeaderText);    
    }

   foreach(DataGridViewRow row in dgv.Rows)
   {
     DataRow dRow = dt.NewRow();
    foreach(DataGridViewCell cell in row.Cells)
     {
      dRow[cell.ColumnIndex] = cell.Value;
     }
    dt.Rows.Add(dRow);
   }
于 2013-01-05T05:50:07.600 に答える