zoukankan      html  css  js  c++  java
  • [Windows Forms] : BindingSource使用模式 Data Binding基础知识 (二)

    前言 :

    在文章「[.NET] : BindingSource使用模式 - Data Binding基础知识 (一)」。

    介绍了如何将对象的属性包装成属性对象 「PropertyDescriptor」,并用它来做存取、监看变更等工作。
    将数据对象的属性包装成属性对象是 Data Binding运作基础,在了解这个运作之后。
    这边再来讨论,Data Binding时会用到的「数据源」。

    在大部分的书里描述,Data Binding透过 ADO.NET里的对象与数据库做互动,用来显示及存取数据库内的数据。
    在这架构下,ADO.NET里的物件是一种 Data Binding的数据源。
    相关资料 : HOW TO:使用 Windows Form BindingSource 组件排序和筛选 ADO.NET 资料

    也有一部份的数据提到的是, Data Binding也可以包装自定义数据对象,来做自定义数据对象的显示及存取。
    在这架构下,自定义数据对象包装后也是一种 Data Binding的数据源。
    相关资料 : 具有 ADO.NET 和自定义对象的数据系结应用程序

    关于 Data Binding的数据源,细分下去有许多不同的实作与定义。
    相关数据可以参考 : Windows Form 支援的数据源与数据系结相关的接口

    本篇文章简略介绍,几个设计开发 Data Binding用来包装数据源用的相关对象。
    让软件开发人员在设计 Data Binding相关程序代码时,能对对象运作模式有基础的理解。

    BindingList :

    在上列文章提供的相关数据里,能找到大量针对 Data Binding的数据源定义的接口。
    照着数据文件可以实作出,符合自己需求的数据源对象,但这是一件工作量不小的工作。

    在 System.ComponentModel命名空间里,可以找到 BindingList<T>这个物件。
    BindingList<T>实作针对 Data Binding的数据源定义的主要接口。
    并且 BindingList<T>是一个泛型类别,可以接受类别 T当作自定义数据对象。

    开发人员可以使用 BindingList<T>,来将自定义数据对象包装成数据源。
    首先建立自定义数据对象

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApplication1
    {
        public class County
        {
            // Properties
            public int CountyID { get; set; }
    
            public string CountyName { get; set; }
    
            public string CountyDescription { get; set; }
    
    
            // Constructor
            public County()
            {
                this.CountyID = 0;
                this.CountyName = string.Empty;
                this.CountyDescription = string.Empty;
            }
        }
    }
    

    再来建立 DataGridView、BindingNavigator、BindingSource系结数据

    image
    image
    image
    image
    image
    image

    最后建立数据源并系结数据

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            BindingList<County> _bindingList = new BindingList<County>();
    
            public Form1()
            {
                InitializeComponent();
    
                // Add Item
                County county1 = new County();
                county1.CountyID = 1;
                county1.CountyName = "台北市";
                county1.CountyDescription = "买不起";
                _bindingList.Add(county1);
    
                County county2 = new County();
                county2.CountyID = 2;
                county2.CountyName = "新北市";
                county2.CountyDescription = "还是买不起";
                _bindingList.Add(county2);
    
                // Data Binding
                this.countyBindingSource.DataSource = _bindingList;
            }
        }
    }

    完成,看成果。

    image

    使用 BindingList<T>有一个地方需要特别注意的,就是关于 AddingNew事件。
    AddingNew事件,主要用来通知要建立一个新的数据对象。

    当有处理 AddingNew事件,BindingList<T>会加入 AddingNew事件里带回的 NewObject。
    修改本文范例为

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApplication1
    {
        public class County
        {
            // Properties
            public int CountyID { get; set; }
    
            public string CountyName { get; set; }
    
            public string CountyDescription { get; set; }
    
    
            // Constructor
            public County()
            {
                this.CountyID = 0;
                this.CountyName = string.Empty;
                this.CountyDescription = string.Empty;
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            BindingList<County> _bindingList = new BindingList<County>();
    
            public Form1()
            {
                InitializeComponent();
    
                // Add Item
                County county1 = new County();
                county1.CountyID = 1;
                county1.CountyName = "台北市";
                county1.CountyDescription = "买不起";
                _bindingList.Add(county1);
    
                County county2 = new County();
                county2.CountyID = 2;
                county2.CountyName = "新北市";
                county2.CountyDescription = "还是买不起";
                _bindingList.Add(county2);
    
                // EventHandler
                _bindingList.AddingNew += new AddingNewEventHandler(_bindingList_AddingNew);
    
                // Data Binding
                this.countyBindingSource.DataSource = _bindingList;
            }
    
            void _bindingList_AddingNew(object sender, AddingNewEventArgs e)
            {
                County county3 = new County();
                county3.CountyID = 3;
                county3.CountyName = "桃园县";
                county3.CountyDescription = "依然买不起";
    
                e.NewObject = county3;
            }
        }
    }
    

    编译执行后,按下bindingNavigator上的『+』按钮看成果。

    image

    当没有处理 AddingNew事件并且数据对象有默认建构函式,BindingList<T>会加入数据对象默认建构函式建立新对象。
    修改本文范例为

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApplication1
    {
        public class County
        {
            // Properties
            public int CountyID { get; set; }
    
            public string CountyName { get; set; }
    
            public string CountyDescription { get; set; }
    
    
            // Constructor
            public County()
            {
                this.CountyID = 4;
                this.CountyName = "新竹市";
                this.CountyDescription = "园区无敌贵";
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            BindingList<County> _bindingList = new BindingList<County>();
    
            public Form1()
            {
                InitializeComponent();
    
                // Add Item
                County county1 = new County();
                county1.CountyID = 1;
                county1.CountyName = "台北市";
                county1.CountyDescription = "买不起";
                _bindingList.Add(county1);
    
                County county2 = new County();
                county2.CountyID = 2;
                county2.CountyName = "新北市";
                county2.CountyDescription = "还是买不起";
                _bindingList.Add(county2);
    
                // Data Binding
                this.countyBindingSource.DataSource = _bindingList;
            }
        }
    }
    

    编译执行后,按下bindingNavigator上的『+』按钮看成果。

    image

    当没有处理 AddingNew事件并且数据对象没有默认建构函式,BindingList<T>会将自己的 AllowNew属性设定为 false,不允许新增对象。
    修改本文范例为

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApplication1
    {
        public class County
        {
            // Properties
            public int CountyID { get; set; }
    
            public string CountyName { get; set; }
    
            public string CountyDescription { get; set; }
    
    
            // Constructor
            public County(int countyID)
            {
                this.CountyID = countyID;
                this.CountyName = string.Empty;
                this.CountyDescription = string.Empty;
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            BindingList<County> _bindingList = new BindingList<County>();
    
            public Form1()
            {
                InitializeComponent();
    
                // Add Item
                County county1 = new County(1);
                county1.CountyName = "台北市";
                county1.CountyDescription = "买不起";
                _bindingList.Add(county1);
    
                County county2 = new County(2);
                county2.CountyName = "新北市";
                county2.CountyDescription = "还是买不起";
                _bindingList.Add(county2);
    
                // Data Binding
                this.countyBindingSource.DataSource = _bindingList;
            }
        }
    }
    

    编译执行后,会发现禁止按下bindingNavigator上的『+』按钮,不允许新增。

    image

    相关资料 : BindingList(Of T)BindingSource.AddingNew

    ITypedList :

    Data Binding在运作的时候,会依照数据源解析出数据对象,再将数据对象的属性包装成属性对象 PropertyDescriptor。
    运作模式的相关数据可以参考 : [.NET] : BindingSource使用模式 - Data Binding基础知识 (一)

    当开发人员要在 Data Binding时使用自定义 PropertyDescriptor来做属性的存取显示时,实作 ITypedList接口就可以取代默认的运作流程。
    首先建立自定义 PropertyDescriptor

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    
    namespace WindowsFormsApplication1
    {
        public class SamplePropertyDescriptor : PropertyDescriptor
        {
            // Properties
            private readonly PropertyDescriptor _component = null;
    
    
            // Constructor
            public SamplePropertyDescriptor(PropertyDescriptor component)
                : base(component)
            {
                #region Require
    
                if (component == null) throw new ArgumentNullException("component");
    
                #endregion
                _component = component;
            }
    
    
            // Properties
            public override Type ComponentType
            {
                get
                {
                    return _component.ComponentType;
                }
            }
    
            public override TypeConverter Converter
            {
                get
                {
                    return _component.Converter;
                }
            }
    
            public override bool IsLocalizable
            {
                get
                {
                    return _component.IsLocalizable;
                }
            }
    
            public override bool IsReadOnly
            {
                get
                {
                    return _component.IsReadOnly;
                }
            }
    
            public override Type PropertyType
            {
                get
                {
                    return _component.PropertyType;
                }
            }
    
    
            // Methods
            public override object GetValue(object component)
            {
                return (component as County).CountyDescription + "$$$$$$$$";
            }
    
            public override void SetValue(object component, object value)
            {
                _component.SetValue(component, (value as string).Replace("$$$$$$$$", string.Empty));
            }        
    
            public override void ResetValue(object component)
            {
                _component.ResetValue(component);
            }
    
            public override bool CanResetValue(object component)
            {
                return _component.CanResetValue(component);
            }
    
            public override bool ShouldSerializeValue(object component)
            {
                return _component.ShouldSerializeValue(component);
            }
    
    
            public override object GetEditor(Type editorBaseType)
            {
                return _component.GetEditor(editorBaseType);
            }
    
            public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)
            {
                return _component.GetChildProperties(instance, filter);
            }
    
    
            public override void AddValueChanged(object component, EventHandler handler)
            {
                _component.AddValueChanged(component, handler);
            }
    
            public override void RemoveValueChanged(object component, EventHandler handler)
            {
                _component.RemoveValueChanged(component, handler);
            }
        }
    }

    再来建立继承 BindingList及实作 ITypedList的自定义BindingList

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    
    namespace WindowsFormsApplication1
    {
        public class SampleBindingList : BindingList<County>, ITypedList
        {
            public string GetListName(PropertyDescriptor[] listAccessors)
            {
                return typeof(County).Name;
            }
    
            public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
            {
                if (listAccessors != null && listAccessors.Length > 0)
                {
                    throw new InvalidOperationException();
                }
                else
                {
                    // Result
                    List<PropertyDescriptor> propertyDescriptorCollection = new List<PropertyDescriptor>();
    
                    // Create           
                    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(typeof(County)))
                    {
                        if (propertyDescriptor.Name == "CountyDescription")
                        {
                            propertyDescriptorCollection.Add(new SamplePropertyDescriptor(propertyDescriptor));
                        }
                        else
                        {
                            propertyDescriptorCollection.Add(propertyDescriptor);
                        }
                    }
    
                    // Return
                    return new PropertyDescriptorCollection(propertyDescriptorCollection.ToArray());
                }
            }
        }
    }
    

    最后修改本文范例为

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApplication1
    {
        public class County
        {
            // Properties
            public int CountyID { get; set; }
    
            public string CountyName { get; set; }
    
            public string CountyDescription { get; set; }
    
    
            // Constructor
            public County()
            {
                this.CountyID = 0;
                this.CountyName = string.Empty;
                this.CountyDescription = string.Empty;
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            SampleBindingList _bindingList = new SampleBindingList();
    
            public Form1()
            {
                InitializeComponent();
    
                // Add Item
                County county1 = new County();
                county1.CountyID = 1;
                county1.CountyName = "台北市";
                county1.CountyDescription = "买不起";
                _bindingList.Add(county1);
    
                County county2 = new County();
                county2.CountyID = 2;
                county2.CountyName = "新北市";
                county2.CountyDescription = "还是买不起";
                _bindingList.Add(county2);
    
                // Data Binding
                this.countyBindingSource.DataSource = _bindingList;
            }
        }
    }
    

    完成,看成果。

    image

    相关资料 : ITypedListHOW TO:实作 ITypedList 界面

  • 相关阅读:
    SpringMVC 多文件上传
    get传参乱码问题
    springMVC配置
    带参sql$和#的区别(注解)
    java多线程--实现Runnable接口方式
    java复制文件夹及所有子目录和文件
    Angularjs 学习笔记
    springboot 项目 docker化部署
    docker 基础
    Java-马士兵动态代理模式
  • 原文地址:https://www.cnblogs.com/clark159/p/2205153.html
Copyright © 2011-2022 走看看