玩转C科技.NET

从学会做人开始认识这个世界!http://volnet.github.io

导航

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

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

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

        //Method1
        private DropDownList ddl1 = new DropDownList();
        
public DropDownList DDL1
        
{
            
get
            
{
                
return this.ddl1;
            }

            
set
            
{
                
this.ddl1 = value;
            }

        }

        
//Method2
        public DropDownList ddl2 = new DropDownList();

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

以上这些其实就是一个类中包含有另一个类的一个对象,现在如何让调用这个类的客户程序去使用这个涵盖的对象的问题。
复合控件是一个特殊的类,因为你希望别人知道你所做的是一个控件而不是一个普通的类。.net框架提供了一个CompositeControl抽象类供我们继承,相比自己做控件的用户而言,做复合控件的用户已经清闲了许多了,直接从这个类继承就可以达到目的了。
public abstract class CompositeControl : WebControl, INamingContainer, ICompositeControlDesignerAccessor
//ICompositeControlDesignerAccessor:提供一个接口以使复合控件设计器可以在设计时重新创建其关联控件的子控件。
当然了,你如果要直接从WebControl继承也不是不可以,其实效果都是一样的,如果你要再从Control来继承也是可以的。这里我们只需要以下形式就可以了
public class CompositeControl1 :CompositeControl
    
{
/*..*/
}
以上所写的声明控件的那部分代码,显而易见就是在上面这个类的内部实现的了。如何才能让我们的控件能够显示到客户程序呢?CompositeControl从Control间接继承的方法CreateChildControls()告诉我们要将所有子控件添加到当前这些直接或间接派生自Control类的类的一个名为Controls的属性中,这个Controls在CompositeControl已经被重写过了,MSDN定义如下:
public override ControlCollection Controls get; }
/*Controls 属性重写基实现,以确保在返回 ControlCollection 对象之前所有子控件均已创建。

通过 Controls 属性,可以采用编程方式访问 CompositeControl 的 ControlCollection。您可以在集合中添加控件,也可以从中移除控件,并且可以循环访问集合中的控件。
*/
实现代码也很简单,就是this.Controls.Add(****);//****表示你的子控件对象,比如这里的ddl1,ddl2有几个就加几个。
其实以上这些你就已经构建出了一个最简单的复合控件,虽然你要的可能不是这样,但它们其实就是复合控件最基础的东西。另外在整个类的头上加上一些Attribute,可以让引用你复合控件.dll文件的人更轻松地使用它们
    [ToolboxData("<{0}:CompositeControl1 runat=\"server\" />")]
    
public class CompositeControl1 :CompositeControl
    
{
/*.*/
}

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

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

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

CompositeControl1.cs
CompositeControl1.aspx
CompositeControl1.aspx.cs
CompositeControl1.aspx.designer.cs


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

posted on 2007-07-02 03:00  volnet(可以叫我大V)  阅读(3116)  评论(2编辑  收藏  举报

使用Live Messenger联系我
关闭