ASP.NET中的用户定制控件(2)

创造的魅力——ASP.NET中的用户定制控件(2)
原创:冯涛 牛建新 2004年5月18日

创造的魅力——定制控件

从上面对用户控件的总体介绍中我们可以看出,用户控件只是实现了对已有控件的组合,从而形成新的控件。喜欢创新的你又怎肯止步于此呢,当然,ASP.NET也不会止步于此。如果你需要一个全新的完全符合你的意愿的控件,那么你应该选择定制控件!

由此我们又要引出一个老套的话题,什么是定制控件呢?

定制控件的范围要比用户控件宽泛得多。首先,定制控件也就是CustomControl,主要可以分为三类:

继承自System.Web.UI.WebControls,这样创建的是一个全定制控件(full custom control);
继承自现有控件,可以对现有控件的功能进行扩充,创建一个派生的定制控件(derived custom control);
最后也可以像用户控件一样,把几个现有的控件组合在一起,创建一个合成定制控件(composite custom control),但与用户控件相比需要使用更有逻辑的结构。

其实,定制控件的特点是其自身包含在C#程序集(程序集的好处相信大家已经相当熟悉了,这是.NET的优势之一)中,不需要单独的ASP.NET代码,但却完全可以控制输出的内容,即控件生成的HTML。一般说来,开发定制控件要难于开发用户控件,不但语法要复杂一些,而且还要编写更多的代码才能得到结果。这些也算是创新所要付出的代价吧。

为了说明定制控件的特性,我们用表格的方式对用户控件和定制控件做一个比较:

  定制控件 用户控件
组成元素 多个定制控件放在一个C#程序集中 一个用户控件是由一个.ascx文件和一个.cs后台代码文件组成
创建方式 在项目中添加一个控件库,添加C#代码,然后编译为C#程序集 在项目中添加用户控件,在.ascx文件中添加ASP.NET代码,在.cs后台代码文件中添加C#代码
引用方式 注册:<%@ Register TagPrefix="..." Namespace="..." Assembly="..."%>

引用:<TagPrefix:类名 ...

注册:<%@ Register TagPrefix="..." TagName="..." Src="..."%>

引用:<TagPrefix:TagName ...

创建的难易程度 复杂 简单
复用程度 复用性非常强,可以近似看成是一个类库。 不如定制控件强

从上面的表格中我们可以看出,定制控件与用户控件的区别还是比较大的,下面我们分别讨论一下:

C#程序集中可以存放多个定制控件,并且可以通过命名空间和类名唯一确定一个控件;
C#程序集可以应用.NET系统固有的程序集动态查询,只要把程序集放在Web应用程序能够找到的地方(Web应用程序的bin目录下或者是全局程序集高速缓存[GAC]中),并进行注册即可使用;
定制控件的每个方面都可以随意定制。但最好只为需要的功能编写代码,因为控件设计得越简单创建就越容易;
定制控件使用方便,一但编译为程序集,我们甚至可以将它放到Visual Studio.NET的Toolbox中。

下面就让我们开始一起来讨论如何创建和使用定制控件。

定制控件的应用

首先我们在Visual Studio.NET中创建一个类型为Web Control Library的新项目,并且命名为"WebControls"如图所示:

我们为了简化测试,需要给同一Solution添加一个Web应用程序项目,并且命名为"WebControlsTestApp"。那么我们如果想在这个项目中使用上面创建的定制控件,就需要把控件库编译好的程序集copy到WebControlsTestApp中的bin目录下,并且添加引用,再进行注册。而其实还有更简单的方法,我们可以将控件库项目编译好的程序集直接输出到WebControlsTestApp中的bin目录下。想做到这点很简单,只需修改WebControls的属性页即可。在Solution Explorer中右击WebControls项目,在菜单中选择Properties。弹出如下对话框:

先将左上方的Configuration下拉菜单改为All Configuration,然后在左边列表框中选择Build,将右边的Output Path更改为WebControlsTestApp中的bin目录。再在左边列表框中选择Debugging,将右边的Debug Mode更改为URL;Start URL更改为http://localhost/WebControlsTestApp/WebForm1.aspx。

