0

我以编程方式在 DataGridView 中插入一列(即,未绑定到任何数据表/数据库),如下所示:

int lastIndex = m_DGV.Columns.Count - 1;  // Count = 4 in this case
DataGridViewTextBoxColumn col = (DataGridViewTextBoxColumn)m_DGV.Columns[lastIndex];
m_DGV.Columns.RemoveAt(lastIndex);
m_DGV.Columns.Insert(insertIndex, col);  // insertIndex = 2

我发现有时使用这种方法我的列在视觉上是乱序的。一种解决方法是事后手动设置列的 DisplayIndex 属性。添加此代码“修复它”,但我不明白它为什么会这样。

Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 3
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 2
col.DisplayIndex = insertIndex;
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 2
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 3

顺便说一句,我的网格可以动态增加其列数。我想以块的形式增长它,所以每个插入不需要列分配(和相关的初始化)。然后将通过从末尾抓取未使用的列,将其插入所需位置并使其可见来添加每个“新”列。

4

3 回答 3

2

我怀疑这是因为 DataGridView 中列的顺序不一定决定显示顺序,尽管默认情况下没有明确指定列的顺序决定了 DisplayIndex 属性值。这就是为什么有一个 DisplayIndex 属性,因此您可以在不执行插入的情况下将列添加到集合中 - 您只需要指定 DisplayIndex 值,并且对于具有相等或更大 DisplayIndex 的所有内容都会发生级联更新。从您的示例中可以看出,插入的列也收到了第一个跳过的 DisplayIndex 值。

从我发现的问题/答案中:

更改 DisplayIndex 将导致旧 DisplayIndex 和新 DisplayIndex 之间的所有列移动。

与几乎所有集合(LinkedLists 除外)一样,添加到集合中总是比插入集合中更好。您所看到的行为反映了该规则。

于 2008-10-22T21:55:15.810 回答
2

我有几个想法。

  1. 使用唯一名称而不是集合中的索引来寻址您的列怎么样?他们可能还没有名字,但如果你给他们一个有意义的名字,你可以跟踪谁是谁。

  2. 您可以使用该类的GetFirstColumn, GetNextColumn, GetPreviousColumn,GetLastColumn方法DataGridViewColumnCollection,这些方法适用于显示顺序,而不是集合中的顺序。您也可以使用 for 循环遍历集合,m_DGV.Columns[i]直到找到所需的集合。

  3. 创建一个继承的DataGridViewand DataGridViewColumnCollection。简单地被覆盖以使用您的DataGridView新集合类。您的 newDataGridViewColumnCollection将包括一种通过显示索引来处理集合的方法,大概是通过迭代集合直到找到您想要的那个(参见#2)。或者,您可以保存字典并为大量列保持更新。

    我怀疑保留字典会提高性能,因为每次移动列时,您基本上都必须重写整个内容。无论如何,迭代都是 O(n) ,除非您正在谈论具有数百列的异步操作,否则您可能没问题。

    假设它不会this[]搞砸DataGridView.

想法 #1 可能是最容易实现的,但不一定是最漂亮的。想法 #2 有效,你可以把它放在一个函数DataGridViewColumn GetColumnByDisplayIndex(int Index)中。想法#3 很可爱,当然也是最封装的方法,但也不是微不足道的。

于 2008-12-10T09:00:57.023 回答
0

感谢 cfeduke 的出色建议。我怀疑Insert会慢一些,但提供的链接让我知道慢了多少。

这就提出了如何在 DataGridView 上有效地动态插入和删除列的问题。看起来理想的设计是使用Addor添加大量列AddRange,然后永远不要真正删除它们。然后,您可以通过将该Visible属性设置为 false 来模拟删除。您可以通过抓取一个不可见的列、设置它DisplayIndex并使其可见来插入一个列。

但是,我怀疑这种方法会避免地雷。最重要的是,您不能再以直接的方式索引您的数据。也就是说,m_DGV.Columns[i]并且m_DGV.Rows[n].Cells[i]不会正确映射。我想你可以创建一个地图/字典来维护一个外部直观的映射。

由于我的应用程序(按照目前的设计)需要频繁的列插入和删除,因此它可能是值得的。有人有什么建议吗?

于 2008-10-27T19:40:41.347 回答