ASP.NET控件开发学习笔记第4回 为控件添加属性

 

4 为控件添加属性

上一回中我们制作了一个稍微复杂一些的控件,但这个控件存在着很多毛病,第一是导航条的标题栏名称被写死为“我的导航控件”,如果想把它改为其他的名称如“我的链接”就无能为力了。另外它完全依赖于xml文件“linksList.xml”,如果给xml文件改个名字就玩完了。有什么办法可以解决呢?当然是添加属性了,属性大家都很熟了,Visual Studio里专门有一个属性窗口来对属性进行设置。好,说做就做,首先打开控件源文件“linksList.cs”并在其中修改代码如下:

4-1代码1linksList.cs代码


using System;
using System.Web.UI;
using System.Data;
using System.Data.OleDb;
[assembly:TagPrefix(
"MyControl""CG")]
namespace MyControl
{
    
public class LinksControl:Control
    {   
//这里添加了两个用于属性的私有成员变量
        private string _titleText="";
        
private string _xmlFileName="";
        
//下面添加了两个属性
        public virtual string TitleText
        {
            
get { return _titleText; }
            
set { _titleText=value; }
        }
        
public virtual string XmlFileName
        {
            
get { return _xmlFileName; }
            
set { _xmlFileName=value; }
        }
        
protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteLine(
"<ul>");
            
//这里先判断标题名称是否为空然后考虑是否添加标题
            if (_titleText!= "")
            {
                writer.WriteLine(
"<li id='caption'>"+_titleText+"</li>");
            }
            
string s;
            
//判断xml文件是否存在
            if (_xmlFileName!= "")
            {
                DataSet ds
=new DataSet();
                ds.ReadXml(Page.Server.MapPath(_xmlFileName));
                
foreach(DataRow row in ds.Tables["link"].Rows)
                {
                    s
="<li><a href='";
                    s
+=row["url"].ToString();
                    s
+="'target='_blank'>";
                    s
+=row["name"].ToString();
                    s
+="</a></li>";
                    writer.WriteLine(s);
                }
            }
            writer.WriteLine(
"</ul>");
        }
    }
}

 

关于属性,如果有不明白的地方请参考:http://www.enet.com.cn/eschool/video/c/18.shtml 。这里需要注意的是,属性使用了virtual关键字,使这个属性变是虚拟属性,这样做可以使继承你的控件来写新控件的人可以重写这个属性。然后使用属性所指向的成员变量来代替代码中的硬编码部分:

writer.WriteLine("<li id='caption'>"+_titleText+"</li>");

ds.ReadXml(Page.Server.MapPath(_xmlFileName));

当然,新程序对两个属性值如果为空做了处理,但还没处理干净,比如xml文件的后缀名不对或文件不存在等等没有做进一步判断。为了简化代码,这些先暂不考虑。

下面更改aspx文件以使用新添加的属性,打开linkslist.aspx文件,更改代码如下:

4-1代码2linkslist.aspx代码

<%@Register TagPrefix="CG" Namespace="MyControl" %>
<html>
    
<head>
        
<title>Chapter 5: Background Images</title>
        
<link rel='Stylesheet' media="screen" type='text/css' href='linkslist.css' />
    
</head>
    
<body>
    
<CG:LinksControl TitleText="我的链接" XmlFileName="linksList.xml" runat="server" />
    
</body>
</html>
 

这里我们在声明控件时加上了(TitleText="我的链接" XmlFileName="linksList.xml")来设置控件的属性。保存并在浏览器中运行linkslist.aspx文件,看看是否和以前效果一样。为了验证属性的作用,更改TitleText属性看看会有什么效果。再更改xml文件的名称,然后相应地更改XmlFileName属性,看看能否运行成功?

好,现在这个控件貌似已经很不错,但你想在Visual Studio的属性窗口里直接设置属性,现在把控件装到Visual Studio里会在属性窗口里显示这两个新添加的属性吗?当然不行,不过要实现它很简单,只需添加一些特性就行了。打开控件源文件linksList.cs,更改代码如下:

4-2代码1linksList.cs代码

