设置: 我有两个DataGridViews,每个都绑定到BindingList<>自定义业务对象。这些网格有一个特殊的行,其中包含该网格中所有行的数学总和 - 这个特殊行反映了BindingList中对应的特殊对象<> (我指定这一点,以便您知道这不是添加到DGV的行,而是添加到BindingList<>)的对象。
错误: 有一段时间,我必须定期找到并从BindingList中删除Totals Row对象<> (因此来自DGV)。这是我用来执行此操作的原始代码:
private void RemoveTotalRow()
{
for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
{
if (UnderlyingGridList[i].IsTotalRow) UnderlyingGridList.RemoveAt(i);
}
}
(这不是非常重要,但我在所有记录中循环的原因是为了防止错误地存在多个Totals行的可能性)。在所有情况下,此代码可以完美地运行两个网格中的一个。但是,在第二个网格上,当调用RemoveAt方法时,我得到以下错误:
The following exception occurred in the DataGridView: System.IndexOutOfRangeException: Index 5 does not have a value. at System.Windows.Forms.CurrencyManager.get_Item(Int32 index) at System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex) To replace this default dialog please handle the DataError event.
...其中'5'是总计行的索引。 I found this question,基本上是相同的,除了接受的答案是:1)不使用我必须做的基础列表,或2)从网格而不是从列表中删除。我已经尝试过#2,用上面的代码示例替换最里面的方法调用:
if (UnderlyingGridList[i].IsTotalRow) brokenDataGrid.Rows.RemoveAt(i);
这会引发同样的错误。 I also found this question,它建议在更改后重新绑定 - 但是,这是不可行的,因为此代码可能每秒调用一次,如果列表填充太多,则会使网格无法使用(我知道这个来自糟糕的经历)。
我可以处理网格的DataError事件,但我宁愿不让每分钟出现一百万个错误,即使它们是静默的。任何帮助将不胜感激。
答案 0 :(得分:2)
所以这是一个奇怪的情况......但是这里有:
1)有问题的网格定义了一个SelectionChanged事件,其中调用了两行代码:
Grid.ClearSelection();
Grid.Refresh();
这些是因为我将网格伪装成看就像有一个选定的行,而实际上没有一个。通过这样做,我可以自定义网格的外观。
2)触发代码来自我的问题的事件是网格的 Sorted 事件。
第3步和第4步是我的推测,但我的测试似乎支持这一理论
3)Grid.Sorted事件显然也会触发此Grid.SelectionChanged事件。
4)网格现在正在尝试刷新网格并同时删除总计行。因此,断点使它看起来好像应该有效,而实际上它不会。
从上面的事件中删除Grid.Refresh()方法调用可以完全解决问题。在检查工作网格的Grid.SelectionChanged事件时,我发现只调用了ClearSelection()方法,而不是Refresh()。
感谢那些在线程和c#聊天帮助的人!
答案 1 :(得分:1)
只是溢出你的问题。可能就是这样:
for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
需要成为这个:
for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
i+=1
这是一个简短的例子。只需添加一个DataGridView(有2列)和两个按钮就可以了。这是VB.Net。
Public Class Form1
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Me.Button1.Text = "Create"
Me.Button2.Text = "Remove"
Me.DataGridView1.AllowUserToAddRows = False
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
For i As Integer = 0 To 99
Me.DataGridView1.Rows.Add("Hello", DateTime.Now)
Next
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim i As Integer = Me.DataGridView1.Rows.Count - 1
Do
If Me.DataGridView1.AllowUserToAddRows = False Then
If i < 0 Then Exit Do
Me.DataGridView1.Rows.RemoveAt(i - 0)
Else
If i < 1 Then Exit Do
Me.DataGridView1.Rows.RemoveAt(i - 1)
End If
i -= 1
Loop
End Sub
End Class
注意Me.DataGridView1.AllowUserToAddRows = False