【问题标题】:Cannot update DataGridView cell via DataBoundItem?无法通过 DataBoundItem 更新 DataGridView 单元格?
【发布时间】:2019-10-07 07:35:46
【问题描述】:

我创建了一个包含两个控件dataGridView1button1 的表单。

public partial class Form1 : Form
{
    public List<Foo> ds { get; private set; }

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ds = new List<Foo> {
            new Foo { A="abc" }, new Foo{B="bbb"}
        };
        dataGridView1.DataSource = new BindingList<Foo>(ds);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var foo = (Foo)dataGridView1.Rows[0].DataBoundItem;
        foo.B = "1BBB";
        foreach(DataGridViewRow x in dataGridView1.Rows)
        {
            if (x.DataBoundItem != null)
                ((Foo)x.DataBoundItem).C = "CCC";
        }
    }
}

但是,单击button1 不会在表单中显示更改的值?在 Visual Studio 中调试显示值已设置。


更新:

我将代码更改为以下以使用 DataTable。但是,单击按钮仍然不会更新 UI?

public partial class Form1 : Form
{
    public List<Foo> ds { get; private set; }

    private Dictionary<string, Foo> dict;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        //ds = new List<Foo> {
        //    new Foo { A="abc" }, new Foo{B="bbb"}
        //};
        //dataGridView1.DataSource = new BindingList<Foo>(ds);
        var dt = new DataTable();
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "A", Unique = true });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "B", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "C", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "D", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "E", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "F", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "G", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "H", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "I", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "J", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "K", Unique = false });
        dt.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "L", Unique = false });
        dt.PrimaryKey = new DataColumn[] { dt.Columns["A"] };

        var row = dt.NewRow();
        row["A"] = "1";
        dt.Rows.Add(row);
        row = dt.NewRow();
        row["A"] = "2";
        dt.Rows.Add(row);
        row = dt.NewRow();
        row["A"] = "3";
        dt.Rows.Add(row);
        dataGridView1.DataSource = dt;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var foo = (DataRowView)dataGridView1.Rows[0].DataBoundItem;
        foo["B"] = "1BBB";
        //foreach (DataGridViewRow x in dataGridView1.Rows)
        //{
        //    if (x.DataBoundItem != null)
        //        ((Foo)x.DataBoundItem).C = "CCC";
        //}
        //dataGridView1.DataSource = ds;
    }
}

【问题讨论】:

  • 为什么要专门讨论这个问题?其实这对我来说是个有趣的问题。

标签: c# winforms


【解决方案1】:

更改值后添加“EndEdit”:

private void button1_Click(object sender, EventArgs e)
    {
        var foo = (DataRowView)dataGridView1.Rows[0].DataBoundItem;
        foo["B"] = "1BBB";
        foo.EndEdit();
    }

您也可以将源更改为绑定源,然后直接在桌子上工作。

【讨论】:

  • 你知道为什么 DataBoundItem 在绑定到 DataTable 时可以转换为 DataRowView 而不是 List&lt;T&gt;
【解决方案2】:

您需要刷新数据源的绑定,因为您直接更改有界实例而不是单元格。

试试这个:

  foreach ( DataGridViewRow x in dataGridView1.Rows )
  {
    if ( x.DataBoundItem != null)
      ((Foo)x.DataBoundItem ).C = "CCC";
  }
  dataGridView1.DataSource = new BindingList<Foo>(ds);

你也可以改写:

  x.Cells[2].Value = "CCC";

所以网格和有界实例一样被更新。

你不需要 BindingList,你可以写这个,第一次,修改后:

dataGridView1.DataSource = null;
dataGridView1.DataSource = ds;

这是一个更好的模式:

How can I refresh c# dataGridView after update ?

但我们可以使用 DataTable,或者更好的 DataSet 具有 DataTable,同时使用 Visual Studio 设计器并在表单上使用拖放表格来编写更少的代码并自动生成数据网格和所有非可视数据组件.

这是一个摘要

要刷新修改后的DataBoundItem 的视图,它是BindingList 或只是List 的DataSource 的对象,我们可以重新分配DataSource。

但如果是BindingSource,您可以在BindingSurce 上使用ResetBindings

但是,如果您在 List 上使用 DataTable 而不是 DataSource,那么您可以在作为 DataRowView 的 DataBoundItem 上使用 EndEdit

那么问题是这里最好做什么:在 List 上使用 BindingSource 或创建 DataTable 并管理 LoadFromStream 和 SaveFromStream,因为您说数据来自 IEnumerable 流?

因此,您可以看到CopyToDataTable() 将您的List&lt;Foo&gt; 映射到DataTable

Creating a DataTable From a Query (LINQ to DataSet)

【讨论】:

  • dataGridView1.DataSource = new BindingList&lt;Foo&gt;(ds); 会贵吗?列表可能很大,我需要每秒更新一次列表。我读到更新绑定的数据源也会在另一个 SO 问题答案中更新控件。
  • 也许如果你有很多数据。但是您不需要按照说明进行操作。您可能更喜欢操纵网格单元。你也可以写dataGridView1.DataSource = ds.ToList();dataGridView1.DataSource = ds;,因为它只用一个赋值来刷新绑定,所以成本更低。或者创建一个数据表来自动刷新。
  • 使用强类型数据集更好:您在项目中添加一个新项目,它是一个数据集,然后打开它,您可以设计数据结构或在其上删除数据库项目。就这么简单。
  • 我可能需要从流中填充数据源。可能需要使用 Reactive 框架。强类型数据集还是更好的选择吗?
  • 这取决于您想要做什么以及您需要管理哪些数据。对于一个真正的应用程序,是的,你应该至少使用一个强类型数据集,或者如果你有一个数据库,并且如果你想要一个大型机器,你应该使用 EF。数据集很好。
猜你喜欢
  • 1970-01-01
  • 2012-08-04
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多