复合控件与事件(1)——基础入门,组合也是一种封装

关于复合控件的文章在网上已经很多了,本文只是最近自己做复合控件的一些心得体会。希望大家愿意和我分享。

复合控件作为组件二次开发一个很好的方式被很多人所喜欢,理由就是它在复用性和实用性两方面做到了很好的权衡。如果你的项目对某一组控件的组合依赖比较多,而这些组合之间的关系基本上也是很稳定的话,再者你对它们会大量使用到的话,那么你可以考虑将它们做成复合控件进行引用。
复合控件不是用户控件ascx,许多用户都做过ascx但是并没有做过复合控件。其实它们的区别也不是很大,表现形式基本上也是一样的,区别就在于用户控件的制作过程和制作页面是无异的,而复合控件的制作则相对更“专业”一点,复合控件以DLL的形式被提供,可以被复用于多个项目,而用户控件则仅限于当前项目中。这些很“酷”的因素也足以让你愿意尝试你的第一个复合控件了。
最简单的复合控件(为了从基础开始有个全面的认识,我用最最简单的例子去开篇,让你对复合控件有个更抽象的认识,从宏观角度更好地把握制作过程)
根据大家对用户控件的认识想必很容易做出同样类型的复合控件,只要它能够以复合控件的形式提供,它事实上已经是一个复合控件,至于好不好用,那就要看你设计的功力了。
在用户控件中,大家通过添加各种控件,然后对它们进行调用,我们用FindControl去寻找它们,理由是因为它们被添加进用户控件ascx文件的时候是protected的,而被调用的时候,用户控件是protected的,而其子控件就相应地变成private的了,因此我们无法轻松的利用点运算符去获取它们,因此我们采用FindControl去Find它们。找到之后它们就可以被你轻松使用了。事实上你最需要的是它们布局上的相对稳定以及一些内部逻辑,而从外部看,控件则是一个整体。在复合控件中,我们也可以这么做,但是我们甚至可以做得更简单,因为它的访问权限受我们支配,我们可以通过public去设置它们,这样用户程序就可以无限制访问了,也就不需要FindControl了,当然你还可以通过get访问器去访问,这样你同样可以获得你子控件对象的实例。你可以像下面这样定义你的子控件,这样你就可以在外部对它们进行访问了。

None.gif          // Method1
None.gif
         private  DropDownList ddl1  =   new  DropDownList();
None.gif        
public  DropDownList DDL1
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this.ddl1;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.ddl1 = value;
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

None.gif        
// Method2
None.gif
         public  DropDownList ddl2  =   new  DropDownList();

调用的代码可以是:
None.gif // 这里以DataSource进行举例,这样的例子同样适用于事件、方法等
None.gif
             this .CompositeControl1_1.DDL1.DataSource  =  GetDDLData();
None.gif            
this .CompositeControl1_1.ddl2.DataSource  =  GetDDLData();

以上这些其实就是一个类中包含有另一个类的一个对象,现在如何让调用这个类的客户程序去使用这个涵盖的对象的问题。
复合控件是一个特殊的类,因为你希望别人知道你所做的是一个控件而不是一个普通的类。.net框架提供了一个CompositeControl抽象类供我们继承,相比自己做控件的用户而言,做复合控件的用户已经清闲了许多了,直接从这个类继承就可以达到目的了。
None.gif public   abstract   class  CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor
None.gif
// ICompositeControlDesignerAccessor:提供一个接口以使复合控件设计器可以在设计时重新创建其关联控件的子控件。
当然了,你如果要直接从WebControl继承也不是不可以,其实效果都是一样的,如果你要再从Control来继承也是可以的。这里我们只需要以下形式就可以了
None.gif public   class  CompositeControl1 :CompositeControl
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*dot.gifdot.gifdot.gif..*/
ExpandedBlockEnd.gif}
以上所写的声明控件的那部分代码,显而易见就是在上面这个类的内部实现的了。如何才能让我们的控件能够显示到客户程序呢?CompositeControl从Control间接继承的方法CreateChildControls()告诉我们要将所有子控件添加到当前这些直接或间接派生自Control类的类的一个名为Controls的属性中,这个Controls在CompositeControl已经被重写过了,MSDN定义如下:
ExpandedBlockStart.gif ContractedBlock.gif public   override  ControlCollection Controls  dot.gif get; }
ExpandedBlockStart.gifContractedBlock.gif
/**/ /*Controls 属性重写基实现,以确保在返回 ControlCollection 对象之前所有子控件均已创建。
InBlock.gif
InBlock.gif通过 Controls 属性,可以采用编程方式访问 CompositeControl 的 ControlCollection。您可以在集合中添加控件,也可以从中移除控件,并且可以循环访问集合中的控件。
ExpandedBlockEnd.gif
*/
实现代码也很简单,就是this.Controls.Add(****);//****表示你的子控件对象,比如这里的ddl1,ddl2有几个就加几个。
其实以上这些你就已经构建出了一个最简单的复合控件,虽然你要的可能不是这样,但它们其实就是复合控件最基础的东西。另外在整个类的头上加上一些Attribute,可以让引用你复合控件.dll文件的人更轻松地使用它们
None.gif     [ToolboxData( " <{0}:CompositeControl1 runat=\ " server\ "  /> " )]
None.gif    
public   class  CompositeControl1 :CompositeControl
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*dot.gifdot.gif.*/
ExpandedBlockEnd.gif}