这样设置完成后,我们就可以方便地测试写好的定制控件了。下面我们来仔细看看上面创建的控件库。Visual Studio.NET在其中为我们默认创建了一个定制控件"WebCustomControl1"。我们来看一下它的内容(删去了XML文档注释):

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace WebControls
{
    [DefaultProperty("Text"),
    ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
    public class WebCustomControl1 : System.Web.UI.WebControls.WebControl
    {
        private string text;

        [Bindable(true),
        Category("Appearance"),
        DefaultValue("")]
        public string Text
        { 
            get
            {
                return text;
            }

            set
            {
                text = value;
            }
        }

        protected override void Render(HtmlTextWriter output)
        {
            output.Write(Text);
        }
    }
}

我们来看这段代码,首先是命名空间的引入,然后声明了一个继承自System.Web.UI.WebControls.WebControl的类。这个类的前面有两个属性:DefaultProperty和ToolboxData。DefaultProperty属性是指定控件的默认特性。ToolboxData属性指定在使用Visual Studio.NET的Toolbox添加控件的条件下,为.aspx页面添加什么样的内容,其中的{0}占位符用于指定标记前缀的位置。

这个类包含一个属性:Text。

在其前面也包含三个属性:

Bindable 属性可否与数据绑定
Category 在属性页面上显示特性
DefaultValue 属性的默认值

剩下的就是一个Render方法,这个方法在设计定制控件时很重要,它访问输出流并控制控件显示内容。但也有不包含Render方法的情况。这样的控件要不就是没有可视化表示(通常称为组件),要不就是继承自其他控件并且不需要改变原有控件的显示特性。

然后我们将其编译,然后可以在Toolbox上右击,在弹出菜单中选择Add/Remove Items,在弹出的对话框中浏览到编译好的程序集,添加它,就可以把这个控件库中的定制控件全部添加到Toolbox中。这样就可以像使用已有控件一样使用自己制作的定制控件了。

添加后,我们将它拖到.aspx页面的design界面中。不难发现,这是一个标准的<asp:Label>控件。

那么现在就让我们对此控件进行一些有趣的改动。我们并不做太多改动,代码如下:

首先,我们在标准的命名空间下面添加一个using System.Drawing;命名空间引用,我们引入这个命名空间是为了可以取得一些颜色的值。然后我们再将Render方法改写如下:

protected override void Render(HtmlTextWriter output)
{
    int[] rgb = {Color.Red.ToArgb() & 0xFFFFFF,
                 Color.Blue.ToArgb() & 0xFFFFFF,
                 Color.Green.ToArgb() & 0xFFFFFF};

    for (int pos=0; pos<text.Length; pos++)
    {
        output.Write("<font color='#"+rgb[pos%3].ToString("X6")+"'>"+Text[pos]+"</font>");
    }
}

我们在原有基础上添加了一些代码。如果你急着看效果那就按下Ctrl+Shift+B编译,然后给控件的Text属性赋上"ASP.NET的定制控件",再按F5运行一下,如图:

怎么样?还是挺有意思的吧。在这里我们只是添加了一个变色的功能,实现也非常简单,只是用一个数组去循环。但却也体现了一些定制控件的特性。你也可以马上再去扩充一下现有的功能,充分发挥你的想象力,因为ASP.NET的服务器控件的每一个方面都可以随你定制。它的功能之强,以至于要把它介绍明白写一本书也不为过。但是我们的水平有限,写书还是不想了。其实我们也只是想通过这篇文章,给大家添个思路,如果想深入研究请参照相关书籍。

总结

本文着重介绍了.NET中代码复用的相关内容,主要是用户控件和定制控件两部分,我们在这里通过一些实例介绍了他们的用法以及特性。而对于定制控件与传统ASP和com组件的比较,超出了本文讨论的范围,所以没有涉及(传统脚本对于已有对象的支持不足,所以效率和维护方面都不太好,至少在这点上C#的程序集是可以轻松超越的)。

最后让我们再来总结一下:

首先,我们介绍了创建简单的用户控件。它的优点就是可以最方便地实现代码的复用。
随后,我们介绍的比用户控件又进一步的定制控件,我们应用它可以定制ASP.NET服务器控件的任何方面。但创建它势必要更费功夫。
那么我们到底应该什么时候使用哪种控件呢?有的书上说像banner那样的元素,应该使用用户控件,而内部逻辑比较多的就应该使用定制控件。其实我觉得没有什么定则,完全要根据具体情况来分析决定。

此文是由我们两人合写的,由于首次合作写文章,所以不免有不足之处,还请各位读者多多包涵。

参考文献

[1] C#高级编程——第二版
[2] ASP.NET高级编程
[3] ASP.NET开发新思维
[4] ASP.NET服务器控件与组件编程
posted @ 2004-08-11 11:49  泡面 @ 幸福  阅读(565)  评论(0编辑  收藏  举报