一起谈.NET技术,asp.net控件开发基础(9)

  写第五篇的时候,我一步步的加上元数据(特性),使得设计时效果更加好,如对复杂属性应用以下特性,使属性浏览器支持扩展/折叠效果,使你更加容易编辑子属性,但接着我又遇到了问题,所以必须去解决

  1.认识默认属性浏览器支持

  让我们再认识一下属性,大家知道每个属性都是有类型的,最熟悉就是string,int这些类型了,vs2005属性浏览器对这些属性类型进行了识别, 如下例子

  (1)table控件的Height属性,当你设置属性为字符串时,则提示错误信息

  (2)当属性类型为Color属性时,属性浏览器为你提供颜色选择器

  (3)当属性类型为枚举类型时,属性浏览器则支持下拉框选择
  (4)当类型是时间类型,属性浏览器则支持时间选择器

  通过上面,我们认识到属性浏览器默认会判别属性类型,当属性值跟属性类型不符时,则会提示错误信息.这里我们还认识到属性浏览器默认为一些属性类型提供了便利
  2.属性表现形式的多样性

  在定义控件属性时,可以直接这样定义,属性都为字符串形式

<asp:TextBox ID="TextBox1" runat="server" 
        Height="11" BackColor="Blue" 
        ForeColor="#FF8000">测试</asp:TextBox>

  用代码表示则是这样,在后台代码中定义的属性类型必须相对应,BackColor必须为Color类型,否则则会出错,当在页面呈现时,则以字符串形式呈现. 

protected void Page_Load(object sender, EventArgs e)
    {
        //TextBox1.BackColor = "blue";
        TextBox1.BackColor = System.Drawing.Color.Red;
        TextBox1.BackColor = System.Drawing.Color.FromName("blue");
    }


