我在Windows窗体中有一个ComboBox(DropDownList样式),它的数据源设置为BindingList,并且SelectedValue属性绑定到viewmodel的属性。
请注意,绑定设置为OnPropertyChanged
而不是OnValidate
,这是因为使用OnValidate
时控件不一定会更新ViewModel表单已关闭或失去焦点(但控件仍认为它具有焦点。在Compact Framework上,无法强制验证,因此我必须使用OnPropertyChanged
。
在桌面Windows窗体和智能设备Windows窗体上都存在可重现的问题:当尝试在组合框中选择或设置当前项目时(使用鼠标或键盘),该值不会是"棒"直到它被设置两次 - 也就是说,你需要在组合框的值改变之前选择相同的项目两次。
没有抛出异常(甚至被捕获的异常),也没有可用的诊断报告。
我不认为这是框架中的错误,并且它在Desktop和Compact Framework上的发生方式很有趣。
这是我的代码:
public partial class Form1 : Form {
private ViewModel _vm;
public Form1() {
InitializeComponent();
this.bindingSource1.Add( _vm = new ViewModel() );
}
}
//
// bindingSource1
//
this.bindingSource1.DataSource = typeof( WinForms.Shared.ViewModel );
//
// comboBox1
//
this.comboBox1.DataBindings.Add( new System.Windows.Forms.Binding( "SelectedValue", this.bindingSource1, "SelectedSomeTypeId", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged ) );
this.comboBox1.DataSource = this.someTypeListBindingSource;
this.comboBox1.DisplayMember = "DisplayText";
this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point( 12, 27 );
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size( 182, 21 );
this.comboBox1.TabIndex = 0;
this.comboBox1.ValueMember = "Id";
//
// someTypeListBindingSource
//
this.someTypeListBindingSource.DataMember = "SomeTypeList";
this.someTypeListBindingSource.DataSource = this.bindingSource1;
public class ViewModel : INotifyPropertyChanged {
public ViewModel() {
this.SomeTypeList = new BindingList<SomeType>();
for(int i=0;i<5;i++) {
this.SomeTypeList.Add( new SomeType() {
Id = i + 1,
Name = "Foo" + ((Char)( 'a' + i )).ToString()
} );
}
this.SelectedSomeTypeId = 2;
}
public BindingList<SomeType> SomeTypeList { get; private set; }
private Int64 _selectedSomeTypeId;
public Int64 SelectedSomeTypeId {
get { return _selectedSomeTypeId; }
set {
if( _selectedSomeTypeId != value ) {
_selectedSomeTypeId = value;
OnPropertyChanged("SelectedSomeTypeId");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String propertyName) {
PropertyChangedEventHandler handler = this.PropertyChanged;
if( handler != null ) handler( this, new PropertyChangedEventArgs(propertyName) );
}
}
public class SomeType {
public String Name { get; set; }
public Int64 Id { get; set; }
public String DisplayText {
get { return String.Format("{0} - {1}", this.Id, this.Name ); }
}
}
答案 0 :(得分:3)
我从未找到解决此问题的“正确”方法,并且通常使用以下两种方法之一来使事情发挥作用:
直接:绕过这一条目的绑定机制
combo1.SelectedIndexChanged += (s,e) _viewModel.Item = combo1.SelectedItem;
通用绑定:创建自定义ComboBox并覆盖OnSelectedIndexChanged事件以强制进行绑定更新。
public class BoundComboBox : ComboBox
{
protected override void OnSelectedIndexChanged(EventArgs e)
{
var binding = this.DataBindings["SelectedItem"];
if( binding != null )
binding.WriteValue();
base.OnSelectedIndexChanged(e);
}
}