我有一个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);
}
}
}
问题是这会导致以下异常:
“集合已被修改;枚举操作可能无法执行。”
我意识到发生这种情况是因为调用SetOrdinal方法导致再次调用事件处理程序,因为DataTable绑定到DataGridView。所以我把它改成了以下内容:
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属性setter中抛出NullReferenceException。这是callstack:
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。这可能不太理想,因为为每个受影响的列调用一次处理程序(即总是不止一次),并且在列重新排序开始时我似乎没有任何事件可以告诉我并完成了。
我完全可以使用它的唯一方法是执行以下操作(请注意副本):
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;
}
}
}
我真的不想做这个副本,因为数据可能非常大。
如果没有副本,我有什么方法可以做到这一点吗?
答案 0 :(得分: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);
}