通过上面,我们认识到属性类型需要转换,这里便要引出我们所要讲的话题,类型转换器,例如,当BackColor="Blue" 时,则会激活一个类型转换器实例将字符串值转换成声明的类型(即将"blue"转换成Color类型,然后赋给BackColor..net类库中的基本类型和许多类型都有与其相关联的类型转换器。
  一般常用的类型有String,Int,Boolean,DateTime,Enum等类型,其类型已默认与其相对应的类型转换器关联起来,如Color类默认关联的类型转换器System.Drawing.ColorConverter;FontInto类默认关联的类型转换器System.Drawing.FontConverter类型转换器的基类为System.ComponentModel.TypeConverter,所有的类型转换器都从其派生.。下面我们再来看一个例子,
  我们先定义一个复杂属性,用于测试
  示例一



1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace CustomComponents
6{
7 public class Name
8 {
9 private string firstName;
10 private string lastName;
11 public String FirstName
12 {
13 get
14 {
15 return firstName;
16 }
17 set
18 {
19 firstName = value;
20 }
21 }
22
23 public String LastName
24 {
25 get
26 {
27 return lastName;
28 }
29 set
30 {
31 lastName = value;
32 }
33 }
34 }
35}

再看aspx文件
  其中我们输出了Label的几个属性,包括FontInfo这个复杂属性,并且实例化了上面定义的Name类


1 <%@ Page Language="C#" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<script runat="server">
6
7 void Page_Load(object sender, EventArgs e)
8 {
9 myLabel.Font.Bold = true;
10 myLabel.Font.Italic = false;
11 myLabel.Font.Name = "verdana";
12 myLabel.Font.Overline = false;
13 myLabel.Font.Size = 10;
14 myLabel.Font.Strikeout = false;
15 myLabel.Font.Underline = true;
16
17 Response.Write(myLabel.Font + "<br>");
18 Response.Write(Label1.Width);
19 Response.Write(Label1.BackColor+"<br>");
20 Response.Write(Label1.ForeColor + "<br>");
21
22 CustomComponents.Name n = new CustomComponents.Name();
23 n.FirstName = "张";
24 n.LastName = "三";
25 Response.Write(n);
26 }
27
28</script>
29<html xmlns="http://www.w3.org/1999/xhtml" >
30<head id="Head1" runat="server">
31 <title>FontInfo Example</title>
32</head>
33 <body>
34 <form id="form1" runat="server">
35 <h3>FontInfo Example</h3>
36 <asp:Label id="myLabel"
37 runat="server" >
38 </asp:Label>
39 <br />
40 <br />
41 <asp:Label ID="Label1" Width="200px" runat="server" BackColor="#FF8080" Text="Label" ForeColor="Red"></asp:Label>
42 </form>
43 </body>
44</html>
45
46

  下面看看输出结果,如下图

  结果是将FontInfo属性和Color属性转换成字符串形式呈现,而我们自定义的Name属性只以其类型呈现,并未呈现其子属性值。再来看看第一点默认属性浏览器支持和第五篇我们所定义的一个复杂属性CustomComponents.Address,
CustomComponents.Address属性同样存在着这样的问题,再对比一下FontInfo属性在属性浏览器的支持,如下图 
--------------------------------------------------------------------------
  复杂属性CustomComponents.Address无法编辑,只读,而且显示的是其属性类型。复杂属性Font则默认显示了子其属性的值(其默认只显示Names值和Size值,且为只读)。问题来了,我们要根据需要为自定义属性实现类型转换器.
  3.自定义属性类型转换器

  上面已经说明问题所在了,实现类型转换器,可以将属性类型和字符串类型之间相互转换。下面我们就为解决这个问题而来了解类型转换器,我们还是以第五篇的那个例子来学习。在说第二点属性表现形式的多样性的时候已经说过了类型转换器的基类为System.ComponentModel.TypeConverter,所有的类型转换器都从其派生。下面以第五篇时的例子为基础,我们为Address实现了一个类型转换器,其实现了复杂属性代码的折叠,如下代码

[TypeConverter(typeof(ExpandableObjectConverter))]
    public class Address
    {
}

  System.ComponentModel.ExpandableObjectConverter 类也是从TypeConverter类派生。所以当自定义复杂类型的类型转换器时,则可从ExpandableObjectConverter 类派生。如果你定义的属性不是复杂属性,则可以直接从TypeConverter类派生
  (1) 值翻译的类型转换器

  从TypeConverter类派生的自定义类型转换器则需要重写TypeConverter类几个方法,主要目的就是实现自定义属性类型与字符串值之间的转换。你需要了解以下几个方法,这里我们就以Address属性为例子,这样来解释以下方法更好理解。其实可以理解成一来一去的关系,Form,To,相互之间的转换,如下代码:
  TypeDescriptor类的方法为静态方法,通过GetConverter方法获取类型转换器,然后通过TypeConverter类的ConvertFromString方法和ConvertToString相互转换类型.
  示例二
 


public class AddressConverter : ExpandableObjectConverter
{
方法
}

 

  自定义好类型转换器后,要与属性相关联起来

    [TypeConverter(typeof(AddressConverter))]
    public class Address
    {
        
        public Address()
            :
            this(String.Empty, String.Empty,
            String.Empty, String.Empty)
        { }

        public Address(string street, string city,
            string state, string zip)
        {
            this.street = street;
            this.city = city;
            this.state = state;
            this.zip = zip;
        }
          .......
    }

  下面来看下效果,如下图,属性编辑器显示的CustomAddress不再显示其类型了,已将其转化为字符串形式了,如果你设置CustomAddress可写的话,就可以直接编辑CustomAddress属性,但其只有四个子属性,所以当大于5个时就会出错,且格式也不可以乱改,一般情况下都设置其只读。

  为了在页面上显示这个CustomAddress属性,还需要为Address类重写一下ToString方法,如下代码

 


#region 方法

public override string ToString()
{
return ToString(CultureInfo.CurrentCulture);
}

public virtual string ToString(CultureInfo culture)
{
return TypeDescriptor.GetConverter(typeof(Address)).ConvertToString(null, culture, this);
}

#endregion

 

  通过上面重写ToString方法后,输出的CustomAddress属性将不再是其类型,而是以字符串形式呈现,以下以Response.Write方法输出Custom1.CustomAddress输出,如下图

  上面讲了最基本的值翻译类型转换器,希望对大家有帮助

  (2)向“属性”窗口提供标准值列表的类型转换器

  像省份这样的属性,为了方便用户填写,我们往往做成下拉框形式,一个省份里面又有城市,我们往往列出一部分,如果其中数据不符合用户要求的话,用户还可以自己输入,使用类型转换器转换器也可以做到这一点。实现这一效果你需要重写以下方法,我们添加一个属性喜欢的游戏的名称。因为属性为String类型,可以直接从StringConverter 派生

  示例三

 public class GameConverter : StringConverter 

    {
        //返回此对象是否支持可以从列表中选取的标准值集
        public override bool GetStandardValuesSupported(
                           ITypeDescriptorContext context)
        {
            return true;
        }
       //返回下拉框集合类
       public override StandardValuesCollection
                     GetStandardValues(ITypeDescriptorContext context)
       {
           return new StandardValuesCollection(new string[]{"传奇", 
                                                     "魔兽世界", 
                                                     "龙与地下城"});
       }
       //标准值的集合是否为独占列表
       //默认为flase,为true则表示无法修改列表值
       public override bool GetStandardValuesExclusive(
                           ITypeDescriptorContext context)
       {
           return false;
       }
    }

  然后与相关属性关联起来

[TypeConverter(typeof(GameConverter))]
        [Description("喜欢的游戏")]
        public String Game
        {
            get
            {
                return game;
            }
            set
            {
                game = value;
            }
        }

  好了,.下面我们看一下效果,如下图,你可以选择下拉框的值,也可以自己手动输入,跟枚举类型很相似,但枚举类型无法自己修改值.

上一篇:asp.net控件开发基础(8)

下一篇:asp.net控件开发基础(10)

时间: 2024-10-27 18:39:17

一起谈.NET技术,asp.net控件开发基础(9)的相关文章

一起谈.NET技术,asp.net控件开发基础(15)

继续我们的话题吧.自定义控件.如果你还不熟悉自定义控件开发的话,还请看看我以前写了几篇,希望对你有帮助 1.1何处继承 自定义控件一般从以下几个基类(此处不包含数据控件) 一.Control类(所有服务器控件的基类,算是比较底层的类,如果控件功能比较简单,要求不多,可直接继承此类.) 二.WebControl类(标准控件的基类,继承此类,你可以继承其丰富的公共属性,若标准控件中的控件没有你需要的控件,你可以继承此类) 三.CompositeControl 类(2.0新增的类,此类继承自WebCo

一起谈.NET技术,asp.net控件开发基础(13)

1.减轻服务器压力,增加用户体验 服务器功能是强大的,客户端脚本一点也不弱,现在的ajax技术和Atlas技术就是最好的证明,我们总是期待UI有一个好的效果,flash动画给我们带来了很酷的效果,我们至少也可以为我们的服务器控件添加客户端脚本,一方面减少了服务器端的回传,一方面又能为控件提供非常酷的效果.我想我们都很喜欢ATLAS里面很多很酷的控件吧,而且无刷新,服务器控件与客户端脚本交互使用,那会服务器控件变的更加完美. 经过上面的废话,下面我们进入正题 2.简单为服务器控件添加客户端脚本 我

一起谈.NET技术,asp.net控件开发基础(8)

有一些复合控件直接把按钮触发事件所需的事情封装好,另外一种则是自定义事件,更具灵活性,当然这是根据需要设计的.以下会以例子来说明的.下面我们假设我们控件中有两个按钮.以下不列出所有代码,具体可在文章最后下载代码. (1) 直接实现按钮事件 在控件中(以下代码并非实现复合控件)直接实现事件则无需自定义事件,如下代码(如果对数据回传有些不熟悉的话,可先看第三篇,希望对你有帮助) 示例一(只列出局部代码,具体可在文章最后下载代码) void IPostBackEventHandler.RaisePos

一起谈.NET技术,asp.net控件开发基础(2)

或许大家还对为何要重写Render方法存有疑惑,希望大家看看我举的例子,能够明白Render方法和其他两个方法的作用,然后真正明白为何一般情况下只须重写Render方法.我们知道我们每次编写控件时,都需要重写Render方法,我们发现在Control类中很多方法可以重写,但我们没有去重写他们,我们需要遵循一个原则,在需要重载的时候再去重写他们 我们还是先来看看与Render方法相关的两个方法 //RenderControl方法的基本实现 public void RenderControl(Htm

一起谈.NET技术,asp.net控件开发基础(22)

上两篇讨论了如何定义结合数据源控件的数据绑定控件.这次我们一起来看下数据源控件是如何实现的.asp.net2.0已经为我们提供了很多数据源控件,相信大家都用过了,也希望大家对其有所熟悉.关于它能做什么就不说了.下面我们也一起来看看,如何简单的实现. 一.你必须了解的 1.关于数据源控件(DataSourceControl) 虽然表面看来,给数据绑定控件指定DataSourceID属性,数据源控件帮你做了一切工作,其实不然,数据源控件只负责收集与数据交互的相关信息,如:SqlDataSource的

一起谈.NET技术,asp.net控件开发基础(18)

本篇继续上篇的讨论,可能大家已经在使用asp.net2.0了,DataSource属性不再使用,而是跟数据源控件搭配使用.现在讨论的绑定技术都是基于1.1版本,先熟悉一下,本质上是一样的,这样一步步的学习.对以后绝对有帮助.因为当你使用数据源控件,只需要设置一个DataSourceID,方便的同时你是否知道数据源控件帮你做了什么事情,如果你想觉的够用了,可以不用了解,但我相信你一定会有需求.上篇最后说过了,讨论还刚刚开始,我们大致把核心的方法都写出来了.下面我们继续. 一.控件对比 我们可以使用

一起谈.NET技术,asp.net控件开发基础(17)

本篇将开始介绍如自定义数据绑定控件,这里感谢很多人的支持,有你们的支持很高兴.这里首先需要大家熟悉asp.net模板控件的使用,还有自定义模板控件.因为数据绑定控件多是基于模板控件的. 一.回顾 如果你使用过asp.net内置的数据控件(如DataList,Repeater),你一定会这么做 1.设置数据源 DataSource属性 2.调用数据绑定  DataBind方法 3.在控件的不同模板内使用绑定语法显示数据 这三步应该是必须要做的 其他更多的 你可能需要对绑定的数据进行统一的一些操作(

一起谈.NET技术,asp.net控件开发基础(10)

集合属性相信大家都很熟悉也很常用,如DropDownList,ListBox等控件 <asp:DropDownList ID="DropDownList1" runat="server">            <asp:ListItem>测试1</asp:ListItem>            <asp:ListItem>测试2</asp:ListItem>            <asp:Lis

一起谈.NET技术,asp.net控件开发基础(3)

本次来介绍控件的事件处理. 我们知道Button控件有OnClick事件,DropDownList控件有SelectedIndexChanged事件. 一.回发事件和客户端回发 下面来看一个最简单的例子,按钮单击事件 protected void Button1_Click(object sender, EventArgs e)2 {3 Label1.Text = "你好: "+TextBox1.Text;4 } 大家知道Web 服务器控件创建的按钮的类型有三种 1.Button 2.

一起谈.NET技术,asp.net控件开发基础(1)

asp.net本身提供了很多控件,提供给我们这些比较懒惰的人使用,我认为控件的作用就在此,因为我们不想重复工作,所以要创建它,这个本身便是一个需求的关系,所以学习控件开发很有意思. wrox网站上有本书 Professional ASP.NET 2.0 Server Control and Component Development,现在还没有出版,但网站上放出了代码,所以正好下载过来学习一下. 我看过前几章代码,环环相扣,作者用不同的知识向我们展示同一个效果,所以循序渐进的学下来很有好处.虽然