.NET快速开发实践中的IExtenderProvider扩展组件

          说起扩展编程组件,我们不得不起到一个接口IExtenderProvider,参考msdn的定义:定义将属性扩展到容器中的其他组件的接口;下面我贴上IExtenderProvider的定义:

    /// <summary>
    /// 定义将属性扩展到容器中的其他组件的接口。
    /// </summary>
    public interface IExtenderProvider
    {
        /// <summary>
        /// 指定此对象是否可以将其扩展程序属性提供给指定的对象。
        /// </summary>
        /// <param name="extendee">要接收扩展程序属性的System.Object。</param>
        /// <returns>如果此对象可以扩展程序属性提供给指定对象,则为true;否则为false。</returns>
        bool CanExtend(object extendee);
    }

          根据定义我们可以理解为,实现了IExtenderProvider接口的某个控件或者组件有扩展其他组件的能力,IExtenderProvider接口借助VisualStudio设计器的功能,使我们可以动态的为控件增加属性,并可以在设计时通过属性窗口修改这些属性,而不需要继承控件类。这样做的最大好处是可以借助Visual Studio的能力,并保持控件原有的设计时支持。

          IExtenderProvider接口组件提供了一种与容器中其他组件的粘合能力,这无疑是为我们提供了另一种组件的扩展思想,我理解为侵入编程,假设没有这个方式,我们扩展一个组件需求继承原有的组件并且增加一个或多个扩展属性,比如我们要达到这么一个目的,界面上指定的方本模框必须输入字符才能离开输入焦点,如果我们用传统方法,需求重写TextBox控件,代码如下:

    public class TextBoxEx:TextBox
    {
        protected override void OnDragLeave(EventArgs e)
        {
            if (this.allowInput)
            {
                if(this.Text.Trim().Length ==0)
                {
                    MessageBox.Show("文本框必须输入字符!", "提示", MessageBoxButtons.OK, 
                      MessageBoxIcon.Information);
                    if (this.CanFocus)
                        this.Focus();
                }

                base.OnDragLeave(e);
            }
        }

        /// <summary>
        /// 是否容器输入为空。
        /// </summary>
        [Category("验证")]
        [Description("获取/设置是否必须输入")]
        [DefaultValue(false)]
        [Browsable(true)]
        public bool AllowInput
        {
            get
            {
                return this.allowInput;
            }
            set
            {
                this.allowInput = value;
            }
        }

        /// <summary>
        /// 默认必须输入字符。
        /// </summary>
        private bool allowInput = false;
    }

          我们来在UI上拖一个TextBoxEx控件,可以通过设置属性AllowEmpty来控件是否允许输入空值:

          以下这种方式可以理解为.NET的原生实现方式,需求继续原来控件,并且在应用过程上需要调用UI的控件,比较麻烦,下面我们来用IExtenderProvider做一个实现:

    [ToolboxItem(true)]
    [Description("TextBox必须输入组件。")]
    [ProvideProperty("AllowInput", typeof(TextBox))]
    public partial class TextBoxAllowInput : Component, System.ComponentModel.IExtenderProvider
    {
        private Dictionary<TextBox, bool> allowInputList = null;
        public TextBoxAllowInput()
        {
            InitializeComponent();
            allowInputList = new Dictionary<TextBox, bool>();
        }

        public TextBoxAllowInput(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
            allowInputList = new Dictionary<TextBox, bool>();
        }

        [Category("输入验证")]
        [Description("获取/设置文本框是否必须输入")]
        public bool GetAllowInput(TextBox textBox)
        {
            if (allowInputList.ContainsKey(textBox))
            {
                return (bool)allowInputList[textBox];
            }
            return false;
        }

        public void SetAllowInput(TextBox textBox, bool allowInput)
        {
            if (!allowInputList.ContainsKey(textBox))
            {
                allowInputList.Add(textBox, allowInput);
                textBox.Leave += new EventHandler(textBox_Leave);
            }
            else
            {
                allowInputList[textBox] = allowInput;
            }
        }

        void textBox_Leave(object sender, EventArgs e)
        {
            TextBox tb = sender as TextBox;
            if (this.GetAllowInput(tb))
            {
                if (tb.Text.Trim().Length == 0)
                {
                    MessageBox.Show("文本框必须输入字符!", "提示", MessageBoxButtons.OK, 
                      MessageBoxIcon.Information);
                    if (tb.CanFocus)
                        tb.Focus();
                }
            }
        }        

        public bool CanExtend(object extendee)
        {
            return (extendee is TextBox); //只扩展TextBox
        }
    }

          我们来在UI上拖一个几个TextBox控件,再拖一个TextBoxAllowInput 组件,我们可以通过设置TextBox的在TextBoxAllowInput 上的扩展属性AllowEmpty来控件是否允许输入空值:

          上例简单的介绍了一下IExtenderProvider接口及其背后的编程思想,在开发过程中,我们可以应用这种侵入式编程接口实现很多的扩展组件如数据绑定、输入验证、焦点跳转、输入法切换等多种多样的快捷编程辅助组件。

          下面我将会介绍基于IExtenderProvider扩展技术的UI控件与实体的数据绑定组件。

QQ群:15118502

链接:AgileEAS.NET应用开发平台介绍

AgileEAS.NET之敏捷并行开发方法

敏捷软件工程实验室

时间: 2024-10-31 18:00:55

.NET快速开发实践中的IExtenderProvider扩展组件的相关文章

