代码之家  ›  专栏  ›  技术社区  ›  BillW

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

  •  3
  • BillW  · 技术社区  · 16 年前

    :如何超越编写用于数据绑定多个控件(没有内置数据源属性的控件)的技术的自定义实现, 对于每种可能的数据类型 ,到简单属性。。。 ... 实现一个更强大的解决方案,该解决方案将独立于绑定到字符串、int或其他类型。

    我的猜测是:这将涉及反思;但是,我被困在那一点上。我在寻找关于下一步行动方向的战略建议,提示,线索,不是一个完整的代码答案,但我当然感谢所有的回答,如果你在回复中发布代码,我一定会研究代码!Marc Clifton 2005年关于CodeProject的文章 Simple Databinding :似乎演示了一种基于反射的方法:但是,老实说,我并没有真正研究他的代码,而且,就.NET而言,2005是一个 长的 很久以前。

    背景:部分是为了回答各种问题和答案,如: Update Usercontrol on Three Forms :我开发了一种成功的技术,可以将各种控件的文本属性同时数据绑定到公共类中定义的一个源;我们还可以使用定义一个扩展方法和两个公共方法的静态类来“抽象”绑定过程的一些细节。

    我已经验证了“MainForm”中控件上的TextBox、MainForm中UserControl上的TextBox以及“独立”打开的第二个窗体上的TextBox(即form2.Parent==null)都从“DataSource equivalent”公共类正确更新(即双向绑定生效)。改变一:改变一切。

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

        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<Control>
            public static void AddTextBindings(List<Control> theControls, string controlPropertyName, string targetPropertyName)
            {
                foreach (Control theControl in theControls)
                {
                    theControl.AddTextBinding(controlPropertyName, targetPropertyName);
                }
            }
        }
    

    如何使用上述类(在窗体加载事件中):

        // create a new TextDataBinder
        TextBindingExtender.CurrentDataSource = new TextDataBinder();
    
        // bind to multiple textboxes, label, on a UserControl, on another Form, etc.
        TextBindingExtender.AddTextBindings(new List<Control> { textBox1, textBox2, userControl11.tb, label1, instanceOfForm2.tb }, "Text", "theText");
    
        // test assigning some initial text to the bound property
        TextBindingExtender.CurrentDataSource.theText = "some initial text";
    
    1 回复  |  直到 9 年前
        1
  •  3
  •   Marc Gravell    16 年前

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

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

    如果你和一个 列表 -清单可能会被抽象出来 IListSource -列表可能有自定义属性,因此请检查 ITypedList Type 物品和用途 TypeDescriptor.GetProperties(type)

    也有类似的事情 ICustomTypeDescriptor TypeDescriptionProvider 考虑一下,但大部分时间 TypeDescriptor 自动为您处理。

    正如你所看到的-有很多事情要考虑!很多工作。。。你能做的一件事 不要 要做的就是反思;这是抽象的背后 属性描述器 . 原因是不是所有的数据都是静态类型的;考虑 DataTable -这些列(映射到可绑定数据属性)在编译时是不固定的,因此反射是不合适的。同样,其他一些类型也有自定义的“属性包”实现。 属性描述器