using System;
using System.Web;
using System.Web.UI;
using System.Data;
using System.Data.OleDb;
using System.ComponentModel;
[assembly:TagPrefix(
"MyControl""CG")]
namespace MyControl
{
    [DefaultPropertyAttribute(
"TitleText")]
    [ToolboxData(
"<{0}:LinksControl "+
                 
"TitleText='我的链接' "+ 
                 
"XmlFileName='linksList.xml' "+
                 
"runat='server'></{0}:LinksControl>")]
    
public class LinksControl:Control
    {   
//这里添加了两个用于属性的私有成员变量
        private string _titleText="我的链接";
        
private string _xmlFileName="";
        
//下面添加了两个属性
        [BrowsableAttribute(true)]
        [DescriptionAttribute(
"设置标题栏的名称")]
        [DefaultValueAttribute(
"我的链接")]
        [CategoryAttribute(
"外观")]
        
public virtual string TitleText
        {
            
get { return _titleText; }
            
set { _titleText=value; }
        }
        [BrowsableAttribute(
true)]
        [DescriptionAttribute(
"存放链接的xml文件名")]
        [DefaultValueAttribute(
"")]
        [CategoryAttribute(
"数据")]
        
public virtual string XmlFileName
        {
            
get { return _xmlFileName; }
            
set { _xmlFileName=value; }
        }
        
protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteLine(
"<ul>");
            
//这里先判断标题名称是否为空然后考虑是否添加标题
            if (_titleText!="")
            {
                writer.WriteLine(
"<li id='caption'>"+_titleText+"</li>");
            }
            
string s;
            
//判断xml文件是否存在
            if (_xmlFileName!="")
            {
                DataSet ds
=new DataSet();
                ds.ReadXml(Page.Server.MapPath(_xmlFileName));
                
foreach(DataRow row in ds.Tables["link"].Rows)
                {
                    s
="<li><a href='";
                    s
+=row["url"].ToString();
                    s
+="'target='_blank'>";
                    s
+=row["name"].ToString();
                    s
+="</a></li>";
                    writer.WriteLine(s);
                }
            }
            writer.WriteLine(
"</ul>");
        }
    }
}
 

然后保存文件,并把文件剪切到虚拟目录下,然后新建一CompilelinksList.bat文件,用记事本打开,输入代码如下:

4-2代码2CompilelinksList.bat代码

set indir=H:\ASP\linksList.cs
set outdir
=H:\ASP\bin\linksList.dll
csc 
/t:library /out:%outdir% %indir%
pause
 

记住,indiroutdir这两个路径根据你自己的实际情况进行更改。在虚拟目录下新建一bin文件夹,双击CompilelinksList.bat文件编译程序集。然后查看bin文件夹下是否生成linksList.dll文件,如果成功,接着下面步骤。

打开Visual Studio,新建一个ASP.NET Web应用程序,在工具箱内把以前我们加上去的控件删掉(在控件上点右键删除),再把我们新做的控件加上去。加完后把它拖到设计窗体,看到了什么?晕了吧,出错!如图4-1所示:


 

不要慌张,这只是设计期的错误,无关大局。怎么样在设计期访问xml及显示正确的东西我现在还没搞清楚,学到后面应该就知道了吧!哪位大侠知道的话麻烦告诉我一声,哈哈!好,继续工作。在【解决方案资源管理器】中右键选中项目,选中【添加】|【现有项】把linkslist.csslinksList.xml这两个文件加进来,然后拖动linkslist.css文件到设计窗体。好运行程序看看效果如何!是不是和前面的一样?好,下面就来讲解代码。

代码所更改的地方是增加了一些特性,所以需要引入如下命名空间:

using System.ComponentModel;

先来看第一个增加的特性:

[DefaultPropertyAttribute("TitleText")]

从名字就可以猜出它的作用,“默认属性”,也就是说,用它来指定在属性窗口中默认高亮显示的属性是哪个。再看下一个:

[ToolboxData("<{0}:LinksControl "+

                    "TitleText='我的链接' "+

                    "XmlFileName='linksList.xml' "+

                    "runat='server'></{0}:LinksControl>")]

这个也很好理解,如果刚才做的例子没有关的话,看看源代码,注意控件声明的地方:

    <CG:LinksControl ID="LinksControl1" runat="server" TitleText="我的链接"

        XmlFileName="linksList.xml">

    </CG:LinksControl>

跟上面对比一下,很相似吧!只是{0}这个参数被CG所替代。这个特性的作用就是当拖动控件到设计窗体时,定制声明这个控件的代码。

[BrowsableAttribute(true)]

指定一个属性 (Property) 或事件是否应显示在“属性”窗口中。它在哪个属性前面使用就指的是这个属性。

[DescriptionAttribute("设置标题栏的名称")]

属性的描述,当一个属性处于选中状态时,属性窗口最下方会显示有关这个属性的描述,这个特性就是设置这个描述信息的。

[DefaultValueAttribute("")]

属性的默认值,也就是第一次拖动控件到设计窗体时,属性窗口中这个属性所显示的值是什么。

[CategoryAttribute("外观")]

当属性窗口分类显示时,里面有好几个栏,你希望把这个属性放到哪个栏里呢?想放哪就放哪,设置这个特性值就OK了。

好,喝茶时间到,还有什么问题下一回再解决。


原文地址:https://www.cnblogs.com/abatei/p/1082955.html