【问题标题】:How to update a DataGridView's Datasource on cell edit如何在单元格编辑时更新 DataGridView 的数据源
【发布时间】:2021-08-01 15:12:29
【问题描述】:

我已通过下面的 Select 语句将我的类 Reports 附加到 dataGridView 的 DataSource,因为我不希望 Prop3 出现在 DGV 中。然后我更新了 cellClick 事件以删除 ReadOnly,因为这似乎是初始运行的问题。

当我单击一个单元格并尝试将值更改为 123 时,一旦我按 Enter 键,它就会切换回 456。我尝试使用各种其他事件,例如 CellEndEdit、CellValueChanged,以及我认为可能有助于不走运的任何其他事件。在使用断点运行代码时,我什至找不到我试图更改为存储在任何地方的值 (123)。我想确保在单元格编辑完成后 myClass 中的值设置为 123。如果我不使用 select 语句,那么所有 3 个属性都将显示在 DGV 中,然后我可以按照我要求的方式编辑值,但我又不想让 Prop3 显示,所以使用了 select 语句。

    List<MyClass> myClass;
    public Form3()
    {
        InitializeComponent();

        myClass = new List<MyClass>();
        for (int i = 0; i < 2; i++)
        {
            myClass.Add(new MyClass(456, 456));
        }
        dataGridView1.DataSource = myClass.Select(x => new { x.Prop1, x.Prop2 }).ToList();
        dataGridView1.ReadOnly = false;
        dataGridView1.CellClick += DataGridView1_CellClick;
    }

    private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        (sender as DataGridView).CurrentCell.ReadOnly = false;

    }

    public class MyClass
    {
        public int Prop1{get;set;}
        public int Prop2 {get;set;}
        public int Prop3 {get;set;}
        public MyClass(int prop1, int prop2)
        {
            Prop1 = prop1;
            Prop2 = prop2;
        }
        public MyClass() { }
    }

【问题讨论】:

  • 将整个 DataGridView 设置为只读... dataGridView1.ReadOnly = true; ... 将覆盖各个行/列/单元格的只读属性。如果将单个行或列设置为只读 = true,则可以将单个单元格设置为只读 = false。
  • DataGridView 已设置 ReadOnly = false;但即使将其添加到 CellClick 事件中,我仍然遇到同样的问题。
  • 您说... “但是,一旦我完成了对单元格的编辑,值就会恢复为之前存储的值。” ... ?你能创建一个minimal reproducible example 来演示复选框被设置回原来的值吗?如果用户更改网格中复选框的值,则底层 DataSource 也会自动更改。所以不清楚你所说的“如何更新 DataGridView 的数据源”是什么意思。
  • 您编写的任何代码的意义何在?这似乎与您问题的标题无关,这似乎也是一个坏主意。为什么将网格设置为只读,然后将单击的单元格设置为可编辑?无论如何,这正是网格的行为方式。编辑控件一次只显示一个单元格。 datagridview 确实可靠地编辑了底层 DataSource 的属性值 - 你为什么要尝试对其进行微观管理?您是否只是在寻找 DataGridView.EndEdit 之类的东西,以便在保存之前将编辑刷新到基础列表(这通常会发生..
  • ..无论如何都会失去焦点)

标签: c# datagridview


【解决方案1】:

因为我不希望 Prop3 出现在 DGV 中

在生成列后从 DGV 中删除列要简单得多

var x = new List<MyClass>(){
  new MyClass(){ Prop1 = 1, Prop2 = 22, Prop3 = 4015559191 },
  new MyClass(){ Prop1 = "Fred", Prop2 = 23, Prop3 = "4015559002" },
};

了解默认情况下 DataGridView 的 AutoGenerateColumns 属性为 true。当您绑定到 MyClass 列表时,DGV 将检查 MyClass 的属性并为它们创建列,同时考虑数据类型和名称

没有什么能阻止你之后编辑它的作品:

dataGridView1.DataSource = x;

dataGridView1.AutogenerateColumns = false; //turn it off so it doesn't later recreate removed columns
dataGridView1.Columns.Remove("Prop3"); //Prop3 property became a column named Prop3

我想确保在单元格编辑完成后myClass 中的值设置为 123。

但是,网格没有绑定到myClass;当您在myClass.Select(...).ToList() 中执行ToList() 并将网格绑定到新列表时,您在内存的其他位置创建了一个新的、不同的、完全独立的列表。

更糟糕的是,在 Select 中,您创建了新的匿名类型对象并将 MyClass 项的属性的数据内容复制过来,这完全断开了存储在 myClass 中的 MyClass 实例并将网格绑定到列出所有恰好有数据副本的匿名类型

当我单击一个单元格并尝试将值更改为 123 时,一旦我按 Enter 键,它就会切换回 456

压死骆驼的最后一根稻草是匿名类型是不可变的 - 你已经将你的网格绑定到一个全新的列表,其中充满了全新的只读匿名类型。

..网格永远不会影响myClass的内容

【讨论】:

    猜你喜欢
    • 2015-05-28
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    相关资源
    最近更新 更多