我以编程方式在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
另外,我的网格可以动态增加其列数。我希望以块的形式增长它,因此每个插入都不需要列分配(以及相关的初始化)。然后,通过从末端抓取未使用的列,将其插入所需位置并使其可见,添加每个“新”列。
答案 0 :(得分:2)
我怀疑这是因为DataGridView中列的顺序不一定决定显示顺序,但默认情况下没有显式指定列的顺序决定了DisplayIndex属性值。这就是为什么有一个DisplayIndex属性,所以你可以在不执行插入的情况下向集合添加列 - 你只需要指定DisplayIndex值,并且对于具有相同或更大DisplayIndex的所有内容都会发生级联更新。从您的示例中可以看出,插入的列也接收到第一个跳过的DisplayIndex值。
从a question/answer我发现:
更改DisplayIndex将导致 旧的所有列之间 DisplayIndex和新的DisplayIndex 转移。
与几乎所有集合(LinkedLists除外)一样,最好将集合than insert into添加到集合中。您所看到的行为反映了该规则。
答案 1 :(得分:2)
我有几个想法。
如何通过唯一名称而不是集合中的索引来处理列?他们可能还没有名字,但如果你给他们一个有意义的名字,你可以跟踪谁是谁。
您可以使用GetFirstColumn
类的GetNextColumn
,GetPreviousColumn
,GetLastColumn
,DataGridViewColumnCollection
方法,这些方法适用于显示顺序,而不是集合中的顺序。你也可以使用for循环和m_DGV.Columns[i]
迭代整个集合,直到找到你想要的那个。
创建一个继承的DataGridView
和DataGridViewColumnCollection
。只需覆盖DataGridView
即可使用您的新集合类。你的新DataGridViewColumnCollection
将包含一个通过显示索引来处理集合的方法,可能是通过遍历集合直到找到你想要的那个(见#2)。或者,您可以保存字典并使其更新为非常多的列。
我怀疑保留字典的性能提升,因为每次列移动时,你基本上都要重写整个字体。无论如何迭代都是O(n),除非你在谈论数百列的异步操作,否则你可能没问题。
您也可以覆盖this[]
运算符,假设它没有搞砸DataGridView
。
DataGridViewColumn GetColumnByDisplayIndex(int Index)
中。想法#3很可爱,当然也是封装最多的方法,但并不是一件容易的事。
答案 2 :(得分:0)
感谢cfeduke的出色建议。我怀疑Insert
会慢一点,但提供的链接让我开得慢了很多。
这提出了如何在DataGridView上有效地插入和删除列的问题。看起来理想的设计是使用Add
或AddRange
添加大量列,然后永远不会真正删除它们。然后,您可以通过将Visible
属性设置为false来模拟删除。您可以通过抓取不可见的列来插入列,设置其DisplayIndex
并使其可见。
但是,我怀疑这种做法会避免地雷。最重要的是,您无法再以直接的方式索引数据。也就是说,m_DGV.Columns[i]
和m_DGV.Rows[n].Cells[i]
将无法正确映射。我想你可以创建一个Map / Dictionary来维护一个外部的直观映射。
由于我的应用程序(按照目前设计)需要频繁插入和删除列,因此可能是值得的。有人有什么建议吗?