我在DataGridView
和PropertyGrid
之间的数据绑定方面遇到了一些问题。
以下是我绑定的对象和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中没有显示任何属性。
当我在加载时选择列表中有对象的行时,我可以编辑属性。
你能帮忙吗?
答案 0 :(得分:0)
新行未在属性网格中显示的原因是其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没有提交。有一点讨论,包括问题here中的DataGridView
代码。