.NET快速开发实践之应用IExtenderProvider实现控件焦点跳转

         我在前面的.NET快速开发实践中的IExtenderProvider扩展组件和其他两篇Post介绍了IExtenderProvider扩展编程模式和应用IExtenderProvider实现实体与对象的做法与例子,下面我为介绍一下在管理信息系统开发中一个常用的功能,控件的输入焦点跳转,我们知道,系统为我们提供了Tab和Shift+Tab切换输入焦点的功能,但是这里面有一个问题,即最终操作者最不习惯于使用Tab进行切换输入焦点,因为都已经习惯于无鼠标操作,常使用回车,上下方向键进

.NET快速开发实践之应用IExtenderProvider实现输入法自动切换

         我在前面的.NET快速开发实践中的IExtenderProvider扩展组件和.NET快速开发实践之应用IExtenderProvider实现对象与UI控件的绑定两篇Post介绍了IExtenderProvider扩展编程模式和应用IExtenderProvider实现实体与对象的做法与例子,下面我为介绍一下在管理信息系统开发中一个常用的功能,输入法的切换,很多在线事务处理系统业务量非常的繁忙,在特定的某个时刻,比如在his应用中的挂号.收费,窗口业务中业务办理者排着长长的队,

.NET快速开发实践之应用IExtenderProvider实现对象与UI控件的绑定

         现在企业级的信息系统应用开发之中,数据层采用了ORM,解放了之前开发最大工作量的核对SQL语句,我到现在还曾经记得在2002年实医院管理信息系统时对齐一个插入数据的SQL语言搞的我头大,从那之后就能不能把这样的东西换个方式,之后搞.NET有了ORM,对齐SQL语句的事终于解放了,但是界面上的UI与ORM对象之间的数据交互避免不了,把数据实体的值显示在UI控件上或者把UI控件的值更新到数据对象,我们不得不这样去写:          取实体的值并显示在界面: private vo

软件开发实践中的入队列和出队列操作的C代码示例

概述 最近有在校的学生朋友在问我,数据结构中的队列在实际的软件开发项目中有什么样的用处. 大家都知道,队列的特点是先入先出,即数据是按照入队列的顺序出队列的.在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列就可以大展身手了.我们可以将接收到的数据存储在一个全局队列中,然后在另外的程序流程中将数据从同一个全局队列中取出来,经过一定的处理之后将消息发送到另外的模块.这样做可以降低程序的性能瓶颈. 本文用实际的C代码示例了简单的数据入队列和出队列的方法,大家可据此了解队列的实际用

Tiny快速入门之Web界面快速开发实践

本来想改改OSChina的界面,但是研究了一下,OSChina界面实在是高大上呀,不是做不出来,只是工作量比较大,因此还是做个简单的网站来展示一下用Tiny开发界面的过程,同时在展示过程的同时,会把相关的知识做一个充分的介绍 . 一.寻找网站模板 要做网站,不能没有模板,自己不会做网页设计,咋办?问谷歌找百度呗,找了一阵,看到下面这个模板不错,就它了. http://www.tooplate.com/zip_files/2042_the_block.zip 相仔细了解这篇文章的同学,建议把原板的

COM组件开发实践(一)

开发实践(一)-前端组件化开发实践"> Preface 因为项目需要,开始从事ActiveX方面的工作,看了一些资料,可惜都是些COM原理方面的,没有切合实际动手的东西,在CodeProject上读完David Marcionek的文章[1]后,收获良多,但也遇到一些恼人的小问题,因此在其基础上就一些易错点做些小注解.本文版权归David Marcionek所有. 简介 在本文中,我们将创建一个ActiveX控件,当加载控件时,它会显示一个动画进度条,以便向用户表明控件正在加载.此控件会包

基于swagger的RESTful API开发实践

前言 RESTful架构,是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用.后端通过提供一套标准的RESTful API,让网站,移动端和第三方系统都可以基于API进行数据交互和对接,极大的提高系统的开发效率,也使得前后端分离架构成为可能. 因此,不同的测试,开发团队(前端,移动端,第三方接入者等)都需要围绕API进行开发工作,API的规范和文档对于团队开发,测试变得越来越重要.除了一份标准的文档,我们还希望API能够在线测试使用,从而有更

手机网络应用客户端软件开发实践简介

网络应用与客户端软件 说到移动网络应用,前几年大家首先想到的就是WAP应用.最近随着市场上手机的可编程能力越来越强,手机软件开发平台和产业链的逐渐成熟,手机上的网络应用软件逐渐多了起来,如移动QQ.PICA.掌讯通等等.这些客户端软件凭着丰富的应用.以用户为中心的体验.良好的业务感知度逐渐成为WAP业务之后的又一类重要网络应用.目前的移动软件开发已经逐渐从传统的嵌入式开发中相对独立出来, 主要指手机上的上层应用软件开发,最近也成为了软件行业的新兴热点. 作为业务运营的手机网络应用客户端软件要求能

DBGRIDEH 组件在Borland开发工具中应用全攻略

DBGRIDEH 是Enlib 3.0组件包中的组件之一.Enlib 3.0组件包是一位俄国人为增强Borland系列开发工具功能而开发的第三方组件,它具有界面友好.功能强大.开发效率高..快速制作预   览/打印简单中国式报表等特点.因此,一推出即受到广大Borland程序员的青睐.目前这个版本支持Borland Delphi versions 4,5,6&7 和 Borland C++ Builder versions 4 & 5 ,可极大地提高数据库应用系统客户端的性能.许多商品软件