WinForms中BindingSource触发PropertyChanged后UltraCombo值重置问题
场景重现
我将部分控件绑定至Windows.Forms.BindingSource,数据类实现INotifyPropertyChanged接口用于数据库交互,核心代码如下:
public class MyClass: INotifyPropertyChanged { public String Bezeichnung { get => _row["bez"].ToString(); set { if (value == null) _row["bez"] = DBNull.Value; else _row["bez"] = value; NotifyPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName] String name = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } // 其他属性省略...
窗体中,第三方组合框Infragistics UltraCombo绑定至Bezeichnung属性,并设置了ValueChanged事件。但在事件中修改数据类的Otherproperty属性时,会再次触发该事件,组合框值被重置为初始值,无法正常修改:
private void Combo_ValueChanged(object sender, EventArgs e) { // 其他业务逻辑... dbclass.Otherproperty = 42.9; // 修改该属性触发PropertyChangedEvent后,此函数再次被调用,组合框值恢复为初始值 }
我猜测这与PropertyChanged事件触发有关,BindingSource似乎会重新绑定所有数据。设置DataSourceUpdateMode.OnPropertyChanged也无效。
解决方案
核心原因
修改Otherproperty触发PropertyChanged时,若BindingSource的数据源是DataRowView这类数据库行对象,可能触发整个数据源刷新,导致BindingSource推送所有属性的变更通知——包括已修改的Bezeichnung。而你的Bezeichnung getter直接从_row["bez"]取值,若此时数据库行的bez字段未正确更新(或因某种原因回退旧值),就会导致UltraCombo接收到旧值通知,重置显示内容。此外,Infragistics UltraCombo的ValueChanged事件在数据绑定同步时也可能被触发,形成循环。
修复步骤
用本地字段缓存属性值,避免直接读写DataRow
修改MyClass的Bezeichnung属性,用本地字段存储值,确保getter返回最新的修改后的值,不会因DataRow刷新回退:private string _bezeichnung; public string Bezeichnung { get => _bezeichnung; set { if (_bezeichnung == value) return; // 避免无意义的变更通知 _bezeichnung = value; _row["bez"] = value ?? DBNull.Value; NotifyPropertyChanged(); } }临时禁用事件避免循环触发
在ValueChanged事件中修改Otherproperty前,先移除事件绑定,修改完成后重新绑定:private void Combo_ValueChanged(object sender, EventArgs e) { // 临时移除事件绑定 var combo = sender as UltraCombo; combo.ValueChanged -= Combo_ValueChanged; // 执行属性修改逻辑 dbclass.Otherproperty = 42.9; // 重新绑定事件 combo.ValueChanged += Combo_ValueChanged; }尝试替换为UltraCombo专属事件
Infragistics控件提供了绑定相关的替代事件,比如SelectionChanged,可避免绑定同步时的误触发:private void Combo_SelectionChanged(object sender, EventArgs e) { dbclass.Otherproperty = 42.9; }确认BindingSource配置
确保BindingSource的DataSourceUpdateMode设置为OnPropertyChanged,同时数据类的PropertyChanged事件仅触发对应属性的通知(你的NotifyPropertyChanged使用CallerMemberName是正确的,无需修改)。
内容的提问来源于stack exchange,提问作者Me3nTaL

