Winforms 删除行时刷新列表的DataGridView绑定

Winforms 删除行时刷新列表的DataGridView绑定,winforms,datagridview,data-binding,Winforms,Datagridview,Data Binding,我有一个WinForm应用程序,其中多个DataGridView绑定到SortableBindingList 在某些情况下,我需要以编程方式从grid绑定到的列表中删除一项 我似乎无法让DGV认识到它的数据已经更改,或者,具体地说,它的行数更少。我正在调用dataGridView1.Invalidate(),它正在重新绘制网格,但它尝试重新绘制与以前一样多的行,并抛出一系列“索引不存在”的异常,每列一个异常 下面是一个显示问题的简化代码示例:(只有一个带有DGV和按钮的WinForm。) 私有列

我有一个WinForm应用程序,其中多个DataGridView绑定到SortableBindingList

在某些情况下,我需要以编程方式从grid绑定到的列表中删除一项

我似乎无法让DGV认识到它的数据已经更改,或者,具体地说,它的行数更少。我正在调用dataGridView1.Invalidate(),它正在重新绘制网格,但它尝试重新绘制与以前一样多的行,并抛出一系列“索引不存在”的异常,每列一个异常

下面是一个显示问题的简化代码示例:(只有一个带有DGV和按钮的WinForm。)

私有列表;
私有void Form1\u加载(对象发送方、事件参数e)
{
列表=新列表();
对于(int-ix=0;ix<3;ix++)
{
list.Add(ObjectMother.GetEmployee(ix+1));
}
dataGridView1.DataSource=列表;
}
私有void cmdDeleteARow_单击(对象发送方,事件参数e)
{
列表。删除(列表[0]);
dataGridView1.Invalidate();
}
在ASP.NET中,当使用GridView控件时,可以调用“DataBind()”方法来强制它刷新其数据。WinForms中似乎没有这样的东西,或者我遗漏了什么吗?

试试看

dataGridView1.Refresh()

好吧,因为我没有得到任何有用的回答,我将继续使用我想出的乱七八糟的方法

如果使用反射进入DataGridView.DataSource属性,您将看到绑定方法仅在数据源更改时调用。请注意,对数据源内容的更改(例如,添加、更改或删除列表元素)不会被视为对数据源的更改。为了强制调用数据绑定方法,我成功地将数据源重新分配给其他对象,然后将其分配回列表。看起来难以置信的笨拙,对CPU周期的巨大浪费,但它似乎是可行的。因此,代码变成:

    private void cmdDeleteARow_Click(object sender, EventArgs e)
    {
        list.Remove(list[0]);
        dataGridView1.DataSource = new List<Employee>();
        dataGridView1.DataSource = list;
        dataGridView1.Invalidate();
    }
private void cmdDeleteARow\u单击(对象发送方,事件参数e)
{
列表。删除(列表[0]);
dataGridView1.DataSource=新列表();
dataGridView1.DataSource=列表;
dataGridView1.Invalidate();
}

如果有人有更好的想法(我相信肯定会有一些),请告诉我。

为了让
DataGridView
能够了解对其
数据源的更改,源代码应该实现<代码>列表
没有,因此它不会广播其更改,
数据网格视图
也不知道它需要更新

在这种情况下,一个简单的解决方法是在列表和
DataGridView
之间放置一个,然后对其调用
Remove()

private List<Employee> list;
private BindingSource bindingSource;
private void Form1_Load(object sender, EventArgs e)
{
    list = new List<Employee>();
    for (int ix = 0; ix < 3; ix++)
    {
        list.Add(ObjectMother.GetEmployee(ix+1));
    }

    dataGridView1.DataSource = bindingSource;
    bindingSource.DataSource = list;
}

private void cmdDeleteARow_Click(object sender, EventArgs e)
{
    bindingSoruce.Remove(list[0]); // or, RemoveAt(0)

    // Probably not necessary:
    // dataGridView1.Invalidate();
}
私有列表;
私有BindingSource BindingSource;
私有void Form1\u加载(对象发送方、事件参数e)
{
列表=新列表();
对于(int-ix=0;ix<3;ix++)
{
list.Add(ObjectMother.GetEmployee(ix+1));
}
dataGridView1.DataSource=bindingSource;
bindingSource.DataSource=列表;
}
私有void cmdDeleteARow_单击(对象发送方,事件参数e)
{
bindingSoruce.Remove(列表[0]);//或者,RemoveAt(0)
//可能没有必要:
//dataGridView1.Invalidate();
}
或者,您可以使用而不是
List
,或者创建自己的List类来实现
IBindingList

我尝试过使用容器对象的Validate()方法,在同步数据网格视图和绑定数据表时,它工作得很顺利

Visual C++中的一个例子可以给出如下:

//假设dgv已在代码中创建为数据栅格视图对象

SplitContainer ^dgvContainer=dynamic_cast(dgv->Parent->Parent); dgvContainer->Validate()


希望能有帮助。

谢谢你,迈克尔,但结果也一样。我尝试用Refresh替换Invalidate调用,还尝试将Invalidate保留在中,并在之前和之后添加刷新。所有仍然抛出相同的异常。我得到的错误与您的相同,我的场景是小的相同的事情,即在for循环中读取datadridview的数据,并对每一行执行一些操作,最后删除当前行…所以我所做的是创建一个用于删除它的委托函数,因为我正在使用后台工作线程。。。它对…有用。。。r u使用ne背景线Andrew Watt给出了一个非常好的答案。你的回答既不好也不好。请在安德鲁的帖子上打个勾。这是一个非常古老的帖子,但它接近谷歌的顶端,所以我会在这里放一些东西。100%切换到BindingList效果很好。其次,我发现了一些问题,如果您使用bindingsource方式,如果您在原始列表上运行add/removes,您将不会看到DataGridView上反映的更改。您需要在bindingsource上运行添加/删除。
private List<Employee> list;
private BindingSource bindingSource;
private void Form1_Load(object sender, EventArgs e)
{
    list = new List<Employee>();
    for (int ix = 0; ix < 3; ix++)
    {
        list.Add(ObjectMother.GetEmployee(ix+1));
    }

    dataGridView1.DataSource = bindingSource;
    bindingSource.DataSource = list;
}

private void cmdDeleteARow_Click(object sender, EventArgs e)
{
    bindingSoruce.Remove(list[0]); // or, RemoveAt(0)

    // Probably not necessary:
    // dataGridView1.Invalidate();
}