顶上的ToolboxData告诉我们,当我们像从工具箱拖动它到页面的时候,默认添加的就是它括号内的那些信息,正如我们总是在包含Button按钮的源代码中可以找到<asp: Button1 runat="server" id="Button1"……></asp:Button1>一样的道理。
CreateChildControls()是什么呢?故名也能思意,创建该 控件的子控件。 CreateChildControls 方法用于在关联控件中重新创建子控件。它确保在创建设计时标记之前已创建控件集合。说白了,我们之前所做的工作没有这个方法,那么它们只是类实例的一个成员而已,并没有融入这个Controls的大家庭供外部统一协调地访问,这个方法正要让这些子控件被创建起来。通常的做法就是在里面去实现子控件的创建工作。当然了,如果你不愿意,你也可以用下面这样的代码去实现同样的功能,控件同样会被呈现出来,并且也能工作的很OK,
None.gif          public  CompositeControl1()
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
this.Controls.Add(ddl1);
InBlock.gif            
this.Controls.Add(ddl2);
ExpandedBlockEnd.gif        }

但是有的方法可能就无法很好地利用了比如EnsureControlCreated()等。

另外你可以在MSDN找到更多的方法,重写它们你可能会得到更多的惊喜,或者选择等待,也许我也能给你带来惊喜。

CompositeControl1.cs
ContractedBlock.gif ExpandedBlockStart.gif
None.gifusing System;
None.gif
using System.Web.UI;
None.gif
using System.Web.UI.WebControls;
None.gif
using System.ComponentModel;
None.gif
None.gif
namespace ComponentWebControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
//添加元数据可以使其显示在工具箱中
InBlock.gif    
//public abstract class CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor
InBlock.gif    
//ICompositeControlDesignerAccessor:提供一个接口以使复合控件设计器可以在设计时重新创建其关联控件的子控件。
InBlock.gif
    [ToolboxData("<{0}:CompositeControl1 runat=\"server\" />")]
InBlock.gif    
public class CompositeControl1 :CompositeControl
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//*************************************************************************
InBlock.gif         * 声明你需要囊括的子控件,你不一定要使用"private",你可以将它们定义成
InBlock.gif         * "public"或者"protected",如果你将它们定义成"public"或者"protected",
InBlock.gif         * 那么你控件的客户程序将可以直接获得你的子控件实例。如果你定义成"private"
InBlock.gif         * 和往常一样,你的子控件在客户程序中是不可访问的。但是你仍然可以通过定义
InBlock.gif         * 一个属性,将子控件的实例通过get访问器返回给你的客户程序,并且你可以同样
InBlock.gif         * 去设置你的子控件。
InBlock.gif         * 这个过程看上去其实只是一个类的组合关系的一个简单调用。事实上整个复合控件
InBlock.gif         * 就是如此构建的。
ExpandedSubBlockEnd.gif         * **********************************************************************
*/

InBlock.gif        
//Method1
InBlock.gif
        private DropDownList ddl1 = new DropDownList();
InBlock.gif        
public DropDownList DDL1
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return this.ddl1;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.ddl1 = value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
//Method2
InBlock.gif
        public DropDownList ddl2 = new DropDownList();
InBlock.gif
InBlock.gif        
//public CompositeControl1()
InBlock.gif        
//{
InBlock.gif        
//    this.Controls.Add(ddl1);
InBlock.gif        
//    this.Controls.Add(ddl2);
InBlock.gif        
//}
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 由 ASP.NET 页面框架调用,以通知使用基于合成的实现的服务器控件
InBlock.gif        
/// 创建它们包含的任何子控件,以便为回发或呈现做准备。 
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        protected override void CreateChildControls()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//从当前服务器控件的 ControlCollection 对象中移除所有控件。 
InBlock.gif
            Controls.Clear();
