WinForm中实现IEnumerable<>的对象无法绑定属性的解决方法
解决WinForms绑定实现IEnumerable的类时无法访问自身属性的问题
这个问题我之前也碰到过,WinForms的数据绑定机制对实现IEnumerable<T>的类有特殊逻辑:它会默认把这类对象当成集合数据源,尝试遍历集合内的元素去寻找指定的dataMember,而不是访问类自身的属性——这就是为什么你绑定Comments时会抛出找不到属性的异常。
下面给你几个可行的解决办法,你可以根据自己的场景选择:
方法1:给数据源套一个非集合的包装类
最简单的方式是把FunctionList对象放到一个普通的包装对象里(比如匿名类或者专门的ViewModel),让绑定系统识别这是单个对象而非集合:
// 用匿名类做包装 var dataWrapper = new { TargetList = functionList }; // 绑定路径指向包装类的TargetList属性下的Comments this.checkEdit1.DataBindings.Add( new Binding( nameof(this.checkEdit1.EditValue), dataWrapper, "TargetList.Comments", false, DataSourceUpdateMode.OnPropertyChanged ) );
方法2:给类添加类型转换器特性
通过给FunctionList添加[TypeConverter(typeof(ExpandableObjectConverter))]特性,告诉WinForms的类型系统:这个类是一个可展开的业务对象,而非集合。这种方式不需要额外包装,代码更优雅:
using System.ComponentModel; // 添加这个特性,让绑定系统把类当作普通对象处理 [TypeConverter(typeof(ExpandableObjectConverter))] public class FunctionList : IEnumerable<Function> { public string Comments {get; set;} public IEnumerator<Function> GetEnumerator() { return ...; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } }
添加特性后,你原来的绑定代码可以直接正常工作,不需要修改绑定逻辑。
方法3:使用BindingSource作为中间层(需注意配置)
如果你已经在使用BindingSource管理数据源,可以把FunctionList赋值给BindingSource,同时确保绑定系统不会把它识别为集合。不过这种方式需要注意,默认BindingSource还是会优先把IEnumerable当作集合,所以最好结合包装的思路:
var bindingSource = new BindingSource(); // 用匿名类包装后再赋值给BindingSource bindingSource.DataSource = new { TargetList = functionList }; this.checkEdit1.DataBindings.Add( new Binding( nameof(this.checkEdit1.EditValue), bindingSource, "TargetList.Comments", false, DataSourceUpdateMode.OnPropertyChanged ) );
内容的提问来源于stack exchange,提问作者BennoDual
相关产品推荐
相关产品推荐

