【问题标题】:Deleting From DGV -- Index [x] does not have a value从 DGV 中删除 -- 索引 [x] 没有值
【发布时间】:2011-05-18 23:27:13
【问题描述】:

设置: 我有两个 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”是总计行的索引。 I found this question,本质上是相同的,除了接受的答案是:1)不使用基础列表,我必须这样做,或者 2)从网格中删除而不是从列表中删除。我已经尝试 #2,将上面代码示例中最里面的方法调用替换为:

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

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

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

【问题讨论】:

    标签: c# datagridview bindinglist


    【解决方案1】:

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

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

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

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

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

      只是溢出你的问题。会不会是这样的:

      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

      【讨论】:

      • 我需要一些说服力才能相信问题出在柜台上。原因如下:当我在 RemoveAt 方法调用之前对代码进行断点时,它显示索引 [5]​​ 是网格和列表中的有效行,但是当它运行 RemoveAt 时,我得到了异常...
      • 嗯,好的。难道 Index(5) Row 只是一个准备好的空行?也许尝试 "UserAllowedToAddRows" = False 再试一次。
      • 感谢收看@goldengel!问题实际上最终是在运行此代码之前进行的刷新调用。拿出刷新解决问题!我将单独发布以供后代使用。
      猜你喜欢
      • 2022-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 1970-01-01
      相关资源
      最近更新 更多