【问题标题】:Datagridview causing IndexOutOfRangeException when clicked upon单击时 Datagridview 导致 IndexOutOfRangeException
【发布时间】:2009-05-30 16:35:59
【问题描述】:

我有一个 datagridview,我们称之为 dataGridViewExample。

我的对象(不常见的数据类型是因为我的数据库是 SQLite):

class MyObject
{
    public Int64 Vnr { get; set; }
    public string Name { get; set; }
    public Single Price { get; set; }
    public int Amount { get; set; }
}

以下是相关代码:

//This form gets called with a .ShowDialog(); in my form1.

private List<MyObjecte> ExampleList = new List<MyObject>();

public MyForm()
{
    dataGridViewExample.DataSource = OrdreInkøbsListe;
}


private void AddtoDataGridViewExample()
{
    //Add a new MyObject to the list
    ExampleList.Add(new myObject()
                 {
                     Vnr = newVnr,
                     Amount = newAmount,
                     Price = newPrice,
                     Name = newName
                 });

    //refresh datasource
    dataGridViewExample.DataSource = null;
    dataGridViewExample.Refresh();
    dataGridViewExample.DataSource = OrdreInkøbsListe;
    ddataGridViewExample.Refresh();
}

当使用 .ShowDialog 调用 MyForm 时,它显示得很好,并且显示我的 DataGridView 示例也很好。从代码中可以看出,ExampleList 最初是空的,所以它只显示一个空的 datagridview 有 4 列:Vnr、名称、价格和金额。如果我点击它等等,什么都不会发生 - 所以到目前为止一切都按计划进行。

每次我调用 AddtoDataGridViewExample() 时,它都会将新对象添加到 Datagridview,并且 datagridview 会更新,列出到目前为止添加的所有对象(它们显示为行,再次根据计划)。

现在,还记得我刚才说过,如果你在我打电话给AddtoDataGridViewExample() 之前点击了DataGridViewExample,什么都不会发生? 好吧,在调用AddtoDataGridViewExample() 一次或多次之后,如果我在DataGridViewExample 内部单击,程序将崩溃(例如:用户要选择一行)。它抛出 IndexOutOfRangeException 并讨论 -1 索引。 它还会以另一种形式抛出异常,在我用 .ShowDialog() 调用 MyForm 的那一行;

我真的被困在这个问题上,你们知道有什么问题吗? 我唯一的线索是,我相信DataGridViewExample 的数据源的刷新可能是问题的原因。 另一个重要注意事项:我尚未将任何事件绑定到我的DataGridViewExample。所以你可以排除这个想法。

这是DataGridViewExample的所有属性:

this.dataGridViewExample.AllowUserToAddRows = false;
this.dataGridViewExample.AllowUserToDeleteRows = false;
this.dataGridViewExample.AllowUserToResizeColumns = false;
this.dataGridViewExample.AllowUserToResizeRows = false;
this.dataGridViewExample.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridViewExample.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridViewExample.Location = new System.Drawing.Point(591, 53);
this.dataGridViewExample.MultiSelect = false;
this.dataGridViewExample.Name = "dataGridViewExample";
this.dataGridViewExample.ReadOnly = true;
this.dataGridViewExample.RowHeadersVisible = false;
this.dataGridViewExample.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dataGridViewExample.ShowEditingIcon = false;
this.dataGridViewExample.Size = new System.Drawing.Size(240, 150);
this.dataGridViewExample.TabIndex = 31;

【问题讨论】:

  • 处理点击事件的代码在哪里?通常会发生此异常,因为您正在处理单击事件,然后在没有选择行时尝试获取所选行。选择一行并单击网格是互斥的。那么,处理引发异常的点击事件的代码在哪里呢?
  • 我还没有向 dataGridViewExample 添加任何事件,这是令人担忧的部分 :( 所以如果有的话,它是导致它的一些内置事件。

标签: c# winforms datagridview


【解决方案1】:

我猜click事件试图获取当前选定的行并对其进行处理,而dataGridViewExample.DataSource = null;清除数据源,当前选定的行变为空。

如果您将DataGridView.DataSource 设置为列表,则无需将其重置为空,刷新并再次将其重置为列表(并再次刷新)即可查看更改。刷新DataGridView就足够了。

您也可以尝试使用BindingList&lt;T&gt; 对象而不是List&lt;T&gt;,它会自动通知您的网格其内部更改(添加和删除元素),还有一个INotifyPropertyChanged 接口可以实现您的 MyObject 类,这将使对象中的每个属性更改都显示在网格上(对于代码中对对象所做的任何更改,而不是通过网格本身)。

【讨论】:

  • 这听起来非常有趣。你能展示一些代码示例吗?特别是如何使用绑定列表以及我应该如何在我的方法中调用刷新
  • 我将列表更改为 bindinglist,删除了所有刷新代码并添加了一次刷新。一切似乎都很完美,非常感谢!!一个快速的请求:你能展示一个如何从绑定列表中删除某个对象的代码示例吗?
  • 如果您的数据源无法更改为 BindingList,您可以处理DataGridView.DataError 事件并在该子例程中执行DataGridView.Refresh。这是一个很好的选择,灵感来自 Noam 的回答
  • 谢谢。将列表从 List 更改为 BindingList 也解决了我的问题。
【解决方案2】:

您是否尝试过运行调试器并在引发 InedxOutOfRangeException 时中断以查看引发异常的位置?

选择“调试”>“异常”,然后对话框上有一个“查找”按钮,因此您不必浏览所有可能性。

【讨论】:

  • 由于某种原因不起作用。我已经检查了它们,当这发生在我身上时,Visual Studio 在我在包含表单上调用 ShowDialog 的那一行爆发了。
【解决方案3】:

我也有类似的情况。我将某些对象的通用列表分配给 DataGridView。然后我将 null 设置为 DataSource 并在刷新之后。之后,我将对象列表分配给 DataSource。在发生运行时错误时单击网格时出现 IndexOutOfRange。我的解决方案是将我的对象的新空列表分配给该网格并刷新,在我的工作列表发生更改后,我确实分配给 DataSource 并调用 Refresh。现在,它可以正常工作,没有任何崩溃。请先查看我的代码:

grid.DataSource = null;
grid.Refresh();
if(cases.Count() > 0)
{
   grid.DataSource = cases;
   grid.Refresh();
}            

现在在我的代码之后:

grid.DataSource = new List<MyCase>();
grid.Refresh();
//do something with cases
if(cases.Count() > 0)
{
   grid.DataSource = cases;
   grid.Refresh();
}            

【讨论】:

    猜你喜欢
    • 2013-02-16
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2011-12-04
    相关资源
    最近更新 更多