从 DGV 中删除 -- 索引 [x] 没有值

发布于 2024-11-08 05:11:54 字数 1647 浏览 3 评论 0原文

设置: 我有两个 DataGridView,每个都绑定到一个 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);  
     }
  }

这并不是非常重要,但我循环遍历所有记录的原因是为了防止错误地出现多个总计行的可能性)。此代码在所有情况下对于两个网格之一完美地工作。但是,在第二个网格上,当调用 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 事件,但我不想让它每分钟弹出一百万个错误,即使它们是静默的。任何帮助将不胜感激。

The Setup:
I have a two DataGridViews, each bound to a BindingList<> of custom business objects. These grids have a special row containing the mathematical totals of all rows in that grid -- this special row is reflective of a corresponding special object in the BindingList<> (I specify that so that you are aware that this is not a row being added to the DGV, but an object being added to the BindingList<>).

The Error:
There comes a time, periodically, where I must find and remove the Totals Row object from the BindingList<> (and thus from the DGV). Here is the original code I was using to do this:

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

(It's not super-important, but the reason I'm cycling through all records is to protect against the possibility that there could be more than one Totals row, by mistake). This code works flawlessly for one of the two grids under all circumstances. However, on the second grid I get the following error when the RemoveAt method is called:

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.

...where '5' is the index of the totals row. I found this question, which is essentially the same, except that the accepted answer is to either: 1) Not use an underlying list, which I must do, or 2) Delete from the grid instead of from the list. I have tried #2 by replacing the innermost method call from my code example above with this:

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

This throws the same error. I also found this question, which suggests rebinding after the change - however, this is not feasible as it is possible for this code to be called once per second and if the list is too heavily populated it will make the grid unusable (I know this from bad experiences).

I could just handle the grid's DataError event, but I'd rather not have the thing popping a million errors per minute, even if they are silent. Any help would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

去了角落 2024-11-15 05:11:54

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

1)所讨论的网格定义了一个 SelectionChanged 事件,其中调用了两行代码:

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

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

2) 触发我的问题中的代码的事件是网格的Sorted事件。

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

3) Grid.Sorted 事件显然也会触发此 Grid.SelectionChanged 事件。

4) 网格现在尝试刷新网格并同时删除总计行。因此,断点看起来似乎应该起作用,但实际上却不起作用。

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

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

So this was a bizarre set of circumstances... but here goes:

1) The Grid in question has a SelectionChanged event defined, inside of which two lines of code are called:

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

These are here because I am faking out the grid into looking like there is a selected row, when in fact there is not one. By doing this I am able to customize the look of the grid.

2) The event that triggers the code from my question is the Sorted event of the grid.

Steps 3 and 4 are speculation on my part, but my testing seems to support the theory

3) The Grid.Sorted event apparently triggers this Grid.SelectionChanged event as well.

4) The Grid is now trying to Refresh the grid and also remove the totals row at the same time. Hence breakpointing makes it seem as though it should work, when in fact it will not.

Removing the Grid.Refresh() method call from the event above rectifies the problem completely. Upon inspecting the Grid.SelectionChanged event of the working grid, I found that only the ClearSelection() method is being called, not Refresh().

Thanks to those who helped here on the thread and in c# chat!

笔芯 2024-11-15 05:11:54

只是溢出你的问题。难道这个:

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

Just overflow your question. Could it be that this:

for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)

needs to become this:

for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
i+=1

Here is a short example. Just add an DataGridView (with 2 columns) and two buttons on it. It is 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

watch out for Me.DataGridView1.AllowUserToAddRows = False

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文