InBlock.gif            CreateControlHierarchy();
InBlock.gif            
//删除服务器控件的所有子控件的视图状态信息。 
InBlock.gif
            ClearChildViewState();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 创建并添加子控件
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        protected virtual void CreateControlHierarchy()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//1.写一些关于控件添加或者与控件有关属性预设值的代码
ExpandedSubBlockStart.gifContractedSubBlock.gif
            /**//*dot.gifdot.gifdot.gifdot.gif*/
InBlock.gif
InBlock.gif            
//2.将控件添加进当前正在设计的控件
InBlock.gif
            this.Controls.Add(ddl1);
InBlock.gif            
this.Controls.Add(ddl2);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
CompositeControl1.aspx
ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif<%dot.gif@ Page Language="C#" AutoEventWireup="true" CodeBehind="CompositeControl1.aspx.cs" Inherits="WebAppTestControls._Default" %>
None.gif
ExpandedBlockStart.gifContractedBlock.gif
<%dot.gif@ Register Assembly="ComponentWebControls" Namespace="ComponentWebControls" TagPrefix="cc1" %>
None.gif
None.gif
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
None.gif
None.gif
<html xmlns="http://www.w3.org/1999/xhtml" >
None.gif
<head runat="server">
None.gif    
<title>CompositeControl1</title>
None.gif
</head>
None.gif
<body>
None.gif    
<form id="form1" runat="server">
None.gif    
<div>
None.gif        
<cc1:CompositeControl1 ID="CompositeControl1_1" runat="server" />
None.gif    
</div>
None.gif    
</form>
None.gif
</body>
None.gif
</html>
None.gif
CompositeControl1.aspx.cs
ContractedBlock.gif ExpandedBlockStart.gif
None.gifusing System;
None.gif
using System.Data;
None.gif
using System.Configuration;
None.gif
using System.Collections;
None.gif
using System.Collections.Generic;
None.gif
using System.Web;
None.gif
using System.Web.Security;
None.gif
using System.Web.UI;
None.gif
using System.Web.UI.WebControls;
None.gif
using System.Web.UI.WebControls.WebParts;
None.gif
using System.Web.UI.HtmlControls;
None.gif
using ComponentWebControls;
None.gif
None.gif
namespace WebAppTestControls
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public partial class _Default : System.Web.UI.Page
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
protected void Page_Load(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.CompositeControl1_1.DDL1.DataSource = GetDDLData();
InBlock.gif            
this.CompositeControl1_1.ddl2.DataSource = GetDDLData();
InBlock.gif            
this.CompositeControl1_1.DataBind();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public IList<string> GetDDLData()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            IList
<string> dataSource = new List<string>();
InBlock.gif            dataSource.Add(
"AAA");
InBlock.gif            dataSource.Add(
"BBB");
InBlock.gif            dataSource.Add(
"CCC");
InBlock.gif            dataSource.Add(
"DDD");
InBlock.gif            
return dataSource;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
CompositeControl1.aspx.designer.cs
ContractedBlock.gif ExpandedBlockStart.gif
None.gif//------------------------------------------------------------------------------
None.gif
// <auto-generated>
None.gif
//     此代码由工具生成。
None.gif
//     运行库版本:2.0.50727.1318
None.gif
//
None.gif
//     对此文件的更改可能会导致不正确的行为,并且如果
None.gif
//     重新生成代码,这些更改将会丢失。
None.gif
// </auto-generated>
None.gif
//------------------------------------------------------------------------------
None.gif

ExpandedBlockStart.gifContractedBlock.gif
namespace WebAppTestControls dot.gif{
InBlock.gif    
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// _Default 类。
InBlock.gif    
/// </summary>
InBlock.gif    
/// <remarks>
InBlock.gif    
/// 自动生成的类。
ExpandedSubBlockEnd.gif    
/// </remarks>

ExpandedSubBlockStart.gifContractedSubBlock.gif    public partial class _Default dot.gif{
InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// form1 控件。
InBlock.gif        
/// </summary>
InBlock.gif        
/// <remarks>
InBlock.gif        
/// 自动生成的字段。
InBlock.gif        
/// 要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
ExpandedSubBlockEnd.gif        
/// </remarks>

InBlock.gif        protected global::System.Web.UI.HtmlControls.HtmlForm form1;
InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// CompositeControl1_1 控件。
InBlock.gif        
/// </summary>
InBlock.gif        
/// <remarks>
InBlock.gif        
/// 自动生成的字段。
InBlock.gif        
/// 要进行修改,请将字段声明从设计器文件移到代码隐藏文件。
ExpandedSubBlockEnd.gif        
/// </remarks>

InBlock.gif        protected global::ComponentWebControls.CompositeControl1 CompositeControl1_1;
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


下一篇: 复合控件和事件(2)——属性,页面要回发,属性要保存

转载于:https://www.cnblogs.com/volnet/archive/2007/07/02/802491.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值