我有一个数据绑定组合框。它的约束如下:
cbo.DataBindings.Add(new Binding("SelectedItem", this.bindingSource, "Order", true, DataSourceUpdateMode.OnPropertyChanged, null));
它的填充如下:
cbo.DataSource = customer.Orders.Where(x => x.Month == month).ToList();
cbo.ValueMember = "OrderId";
cbo.DisplayMember = "OrderDate";
cbo.SelectedIndex = -1;
数据源是BindingSource
,它又绑定到DTO类。
如果我选择一个项目并使用TAB
将焦点移至另一个控件,则SelectedItem
设置正确。
但是,如果我选择一个项目并点击另一个控件,那么当标签退出控件时,SelectedItem
将成为之前选择的项目。
我尝试过绑定SelectedItem
,SelectedValue
,OnPropertyChanged
和OnValidation
的混合物,但如果没有标记,则会导致同样的问题。
在此SO answer中给出了部分解决方案,但是,就我而言,它不起作用。
目前的解决方法是:
(bindingSource.Current as Customer).Order = selectedOrder;
这应该是不必要的,因为数据源是绑定的。有没有更好的方法来强制在单击另一个控件而不是标签时提交更改?
答案 0 :(得分:1)
问题是ComboBox
没有提供正确绑定到SelectedItemChanged
所需的SelectedItem
事件。
您应该绑定到SelectedValue
,这样可以正常工作。问题是无法指定使用DisplayMember
作为显示,将数据源对象指定为ValueMember
。解决它的一种方法是使用专用对象(a.k.a.视图模型)作为列表元素。例如,使用匿名类型投影:
cbo.DisplayMember = "OrderDate";
cbo.ValueMember = "Order";
cbo.DataSource = customer.Orders.Where(x => x.Month == month)
.Select(o => new { o.OrderDate, Order = o })
.ToList();
cbo.DataBindings.Add(new Binding("SelectedValue", bindingSource, "Order", true, DataSourceUpdateMode.OnPropertyChanged, null));
答案 1 :(得分:0)
理论上" OnPropertyChanged"当控件失去焦点时,将强制执行数据绑定以将值写入底层对象。但不知怎的,它没有;所以我想在某处数据绑定没有正确完成:
是绑定到正确对象的数据绑定吗?
是否在更改绑定对象时清除了先前的数据绑定?
您是否尝试直接将this.bindingSource更改为您的对象,而不是通过bindingSource包装器?
通常,如果您希望强制将数据写回对象以进行数据绑定,则可以调用binding.WriteValue()。
如下所示:
cbo.LostFocus += (object sender, EventArgs e) => {
foreach (Binding b in cbo.DataBindings)
{
if (string.Equals(b.PropertyName, "SelectedItem"))
{
b.WriteValue();
}
}
};