将简单绑定的解决方案扩展到’Text属性到多个控件以处理绑定到任何类型?

我的问题是 :如何超越编写一种技术的自定义实现, 以便为每种可能的数据类型将多个控件(没有内置DataSource属性的控件)数据绑定到简单属性…… 如下面的代码所述和演示 …以实现更强大的解决方案,该解决方案将独立于绑定是字符串,int还是其他类型。

我的猜测是:这将涉及反思; 但是,我被困在那一点上。 我正在寻找关于哪个“方向”下一步移动的战略建议,提示,线索,而不是完整的代码答案,但当然我感谢所有回复,如果你发布代码回复,我肯定会学习代码! Marc Clifton 2005年关于CodeProject 简单数据绑定的文章似乎展示了一种基于reflection的方法:但老实说,我并没有真正理解他的代码,而且就.NET来说,2005年是很久以前的。

背景:部分响应各种SO问题和答案,例如: 更新三个表单上的用户控件 :我已经发展出一种成功的技术,可以将各种控件的文本属性同时绑定到Public类中定义的一个源; 还能够使用定义一个扩展方法的静态类和两个公共方法“抽象”绑定过程的一些细节。

我已经validation了MainForm上的控件上的TextBoxes,MainForm上UserControl上的TextBoxes,以及第二个Form上的TextBox“独立”打开(即form2.Parent == null)所有更新都正确(即两个) -way binding实际上来自“DataSource等效”公共类。 改变一:改变一切。

代码:此类的实例将提供数据绑定的目标属性(theText):

public class TextDataBinder { public event PropertyChangedEventHandler PropertyChanged; private string _theText; public string theText { get { return _theText; } // note : if 'setter is declared 'internal : blocks // auto-updating when run-time user modifies consumers // but will still allow update via code set { _theText = value; OnPropertyChanged(new PropertyChangedEventArgs("theText")); } } protected void OnPropertyChanged(PropertyChangedEventArgs e) { if (this.PropertyChanged != null) { this.PropertyChanged(this, e); } } } 

代码:这个静态类可以隐藏一些绑定过程的复杂性,并允许轻松绑定到多个控件:

  public static class TextBindingExtender { public static TextDataBinder CurrentDataSource; public static void SetCurrentDataSource(TextDataBinder newCurrentDataSource) { CurrentDataSource = newCurrentDataSource; } // extension method for Control public static void AddTextBinding(this Control theControl, string controlPropertyName, string targetPropertyName) { theControl.DataBindings.Add(controlPropertyName, CurrentDataSource, targetPropertyName, false, DataSourceUpdateMode.OnPropertyChanged); } // bind to all Controls in a List public static void AddTextBindings(List theControls, string controlPropertyName, string targetPropertyName) { foreach (Control theControl in theControls) { theControl.AddTextBinding(controlPropertyName, targetPropertyName); } } } 

如何使用上述类(在Form Load事件中):

  // create a new TextDataBinder TextBindingExtender.CurrentDataSource = new TextDataBinder(); // bind to multiple textboxes, label, on a UserControl, on another Form, etc. TextBindingExtender.AddTextBindings(new List { textBox1, textBox2, userControl11.tb, label1, instanceOfForm2.tb }, "Text", "theText"); // test assigning some initial text to the bound property TextBindingExtender.CurrentDataSource.theText = "some initial text"; 

这真的取决于你想做什么; 但最终常见的数据绑定(对于简单属性,手动完成)包括:

  • 获得财产; 最好通过TypeDescriptor.GetProperties(obj)[propName] ,给你一个抽象( PropertyDescriptor
  • 询问该属性是否为只读( .IsReadOnly
  • 获取(或设置)值( .GetValue() .SetValue()
  • 要求转换器格式化/解析值( .Converter.ConvertFromString() , .ConvertToString()这是一个关键位,这意味着你不必担心数据类型是什么
  • 要求它为标题( .DisplayName ,或.Name如果它为空/ null)
  • 询问它是否支持特定于属性的通知( .SupportsChangeEvents
  • 要求它添加/删除更改处理程序( .AddValueChanged() .RemoveValueChanged()
  • 您可能还想查看对象是否支持集中通知(查找INotifyPropertyChanged

如果您可能绑定到列表而不是单个对象: – 列表可能在IListSource后面抽象 – 列表可能具有自定义属性,因此检查ITypedList – 否则,标识项的Type并使用TypeDescriptor.GetProperties(type) – 你需要考虑一个“货币管理器”(即,所有绑定到同一列表的东西都应该始终指向列表中的相同记录)

还有一些事情需要考虑ICustomTypeDescriptorTypeDescriptionProvider ,但大多数时候TypeDescriptor会自动为您处理。

正如你所看到的 – 很多事情要考虑! 很多工作……你不必做的一件事就是反思; 这是在PropertyDescriptor后面抽象的。 原因是并非所有数据都是静态类型的; 想想DataTable – 列(映射到可绑定数据属性)在编译时不是固定的,因此reflection是不合适的。 同样,一些其他类型具有自定义“属性包”实现。 PropertyDescriptor允许您的代码处理动态(不是4.0意义上的)和reflection属性相同。 它还适用于“HyperDescriptor”,另一种属性定制。