CodeGo.net>扩展解决方案,以简单地绑定到’Text属性到多个控件以处理绑定到任何类型?

我的问题是:如何超越编写用于对各种控件(没有内置DataSource属性的控件)进行数据绑定的技术的自定义实现,将每种可能的数据类型绑定到简单的属性……如下面的代码中所描述和演示的…以获得更强大的解决方案,而该解决方案将与绑定是绑定到字符串,int还是其他类型无关.

我的猜测是:这将涉及反思.但是,我被困在那一点上.我正在寻找下一个“方向”的战略建议,提示,线索,而不是完整的代码答案,但是我当然感谢所有答复,并且如果您张贴代码作为答复,我一定会研究代码!马克·克利夫顿(Marc Clifton)在2005年关于CodeProject Simple Databinding的文章:似乎演示了一种基于反射的方法:但是,老实说,我并没有真正理解他的代码,就.NET而言,2005年已经很久了.

背景技术:部分响应于各种SO问题和答案,例如:Update Usercontrol on Three Forms:我已经开发出一种成功的技术,可以将各种控件的文本属性同时数据绑定到Public类中定义的一个源.还可以使用定义一个扩展方法和两个公共方法的静态类“抽象”绑定过程的某些细节.

我已验证“ MainForm”上控件上的TextBoxes,MainForm上UserControl上的TextBoxes和“独立”打开的第二个Form(即form2.Parent == null)上的TextBox都可以正确更新(即,两个-way绑定有效)来自“ 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<Control>
        public static void AddTextBindings(List<Control> 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<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";

解决方法:

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

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

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

还有一些类似ICustomTypeDescriptor和TypeDescriptionProvider的东西需要考虑,但是大多数时候TypeDescriptor会自动为您处理.

如您所见-有很多事情要考虑!许多工作……您不必做的一件事就是反思.这是在PropertyDescriptor之后抽象的.这是因为并非所有数据都是静态类型的.考虑一下DataTable-列(映射到可绑定数据属性)在编译时不是固定的,因此反射是不合适的.同样,其他一些类型也具有自定义的“属性包”实现. PropertyDescriptor允许您的代码以相同方式处理动态(非4.0含义)和反射属性.它也可以很好地与“ HyperDescriptor”(另一个属性自定义)之类的东西配合使用.

上一篇:C#-WndProc处理程序效率低下


下一篇:c#-MVP被动视图-将视图数据和模型数据分开