【问题标题】:Datagridview databinding when create new object on create new row在创建新行时创建新对象时的 Datagridview 数据绑定
【发布时间】:2012-06-25 12:12:21
【问题描述】:

DataGridViewPropertyGrid 之间的数据绑定有点问题。

这是我绑定的对象的代码和DataGridView

 public class Effort
 {
     public BindingList<EffortCalculationRelation> CalculationRelations { get; set; }
     public int ID { get; set; }
     // more properties

     public Effort()
     {
         CalculationRelations = new BindingList<EffortCalculationRelation>();
         CalculationRelations.Clear();

         for (int i=0;i<10;i++)
         {
             CalculationRelations.Add( new EffortCalculationRelation() { ID = i, Name = "Round:" + i.ToString(), calculation = "Some calc" });
         }
     }

     public Effort(int id) : this()
     {
         this.ID = id;
         // Load all other properties
     }

     public class EffortCalculationRelation
     {
         public int ID { get; set; }
         public string Name { get; set; }
         public string calculation { get; set; }


         public int Save()
         {
             // save or insert and return id or 0 on fail
             if (this.ID > 0)
             {
                 return this.Update();
             }
             else
             {
                 return this.Insert();
             }
         }
         public string Delete()
         {
             // delete and return "" or errormsg on fail
             return "";
         }
         private int Insert()
         {
             // insert and return id or 0 on fail
             return ID;
         }
         private int Update()
         {
             // return affected rows or 0 on fail
             return 1;
         }

         public string Representation
         {
             get { return String.Format("{0}: {1}", ID, Name); }
         }
     }
 }

datagridview 连接真的很简单,只有一点点样式:

  public test()
  {
     effort = new Effort(1209);
     dgv.DataSource = effort.CalculationRelations;
     dgv.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
     dgv.AllowUserToAddRows = true;
     //this.dgv.AllowUserToDeleteRows = false;
     dgv.AllowUserToResizeRows = false;
     dgv.ReadOnly = true;
     dgv.SelectionChanged += (sender, args) =>
     {
         var selectedObjects =
              (from System.Windows.Forms.DataGridViewRow r in dgv.SelectedRows
              where r.DataBoundItem != null && r.DataBoundItem.GetType() == typeof(EffortCalculationRelation)
              select r.DataBoundItem).ToArray();

         // pg is a propertygrid
         this.pg.SelectedObjects = selectedObjects;
     };
  }

所以我的问题是,当我在 datagridview 中选择新行时,propertygrid 中没有显示任何属性。

当我在加载时选择列表中包含对象的行时,我可以编辑属性。

那你能帮忙吗?

【问题讨论】:

  • 您提供的代码不能按原样工作。我将使用我相信您跳过的代码对其进行编辑,但请检查我所做的是否正确,并通过进一步的代码准确给出您所拥有的。
  • 对不起,我看到了,它是正确的,它是我工作源的剪辑版。
  • 您必须提供多项选择吗?如果您使用SelectedObject 而不是SelectedObjects,这将非常有效。我正在研究为什么新行现在不起作用。
  • 是的,有多个选择可用,我需要所有选定的对象,因为必须可以同时更改所有选定对象的值。它工作正常,但当我选择新行时不行。
  • 发生这种情况的原因实际上非常简单 - 在新行提交之前不存在任何数据绑定项。不过仍在尝试寻找解决方案,目前正在尝试使用 BindingSource 以查看是否有帮助。

标签: c# data-binding datagridview


【解决方案1】:

新行未显示在属性网格中的原因是其DataBoundItem 为空,因此被您的LINQ 语句where r.DataBoundItem != null 删除。 1

我同意你的观点,这是非常烦人的行为,特别是因为对象在某种意义上已经被创建了。

我曾认为在某些情况下有一种可行的解决方法,可以使用以下代码将属性网格绑定到父 Effort 对象或 BindingSource 中的新对象:

var selectedObjects =
        (from System.Windows.Forms.DataGridViewRow r in dataGridView1.SelectedRows
        where r.DataBoundItem != null && r.DataBoundItem.GetType() == typeof(Effort.EffortCalculationRelation)
        select r.DataBoundItem).ToArray();

if (dataGridView1.CurrentRow.IsNewRow && dataGridView1.SelectedRows.Count == 1)
{
    // I tried accessing the parent object like this:
    //Effort.EffortCalculationRelation ecr = effort.CalculationRelations[effort.CalculationRelations.Count - 1];
    //propertyGrid1.SelectedObject = ecr;

    // Or accessing a binding source like:
    propertyGrid1.SelectedObject = calculationRelations.Current;
}
else
{
    propertyGrid1.SelectedObjects = selectedObjects;
}

我对这些变体进行了一些试验,并将这些项目添加到 SelectedObjects 数组中,认为某些东西会满足您的要求,但我最终意识到 将焦点从新行转移到 DataGridView 之前的属性网格已提交新行意味着新行已丢失且无法再编辑

那么 - 怎么办?

如果我在你的位置,我会考虑以下两件事之一:

  • 允许在某种形式的网格中直接编辑 - 可能只是到新行。

    在选择更改事件中这样的事情会起作用:

    if (dataGridView1.CurrentRow.IsNewRow)
    {
        dataGridView1.CurrentRow.ReadOnly = false;
    }
    else
    {
        dataGridView1.CurrentRow.ReadOnly = true;
    }
    
  • 保持网格不变,但不允许新行 - 而是在单独的行创建面板之间处理新对象。


1 这显然是通过设计以这种方式工作的 - 在您离开网格之前不会提交 DataBoundItem。有一些讨论,包括有问题的DataGridView 代码here

【讨论】:

  • 非常感谢大卫,我使用了另一种解决方法。我创建了一个按钮,将一个新项目添加到数据绑定列表中,当它被创建时,网格将显示该对象。
猜你喜欢
  • 1970-01-01
  • 2011-02-02
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
相关资源
最近更新 更多