为什么Columns.Insert不更新DataGridView(C#)中的DisplayIndex?

时间:2008-10-22 21:27:08

标签: c# datagridview

我以编程方式在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

另外,我的网格可以动态增加其列数。我希望以块的形式增长它,因此每个插入都不需要列分配(以及相关的初始化)。然后,通过从末端抓取未使用的列,将其插入所需位置并使其可见,添加每个“新”列。

3 个答案:

答案 0 :(得分:2)

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

a question/answer我发现:

  

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

与几乎所有集合(LinkedLists除外)一样,最好将集合than insert into添加到集合中。您所看到的行为反映了该规则。

答案 1 :(得分:2)

我有几个想法。

  1. 如何通过唯一名称而不是集合中的索引来处理列?他们可能还没有名字,但如果你给他们一个有意义的名字,你可以跟踪谁是谁。

  2. 您可以使用GetFirstColumn类的GetNextColumnGetPreviousColumnGetLastColumnDataGridViewColumnCollection方法,这些方法适用于显示顺序,而不是集合中的顺序。你也可以使用for循环和m_DGV.Columns[i]迭代整个集合,直到找到你想要的那个。

  3. 创建一个继承的DataGridViewDataGridViewColumnCollection。只需覆盖DataGridView即可使用您的新集合类。你的新DataGridViewColumnCollection将包含一个通过显示索引来处理集合的方法,可能是通过遍历集合直到找到你想要的那个(见#2)。或者,您可以保存字典并使其更新为非常多的列。

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

    您也可以覆盖this[]运算符,假设它没有搞砸DataGridView

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

答案 2 :(得分:0)

感谢cfeduke的出色建议。我怀疑Insert会慢一点,但提供的链接让我开得慢了很多。

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

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

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