当前位置: 首页 > news >正文

【转载】[Windows Forms] : BindingSource使用模式 - Data Binding基础知识 (二)

http://www.cnblogs.com/clark159/archive/2011/10/10/2205153.html

前言 :

在文章「[.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 

相关资料 : ITypedList、 HOW TO:实作 ITypedList 界面


期許自己~
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。


 

 

转载于:https://www.cnblogs.com/yhlx125/articles/2458849.html

相关文章:

  • groovy string类型转换成int(来自csdn)不要问为什么系列6
  • svnserve:error while loading shared libraries:/usr/local/lib/libsvn_fs-1.so.0:cannot restore
  • 经常查看的一些命中率
  • 删除Exchange 2010 中的已断开连接邮箱
  • 软件开发30岁,中层管理40岁?
  • Oracle数据库 ORA-28000 错误处理方式
  • 再谈.NET Micro Framework移植
  • JRebel配置
  • python为什么叫好不叫座
  • flex togglebuttonbar 实现的导航
  • 重装TCP/IP协议
  • 事件的好处~实现对修改的封闭,对扩展的开放!~续
  • zabbix服务端的安装手册
  • PerformanceCountersHelper
  • Linux / Unix Command: va_arg
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • axios 和 cookie 的那些事
  • Go 语言编译器的 //go: 详解
  • JavaScript新鲜事·第5期
  • JavaScript学习总结——原型
  • jquery cookie
  • LeetCode算法系列_0891_子序列宽度之和
  • Spring Cloud Feign的两种使用姿势
  • use Google search engine
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 读懂package.json -- 依赖管理
  • 给新手的新浪微博 SDK 集成教程【一】
  • 如何选择开源的机器学习框架?
  • 微信支付JSAPI,实测!终极方案
  • 一文看透浏览器架构
  • 正则学习笔记
  • Java总结 - String - 这篇请使劲喷我
  • 带你开发类似Pokemon Go的AR游戏
  • ​2021半年盘点,不想你错过的重磅新书
  • ​一些不规范的GTID使用场景
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #Linux(帮助手册)
  • ${ }的特别功能
  • (007)XHTML文档之标题——h1~h6
  • (pojstep1.1.2)2654(直叙式模拟)
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (多级缓存)缓存同步
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (算法)求1到1亿间的质数或素数
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)http协议
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • *上位机的定义
  • 、写入Shellcode到注册表上线
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .NET4.0并行计算技术基础(1)
  • .Net7 环境安装配置
  • :“Failed to access IIS metabase”解决方法
  • @property python知乎_Python3基础之:property
  • @我的前任是个极品 微博分析