【问题标题】:Reordering columns in DataTable via a DataGridView通过 DataGridView 对 DataTable 中的列重新排序
【发布时间】:2013-01-02 23:05:10
【问题描述】:

我有一个 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 属性设置器中引发 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。无论如何,这可能并不理想,因为每个受影响的列都会调用一次处理程序(即总是不止一次),并且似乎没有任何事件我可以处理来告诉我列重新排序何时开始并完成。

我可以让它工作的唯一方法是执行以下操作(注意副本):

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

不过,我真的不想做这个副本,因为数据可能非常大。

有没有什么方法可以在没有副本的情况下做到这一点?

【问题讨论】:

  • 您是否尝试在设置序数之前暂时删除事件处理程序并在之后再次添加它?
  • @TimSchmelter 我没有,但我现在刚刚尝试过,不幸的是它仍然抛出相同的 NullReferenceException。不过好想! :)
  • 你能等到关门吗? stackoverflow.com/questions/10098627/…
  • @Blam 是的,我可能会等到我保存文件并考虑 DGV 的 DisplayIndex 而无需对 DataTable 列进行物理重新排序。如果没有一种简单的方法来处理我正在尝试做的事情,这可能就是我会求助的方法。不过,理想情况下,我希望 DVG 和 DT 保持同步。如果这意味着 DT 副本,那就不值得了。

标签: c# .net data-binding datagridview


【解决方案1】:

重新绑定datagridview到数据表

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

【讨论】:

  • 遍历每一个单元格并不是我的想法;)如果我很高兴做任何形式的复制,那么我会使用我放入的最后一个代码 sn-p问题。我只想能够设置 DataTable 的列的序号。我可能最终会按照@Blam 的建议去做,只在“文件保存时间”使用排序顺序。
  • DataColumn Col1 = dt.Columns.Add("Remove",System.Type.GetType("System.String")); Col1.SetOrdinal(0);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2013-08-08
  • 2011-02-20
  • 2016-04-27
  • 1970-01-01
  • 2022-10-14
  • 2011-10-10
相关资源
最近更新 更多