3

设置: 我有两个 DataGridView,每个都绑定到自定义业务对象的 BindingList<>。这些网格有一个特殊的行,其中包含该网格中所有行的数学总计——这个特殊的行反映了 BindingList<> 中相应的特殊对象(我指定了这一点,以便您知道这不是要添加的行到 DGV,但将对象添加到 BindingList<>)。

错误: 有一段时间,我必须定期从 BindingList<> (因此从 DGV)中找到并删除 Totals Row 对象。这是我用来执行此操作的原始代码:

private void RemoveTotalRow()
  {
     for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
     {
        if (UnderlyingGridList[i].IsTotalRow) UnderlyingGridList.RemoveAt(i);  
     }
  }

(这不是超级重要,但我循环浏览所有记录的原因是为了防止错误地出现多个总计行的可能性)。此代码在所有情况下都可以完美地用于两个网格之一。但是,在第二个网格上,当调用 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”是总计行的索引。 我发现这个问题基本上是相同的,除了接受的答案是:1)不使用基础列表,我必须这样做,或者 2)从网格中删除而不是从列表中删除。我尝试了#2,将上面代码示例中最里面的方法调用替换为:

if (UnderlyingGridList[i].IsTotalRow) brokenDataGrid.Rows.RemoveAt(i);

这会引发相同的错误。 我还发现了这个问题,它建议在更改后重新绑定 - 但是,这是不可行的,因为此代码可能每秒调用一次,并且如果列表填充过多,它将使网格无法使用(我知道这个来自糟糕的经历)。

我可以只处理网格的 DataError 事件,但我宁愿不要每分钟弹出一百万个错误,即使它们是无声的。任何帮助将不胜感激。

4

2 回答 2

2

所以这是一个奇怪的情况......但这里是:

1)有问题的 Grid 定义了一个 SelectionChanged 事件,其中调用了两行代码:

Grid.ClearSelection(); 
Grid.Refresh(); 

这些在这里是因为我将网格伪装成看起来有一个选定的行,而实际上没有。通过这样做,我可以自定义网格的外观。

2)从我的问题触发代码的事件是网格的排序事件。

第 3 步和第 4 步是我的推测,但我的测试似乎支持该理论

3) Grid.Sorted 事件显然也触发了这个 Grid.SelectionChanged 事件。

4) 网格现在正在尝试刷新网格并同时删除总计行。因此断点使它看起来好像应该工作,而实际上它不会。

从上述事件中删除 Grid.Refresh() 方法调用可以完全解决问题。在检查工作网格的 Grid.SelectionChanged 事件后,我发现只调用了 ClearSelection() 方法,而不是 Refresh()。

感谢那些在线程和 c# 聊天中提供帮助的人!

于 2011-05-18T15:27:13.840 回答
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

于 2011-05-18T14:04:20.293 回答