from:http://zhf777.cnblogs.com/articles/300606.html

元数据attribute主要分为两大类:
  • 设计期attribute 
  • 解析期attribute

 

设计期attribute

 

    设计期attribute对于控件在可视化设计器(如.NET 2003)内正确运行是很重要的,设计器、属性浏览器和其他的设计期元素使用设计期attribute提供的元数据的作用如下:

 

 

 

  • 显示属性和事件
  • 执行设计期的序列化
  • 把用来实现设计期功能的类和控件或者属性类型关联起来

    因为设计时特性向可视设计工具提供有价值的信息,所以它们对在设计时正确显示控件及其成员非常重要。

    在下面的代码片段中,CategoryAttribute特性启用属性浏览器以在“Alignment”类别中显示 TextAlignment属性。DescriptionAttribute特性允许属性浏览器在用户单击某个属性时显示该属性的简要说明。

1 [C#]
2 [
3 Category("Alignment"),
4 Description("Specifies the alignment of text.")
5 ]
6 public ContentAlignment TextAlignment {  } 

    在 C# 和 Visual Basic .NET 中,名为 AttributeNameAttribute 的特性类在特性语法中可以被简单地引用为 AttributeName

    某些设计时特性是在类级别应用的。DesignerAttribute 特性在类级别应用,它通知窗体设计器使用哪个设计器类来显示控件。组件与默认的设计器 (System.ComponentModel.Design.ComponentDesigner) 关联,Windows 窗体和 ASP.NET 服务器控件与它们自己的默认设计器关联。只有在为组件或控件定义自定义设计器时才应用 DesignerAttribute

1 [C#] 
2 // Associates the designer class SimpleControl.Design.SimpleDesigner 
3 // with Simple. 
4 [ Designer(typeof(SimpleControl.Design.SimpleDesigner))] 
5 public class Simple : WebControl { // } 

1.显示属性和事件的attribute 
下面的attribute在设计期里用来显示属性和事件。

1)BrowsableAttribute 类
    指定一个属性或事件是否应显示在“属性”窗口中。
        System.Object 
           System.Attribute 
              System.ComponentModel.BrowsableAttribute 
    概要:告知属性浏览器,是否在属性浏览器中显示属性或事件。
    应用:属性和事件
    样例中的使用:[Browsable(true)]
    参数类型:Boolean
    默认值:true
    注意:当检查代码中此特性的值时,必须将该特性指定为BrowsableAttribute.Yes BrowsableAttribute.No
    示例:下面的示例将属性标记为可浏览。

 1 [C#] 
 2 [Browsable(true)] 
 3 public int MyProperty 
 4  {  
 5     get {  
 6             // Insert code here.  
 7             return 0
 8      } 
 9     set { 
10              // Insert code here.  
11     } 
12  } 

 

            下一个示例显示如何检查 MyPropertyBrowsableAttribute 的值。 
            首先,代码获取具有该对象的所有属性的 PropertyDescriptorCollection。 
            接着,将代码编入 PropertyDescriptorCollection 的索引,以获取 MyProperty。 
            然后它返回该属性的特性,并将它们保存到特性变量中。 
            该示例提供两种不同的方法检查 BrowsableAttribute 的值。 
            在第二个代码片断中,示例调用 Equals 方法。在最后一个代码段中,该示例使用 Browsable 属性检查此值。 

 1 [C#] 
 2 // Gets the attributes for the property. 
 3 AttributeCollection attributes = 
 4     TypeDescriptor.GetProperties(this)["MyProperty"].Attributes; 
 5 
 6 // Checks to see if the value of the BrowsableAttribute is Yes. 
 7 if(attributes[typeof(BrowsableAttribute)].Equals(BrowsableAttribute.Yes)) { 
 8     // Insert code here. 
 9 
10 
11 // This is another way to see whether the property is browsable. 
12 BrowsableAttribute myAttribute = 
13     (BrowsableAttribute)attributes[typeof(BrowsableAttribute)]; 
14 if(myAttribute.Browsable) { 
15     // Insert code here. 
16 
17 

            如果将类标记为 BrowsableAttribute,可使用下列代码检查该值。

1 [C#] 
2 AttributeCollection attributes = 
3     TypeDescriptor.GetAttributes(MyProperty); 
4 if(attributes[typeof(BrowsableAttribute)].Equals(BrowsableAttribute.Yes)) { 
5     // Insert code here. 
6 
7 

 

2)BindableAttribute 类
    指定属性是否通常用于绑定。
        System.Object 
           System.Attribute  
              System.ComponentModel.BindableAttribute 
    概要:告知属性浏览器绑定数据到属性是否有意义。
                  带有Bindable[true]标记的属性能显示在从属性浏览器中装载的DataBinding对话框里,
                  页面开发者利用它可以把属性和数据绑定表达式关联起来。
    应用:只应用于属性 
    样例中的使用:[Bindable(true)]
    参数类型:Boolean
    默认值:false
    注意:若要在代码中检查该特性的值,必须将该特性指定为 BindableAttribute.YesBindableAttribute.No。  
            只能在设计时使用该特性。在运行时可以随意向任何属性进行绑定。 
            如果属性没有标记为Bindable(true),页面开发者仍能够通过在.aspx页面里手动输入表达式 
            来把属性和一个数据绑定表达式关联起来。
    示例:下面的示例将属性标记为适于将数据绑定到的属性。

 1 [C#] 
 2 [Bindable(true)] 
 3 public int MyProperty { 
 4     get { 
 5        // Insert code here. 
 6        return 0
 7     } 
 8     set { 
 9        // Insert code here. 
10     } 
11 

 

 

 

 

 

 

 

 

 

 

            下一个示例显示如何检查 MyPropertyBindableAttribute 的值。 
            首先,代码获取具有该对象的所有属性的 PropertyDescriptorCollection。 
            接着它使用索引进入 PropertyDescriptorCollection 以获取 MyProperty。 
            最后,它返回该属性的特性,并将它们保存在特性变量中。 
            此示例介绍两种不同的检查 BindableAttribute 的值的方法。 
            在第二个代码片断中,示例调用 Equals 方法。 
            在最后一个代码片段中,该示例使用 Bindable 属性检查该值。

 1 [C#] 
 2 // Gets the attributes for the property. 
 3 AttributeCollection attributes = 
 4     TypeDescriptor.GetProperties(this)["MyProperty"].Attributes; 
 5 
 6 // Checks to see if the value of the BindableAttribute is Yes. 
 7 if(attributes[typeof(BindableAttribute)].Equals(BindableAttribute.Yes)) { 
 8     // Insert code here. 
 9 
10 
11 // This is another way to see whether the property is bindable. 
12 BindableAttribute myAttribute = 
13     (BindableAttribute)attributes[typeof(BindableAttribute)]; 
14 if(myAttribute.Bindable) { 
15     // Insert code here. 
16 }  
17 
18 // Yet another way to see whether the property is bindable.  
19 if (attributes.Contains(BindableAttribute.Yes)) {  
20     // Insert code here.  
21 

 


            如果将类标记为 BindableAttribute,则可使用以下代码检查该值。

1 [C#] 
2 AttributeCollection attributes = 
3     TypeDescriptor.GetAttributes(MyProperty); 
4 if(attributes[typeof(BindableAttribute)].Equals(BindableAttribute.Yes)) { 
5     // Insert code here. 
6 }

3)CategoryAttribute 类
   
指定其属性或事件将显示在可视化设计器中的类别。
        System.Object
           System.Attribute
              System.ComponentModel.CategoryAttribute
    概要:提供一个分类名,以这个分类名来显示属性或事件。
                  这个attribute允许属性浏览器以逻辑分组的形式显示属性和事件。 
    应用:属性和事件
    样例中的使用:[Category("Appearance")]
    参数类型:string
    默认值:"Default"
    注意CategoryAttribute 指示在一个被设置为按分类顺序模式的 
            System.Windows.Forms.PropertyGrid 控件中列出属性或事件时, 
            将关联的属性或事件与之关联的类别。 
            如果没有对属性或事件应用 CategoryAttribute, 
            则 System.Windows.Forms.PropertyGrid 将属性或事件与杂项类别关联。 
            通过在 CategoryAttribute 的构造函数中指定类别的名称, 
            可以为任何名称创建新的类别。 
            Category 属性指示该属性所代表的类别的名称。 
            Category 属性还以透明方式对类别名称进行本地化。 
            这个attribute可以被局部化。
    对继承者的说明:如果使用类别名称而不是预定义的名称, 
                    并且想要本地化类别名称, 
                    则必须重写 GetLocalizedString 方法。 
                    此外,可以重写 Category 属性以提供您自己的本地化逻辑。 
    CategoryAttribute 类定义下列通用类别

类别 说明
Action 与可用操作相关的属性。
Appearance 与实体的外观相关的属性。
Behavior 与实体的行为相关的属性。
Data 与数据和数据源管理相关的属性。
Default 组合到默认类别中的属性。
Design 仅在设计时可用的属性。
DragDrop 与拖放操作相关的属性。
Focus 与焦点相关的属性。
Format 与格式设置相关的属性。
Key 与键盘相关的属性。
Layout 与布局相关的属性。
Mouse 与鼠标相关的属性。
WindowStyle 与顶级窗体的窗口样式相关的属性。

    示例:下面的示例创建 MyImage 属性。

 1 [C#] 
 2 [Category("Appearance")] 
 3 public Image MyImage { 
 4     get { 
 5        // Insert code here. 
 6        return image1; 
 7     } 
 8     set { 
 9        // Insert code here. 
10     } 
11 

 

            下一个示例获取 MyImage 的类别。 
            首先,代码获取具有该对象的所有属性的 PropertyDescriptorCollection。 
            接着,将代码编入 PropertyDescriptorCollection 的索引, 
            以获取 MyImage。然后它返回该属性的特性,并将它们保存到 attributes 变量中。 
            然后,该示例通过以下方法输出类别: 
            从 AttributeCollection 检索 CategoryAttribute,然后将它写到控制台屏幕上。

 1 [C#] 
 2 // Gets the attributes for the property. 
 3 AttributeCollection attributes = 
 4     TypeDescriptor.GetProperties(this)["MyImage"].Attributes; 
 5 
 6 // Prints the description by retrieving the CategoryAttribute. 
 7 // from the AttributeCollection. 
 8 CategoryAttribute myAttribute = 
 9     (CategoryAttribute)attributes[typeof(CategoryAttribute)]; 
10 Console.WriteLine(myAttribute.Category); 

4)DefaultEventAttribute 类
   
指定组件的默认事件。
        System.Object
           System.Attribute
              System.ComponentModel.DefaultEventAttribute
   
概要:告诉属性浏览器哪一个控件事件是默认事件。 
            允许页面开发者双击设计界面中的控件,为默认事件编写事件处理代码。
    应用:只应用于事件
    样例中的使用:[DefaultEvent("Click")] 
    参数类型:string
    默认值:无
    示例:以下示例定义名为 MyCollection 的集合类。 
            该类标记为 DefaultEventAttribute,它指定 CollectionChanged 作为默认事件。

 1 [C#] 
 2 [DefaultEvent("CollectionChanged")] 
 3 public class MyCollection : BaseCollection { 
 4      
 5     private CollectionChangeEventHandler onCollectionChanged; 
 6      
 7     public event CollectionChangeEventHandler CollectionChanged { 
 8        add { 
 9           onCollectionChanged += value; 
10        } 
11        remove { 
12           onCollectionChanged -= value; 
13        } 
14     } 
15     // Insert additional code. 
16 

 

 

 

 

 

 

 

            下一个示例创建 MyCollection 的实例。 
            然后它获取该类的特性,提取 DefaultEventAttribute,并输出默认事件的名称。

 1 [C#] 
 2 public static int Main() { 
 3     // Creates a new collection. 
 4     MyCollection myNewCollection = new MyCollection(); 
 5 
 6     // Gets the attributes for the collection. 
 7     AttributeCollection attributes = TypeDescriptor.GetAttributes(myNewCollection); 
 8 
 9     /* Prints the name of the default event by retrieving the 
10      * DefaultEventAttribute from the AttributeCollection. */ 
11     DefaultEventAttribute myAttribute = 
12        (DefaultEventAttribute)attributes[typeof(DefaultEventAttribute)]; 
13     Console.WriteLine("The default event is: " + myAttribute.Name); 
14     return 0
15 

5)DefaultPropertyAttribute 类
   
指定组件的默认属性。
        System.Object
           System.Attribute
              System.ComponentModel.DefaultPropertyAttribute
    概要
:告诉属性浏览器哪一个控件属性是默认属性。  
            页面开发者在设计界面中选择控件时,该属性被属性浏览器突出显示。
    应用:只应用于属性 
    样例中的使用:[DefaultProperty("MyProperty")]
    参数类型:string
    默认值:无
    示例:以下示例定义名为 MyControl 的控件。 
            该类标记为 DefaultPropertyAttribute,它指定 MyProperty 作为默认属性。


 1 [C#] 
 2 [DefaultProperty("MyProperty")] 
 3 public class MyControl : Control {  
 4     public int MyProperty { 
 5        get { 
 6           // Insert code here. 
 7           return 0
 8        } 
 9        set { 
10           // Insert code here. 
11        } 
12     }  
13     // Insert any additional code.  
14 

            下一个示例创建 MyControl 的实例。 
            然后它获取该类的特性,提取 DefaultPropertyAttribute,并输出默认属性的名称。

 1 [C#] 
 2 public static int Main() { 
 3     // Creates a new control. 
 4     MyControl myNewControl = new MyControl(); 
 5 
 6     // Gets the attributes for the collection. 
 7     AttributeCollection attributes = TypeDescriptor.GetAttributes(myNewControl); 
 8 
 9     /* Prints the name of the default property by retrieving the 
10      * DefaultPropertyAttribute from the AttributeCollection. */ 
11     DefaultPropertyAttribute myAttribute = 
12        (DefaultPropertyAttribute)attributes[typeof(DefaultPropertyAttribute)]; 
13     Console.WriteLine("The default property is: " + myAttribute.Name); 
14   
15     return 0
16 

6)DescriptionAttribute 类
   
指定属性或事件的说明。 
        System.Object
           System.Attribute
              System.ComponentModel.DescriptionAttribute
   
概要:提供一个简要的描述,在用户选择了属性或事件时,属性浏览器就显示这个描述。
    应用:属性和事件 
    样例中的使用:[Description("The image associated with the control")] 
    参数类型:string
    默认值:无
    注意:可视化设计器在引用组件成员时可以显示指定的说明, 
            如在“属性”窗口中。调用 Description 访问该特性的值。 
            这个attribute可以被局部化。
    示例:下面的示例创建 MyImage 属性。

 1 [C#] 
 2 [Description("The image associated with the control"),Category("Appearance")] 
 3 public Image MyImage { 
 4     get { 
 5        // Insert code here. 
 6        return image1; 
 7     } 
 8     set { 
 9        // Insert code here. 
10     } 
11 

            下一个示例获取 MyImage 的说明。 
            首先,代码获取具有该对象的所有属性的 PropertyDescriptorCollection。 
            接着,将它编入 PropertyDescriptorCollection 的索引, 
            以获取 MyImage。然后它返回该属性的特性,并将它们保存到特性变量中。             
            然后该示例通过以下方法输出说明: 
            从 AttributeCollection 检索 DescriptionAttribute,然后将它写到控制台屏幕上。

 1 [C#] 
 2 // Gets the attributes for the property. 
 3 AttributeCollection attributes = 
 4     TypeDescriptor.GetProperties(this)["MyImage"].Attributes; 
 5 
 6 /* Prints the description by retrieving the DescriptionAttribute 
 7   * from the AttributeCollection. */ 
 8 DescriptionAttribute myAttribute = 
 9     (DescriptionAttribute)attributes[typeof(DescriptionAttribute)]; 
10 Console.WriteLine(myAttribute.Description); 

7)EditorBrowsableAttribute 类
   
指定某个属性或方法在编辑器中可以查看。不能继承此类。
        System.Object 
           System.Attribute   
              System.ComponentModel.EditorBrowsableAttribute
    概要:告知代码编辑器是否为属性、方法或事件显示对IntelliSense的支持。 
    应用:属性、方法和事件 
    样例中的使用:[EditorBrowsable(EditorBrowsableState.Never)]
    参数类型:EditorBrowsableState的枚举类型
    默认值:EditorBrowsableState.Always
    注意:可以在可视化设计器或文本编辑器中使用该类来确定用户可见的内容。 
            例如,Visual Studio .NET 中的智能感知引擎使用此特性来确定是否显示方法或属性。  
            代码编辑器默认地显示对IntelliSense的支持,仅当想重载默认行为时才应用这个attribute。 
            EditorBrowsableState枚举成员如下:

成员名称 说明
Advanced 该属性或方法是只有高级用户才可以看到的功能。编辑器可以显示或隐藏这些属性。
Always 该属性或方法在编辑器中始终是可浏览的。
Never 该属性或方法始终不能在编辑器中浏览。


    示例:下面的示例说明如何通过为 EditorBrowsableAttribute 特性设置适当的值来向智能感知隐藏控件的属性。 
            在打开新应用程序,添加对控件的引用,并且声明该控件的实例之后, 
            IntelliSense 不在下拉列表框中显示 Age 属性。

 1 [C#] 
 2 int ageval; 
 3 [EditorBrowsable(EditorBrowsableState.Never)] 
 4 public int Age 
 5 
 6     get { return ageval; } 
 7     set 
 8     { 
 9         if (!ageval.Equals(value)) 
10         { 
11             ageval = value; 
12         } 
13     } 
14 
15 

2.用于设计期序列化的attribute 
    下面的attribute告知设计器如何去序列化控件及控件的属性。序列化是在页面中对应于设计视图中的更改生成HTML的过程。

1)DefaultValueAttribute 类
    指定属性的默认值。
        System.Object
           System.Attribute
              System.ComponentModel.DefaultValueAttribute
    概要:为属性提供一个默认值。  
    应用:属性  
    样例中的使用:[DefaultValue("Edit Text")]
    参数类型:任何的原始类型、枚举类型或字符串文字类型。根据attribute的标记为复杂属性提供默认值。
    默认值:无
    注意:如果属性的类型具有一个相关联的转换器,就可以为复杂属性提供一个默认值。
            在这种情况下,必须采用attribute的两参数形式,形式中第一参数规定了属性的类型,
            第二参数规定了这个值的字符串表示,例如:[DefaultValue(typeof(Color),"Red")]。
            可以使用任何值创建 DefaultValueAttribute。成员的默认值通常是其初始值。
            可视化设计器可以使用默认值重置成员的值。代码生成器也可使用默认值确定是否为成员生成代码。
    示例:以下示例将 MyProperty 的默认值设置为 false
 1 [C#] 
 2 
 3 private bool myVal=false
 4 
 5 [DefaultValue(false)] 
 6 public bool MyProperty { 
 7     get { 
 8        return myVal; 
 9     } 
10     set { 
11        myVal=value; 
12     } 
13 

            下一个示例检查 MyProperty 的默认值。
            首先,代码获取具有该对象的所有属性的 PropertyDescriptorCollection。
            接着,将它编入 PropertyDescriptorCollection 的索引,以获取 MyProperty
            然后它返回该属性的特性,并将它们保存到特性变量中。
            接着该示例通过从 AttributeCollection 检索 DefaultValueAttribute 来打印默认值,并将其名称写到控制台屏幕。
 1 [C#] 
 2 // Gets the attributes for the property. 
 3 AttributeCollection attributes = 
 4     TypeDescriptor.GetProperties(this)["MyProperty"].Attributes; 
 5 
 6 /* Prints the default value by retrieving the DefaultValueAttribute 
 7   * from the AttributeCollection. */ 
 8 DefaultValueAttribute myAttribute = 
 9     (DefaultValueAttribute)attributes[typeof(DefaultValueAttribute)]; 
10 Console.WriteLine("The default value is: " + myAttribute.Value.ToString()); 

2)DesignerSerializationVisibilityAttribute 类
   
指定在设计时序列化组件上的属性时所使用的持久性类型。
        System.Object
           System.Attribute
              System.ComponentModel.DesignerSerializationVisibilityAttribute
    概要:告诉设计器是否序列化属性或属性的内容。  复杂属性含有内容-比如子属性或者集合项
    应用:属性  
    样例中的使用:[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    参数类型:DesignerSerializationVisibility的枚举类型:
                Content,指定序列化程序应该序列化属性的内容,而不是属性本身。此字段为只读。
                Hidden,指定序列化程序不应该序列化属性的值。此静态(在 Visual Basic 中为 Shared)字段是只读的。
                Visible,指定应该允许序列化程序序列化属性的值。此静态(在 Visual Basic 中为 Shared)字段是只读的。
    默认值:DesignerSerializationVisibility.Visible
    注意:默认情况下,代码生成器序列化属性值。attribute允许重载默认行为,排除序列化机制中的属性,
            或者序列化属性的内容(例如子属性或者集合项)而不是属性自身。
            当序列化程序保持设计模式文档的可持续状态时,它通常会向组件的初始化方法中添加代码,
            以便保持已在设计时设置的属性值。如果尚未设置指示其他行为的特性,大多数基类型都会默认出现此情况。
            DesignerSerializationVisibilityAttribute 允许您指示属性值是否为 Visible,
            是否应在初始化代码中保持,Hidden,是否不应在初始化代码中保持,
            是否由 Content 组成,它应具有为分配到该属性的对象的每个公共属性(而非隐藏属性)生成的初始化代码。
            没有 DesignerSerializationVisibilityAttribute 的成员将被视为
            具有值为 Visible 的 DesignerSerializationVisibilityAttribute
            如果可能,序列化程序会将标记为 Visible 的属性值序列化为该类型。
            要为特定类型或属性指定自定义序列化,请使用 DesignerSerializerAttribute。
    示例:下面的示例说明如何使用设置为 Content 的 DesignerSerializationVisibilityAttribute
            以保持可在设计时配置的用户控件的公共属性值。
            要使用该示例,请先将以下代码编译到用户控件库中。
            下一步,将新项目中的引用添加到已编译的 .DLL 文件,右击工具箱并选择“自定义工具箱...”,
            然后从包含用户控件的 .DLL 文件选择控件,从而在设计模式下将 .DLL 文件中的控件添加到“工具箱”。
            接着,将控件从工具箱拖动到“窗体”中,然后设置选中控件时属性网格中列出的 DimensionData 对象的属性。
            查看窗体代码时,代码应已添加到控件父窗体的 InitializeComponent 方法中,
            该方法将控件的属性值设置为您在设计模式下设置的值。
 1 [C#] 
 2 using System; 
 3 using System.Collections; 
 4 using System.ComponentModel; 
 5 using System.ComponentModel.Design; 
 6 using System.Drawing; 
 7 using System.Windows.Forms; 
 8 
 9 namespace DesignerSerializationVisibilityTest 
10 
11     /* The code for this user control declares a public property of type DimensionData with a DesignerSerializationVisibility  
12     attribute set to DesignerSerializationVisibility.Content, indicating that the properties of the object should be serialized. 
13 
14     The public, not hidden properties of the object that are set at design time will be persisted in the initialization code 
15     for the class object. Content persistence will not work for structs without a custom TypeConverter.*/            
16 public class ContentSerializationExampleControl : System.Windows.Forms.UserControl 
17 
18     private System.ComponentModel.Container components = null
19 
20     [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
21     public DimensionData Dimensions 
22     { 
23         get 
24         { 
25         return new DimensionData(this); 
26         }             
27     } 
28 
29     public ContentSerializationExampleControl() 
30     { 
31             InitializeComponent();             
32     } 
33 
34     protected override void Dispose( bool disposing ) 
35     { 
36         if( disposing ) 
37         { 
38             if( components != null ) 
39                 components.Dispose(); 
40         } 
41         base.Dispose( disposing ); 
42     } 
43 
44     private void InitializeComponent() 
45     { 
46         components = new System.ComponentModel.Container(); 
47     } 
48 
49 
50     [TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))] 
51     /*This attribute indicates that the public properties of this object should be listed in the property grid.*/ 
52 public class DimensionData 
53 {             
54         private Control owner; 
55 
56     /*This class reads and writes the Location and Size properties from the Control which it is initialized to.*/ 
57     internal DimensionData(Control owner) 
58     { 
59             this.owner = owner;                 
60     } 
61 
62     public Point Location 
63     { 
64         get 
65         { 
66         return owner.Location; 
67         } 
68         set 
69         { 
70         owner.Location = value; 
71         } 
72     } 
73 
74     public Size FormSize 
75     { 
76         get 
77         { 
78             return owner.Size; 
79         } 
80         set 
81         { 
82             owner.Size = value; 
83         } 
84     } 
85 
86 

3)NotifyParentPropertyAttribute 类
   
指示当此属性应用到的属性的值被修改时将通知父属性。不能继承此类。
        System.Object
           System.Attribute
              System.ComponentModel.NotifyParentPropertyAttribute

    概要:告知属性浏览器从子属性到父属性或者到控件上传一个更改通知。  
    应用:复杂属性和它们的子属性  
    样例中的使用:[NotifyParentPropertyAttribute(true)]
    参数类型:Boolean
    默认值:false
    注意:如果属性的父属性应该在该属性值更改时接到通知,则向该属性应用 NotifyParentPropertyAttribute
            例如,Size 属性具有两个嵌套的属性:高度和宽度。
            这些嵌套的属性应标记为 NotifyParentPropertyAttribute(true),以便当属性值更改时,
            它们可以通知父属性来更新其值并显示。
   
4)PersistChildrenAttribute 类
   
定义 ASP.NET 服务器控件使用的元数据属性。该属性指示设计时是否应将 ASP.NET 服务器控件的子控件作为嵌套内部控件保持。无法继承此类。
    System.Object
        System.Attribute
            System.Web.UI.PersistChildrenAttribute
    概要:告知设计器嵌套在控件标签内的内容是否和子控件或者属性对应。  
    应用:控件 
    样例中的使用:[PersistChildren(false)]
    参数类型:Boolean
    默认值:值为true意味着嵌套的内容对应子控件
    注意:WebControl标记为PersistChildren(false)。如果控件派生于WebControl,
            仅当实现的控件的嵌套内容对应于子控件时,才需要重新应用这个attribute。
            如果该属性为 true,则将 ASP.NET 服务器控件的子控件作为嵌套服务器控件标记保持。
            如果为 false,则将该控件的属性作为嵌套元素保持。
    示例

  1 using System; 
  2 using System.Collections; 
  3 using System.Drawing; 
  4 using System.Web; 
  5 using System.Web.UI; 
  6 using System.Web.UI.WebControls; 
  7 
  8 namespace PersistChildrenSamples 
  9 
 10    // The child element class. 
 11    public class Employee 
 12    { 
 13       private String name; 
 14       private String title; 
 15       private String alias; 
 16 
 17       public Employee():this ("","",""){} 
 18       
 19       public Employee (String name, String title, String alias) 
 20       { 
 21          this.name = name; 
 22          this.title = title; 
 23          this.alias = alias; 
 24       } 
 25       public String Name 
 26       { 
 27          get 
 28          { 
 29             return name; 
 30          } 
 31          set 
 32          { 
 33             name = value; 
 34          } 
 35       } 
 36       
 37       public String Title 
 38       { 
 39          get 
 40          { 
 41             return title; 
 42          } 
 43          set 
 44          { 
 45             title = value; 
 46          } 
 47       } 
 48       
 49       public String Alias 
 50       { 
 51          get 
 52          { 
 53             return alias; 
 54          } 
 55          set 
 56          { 
 57             alias = value; 
 58          } 
 59       } 
 60    } 
 61    // Use the PersistChildren attribute to set the Persist 
 62    // property to false so that none of this class's 
 63    // child controls will be persisted as controls. They will 
 64    // be persisted only as child elements of this class. 
 65    // If you set the PersistChildren attribute to true, or if you 
 66    // do not include this attribute when you create a control, 
 67    // the child controls will be persisted as controls.   
 68    [PersistChildren(false)] 
 69    public class CollectionPropertyControl : Control 
 70    {  
 71       private String header; 
 72       private ArrayList employees = new ArrayList(); 
 73       
 74       public String Header 
 75       { 
 76          get 
 77          { 
 78             return header; 
 79          } 
 80          set 
 81          { 
 82             header = value; 
 83          } 
 84       } 
 85 
 86 
 87       
 88       public ArrayList Employees 
 89       { 
 90          get 
 91          { 
 92             return employees; 
 93          } 
 94       } 
 95       // Override the CreateChildControls method to 
 96       // add child controls to the Employees property when this 
 97       // custom control is requested from a page. 
 98       protected override void CreateChildControls() 
 99       { 
100          Label label = new Label(); 
101          label.Text = Header; 
102          label.BackColor = Color.Beige; 
103          label.ForeColor = Color.Red; 
104          Controls.Add(label); 
105          Controls.Add(new LiteralControl("<BR> <BR>")); 
106 
107          Table table = new Table(); 
108          TableRow htr = new TableRow(); 
109 
110          TableHeaderCell hcell1 = new TableHeaderCell();    
111          hcell1.Text = "Name"
112          htr.Cells.Add(hcell1); 
113 
114          TableHeaderCell hcell2 = new TableHeaderCell(); 
115          hcell2.Text = "Title"
116          htr.Cells.Add(hcell2); 
117          
118          TableHeaderCell hcell3 = new TableHeaderCell(); 
119          hcell3.Text = "Alias"
120          htr.Cells.Add(hcell3); 
121          table.Rows.Add(htr); 
122 
123          table.BorderWidth = 2
124          table.BackColor = Color.Beige; 
125          table.ForeColor = Color.Red; 
126          foreach (Employee employee in Employees) 
127          { 
128             TableRow tr = new TableRow(); 
129 
130             TableCell cell1 = new TableCell(); 
131             cell1.Text = employee.Name; 
132             tr.Cells.Add(cell1); 
133             
134             TableCell cell2 = new TableCell(); 
135             cell2.Text = employee.Title; 
136             tr.Cells.Add(cell2); 
137             
138             TableCell cell3 = new TableCell(); 
139             cell3.Text = employee.Alias; 
140             tr.Cells.Add(cell3); 
141             
142             table.Rows.Add(tr); 
143          } 
144          Controls.Add(table); 
145          
146       } 
147    } 
148 

5)PersistenceModeAttribute 类
   
定义指定如何将 ASP.NET 服务器控件属性或事件保持到 ASP.NET 页的元数据属性。无法继承此类。
        System.Object
           System.Attribute
              System.Web.UI.PersistenceModeAttribute
    概要:告知设计器是否把属性保存到控件的标签上,或者把它作为一个嵌套属性进行保存。
    应用:属性
    样例中的使用:[PersistenceMode(PersistenceMode.InnerProperty)]
    参数类型:PersistenceMode枚举类型
成员名称 说明
Attribute 指定属性或事件保持为特性。
EncodedInnerDefaultProperty 指定属性作为 ASP.NET 服务器控件的唯一内部文本而进行保持。属性值是 HTML 编码的。只能对字符串做这种指定。
InnerDefaultProperty 指定属性在 ASP.NET 服务器控件中保持为内部文本。还指示将该属性定义为元素的默认属性。只能指定一个属性为默认属性。
InnerProperty 指定属性在 ASP.NET 服务器控件中保持为嵌套标记。这通常用于复杂对象;它们具有自己的持久性属性。
    默认值:PersistenceMode.Attribute 
    示例:  
 1 [C#] 
 2 [PersistenceMode(PersistenceMode.InnerProperty),
 3 TemplateContainer(typeof(TemplateItem))]
 4 public ITemplate MessageTemplate {
 5    get {
 6       return _messageTemplate;
 7    }
 8    set {
 9       _messageTemplate = value;
10    }
11 }

6)TagPrefixAttribute 类
    定义在 Web 页中用于标识自定义控件的标记前缀。无法继承此类。
        System.Object
           System.Attribute
              System.Web.UI.TagPrefixAttribute
    概要:告知设计器生成一个Register指令,把一个标签前缀映射到命名控件和配件中。
            当页面开发者把控件从工具箱拖放到设计界面时,这个指令就在.aspx页面中生成。 
    应用:包含有服务器控件的配件 
    样例中的使用:[assembly:TagPrefix("CustomControls", "custom")]
    参数类型:第一个参数指定了命名空间,第二个参数允许为配件中的控件指定一个标签前缀。
    注意:Register指令仅当页面开发者把控件从工具箱拖放到设计界面时才生成。
            如果页面开发者手工为页面中的控件添加HTML,指令不会生成。
            TagPrefixAttribute 定义为自定义控件指定标记前缀别名所需的程序集级属性。
            此属性由 Visual Studio .NET 等工具用来在使用自定义控件的 ASP.NET 页中自动生成 Register 指令。
            此指令向命名空间注册标记前缀。而且,它指定自定义控件代码实现所在的程序集。
            有了此指令后,就可以在 Web 页中以声明方式使用自定义控件。
    示例
 1 [C#] 
 2 using System;
 3 using System.Web;
 4 using System.Web.UI;
 5 using System.Web.UI.WebControls;
 6 
 7 [assembly:TagPrefix("CustomControls""custom")]
 8 
 9 namespace CustomControls
10 {
11     // Simple custom control
12     public class MyCS_Control : Control
13       {
14             private String message = "Hello";
15             
16             public virtual String Message
17             {
18                   get
19                   {
20                         return message;
21                   }
22                   set
23                   {
24                         message = value;
25                   }
26             }
27             
28             [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] 
29             protected override void Render( HtmlTextWriter writer)
30             {
31             writer.Write("<span style='background-color:aqua; font:8pt tahoma, verdana;'> "
32                         + this.Message + "<br>" + "C# version. The time on the server is " + System.DateTime.Now.ToLongTimeString()
33                         + "</span>");                  
34             }      
35       }
36 }

3.提供高级设计期功能的相关联类的attribute 
    下列attribute使得可以将提供高级设计期功能的类与控件相关联。

1)DesignerAttribute 类
   
指定用于为组件实现设计时服务的类。
        System.Object
           System.Attribute
              System.ComponentModel.DesignerAttribute
    概要:把设计器与控件关联。
    应用:控件
    样例中的使用:[Designer(typeof (ControlDesigner))]
    注意:当设计器和控件位于不同配件时,后期绑定类型是必要的。
            用于设计时服务的类必须实现 IDesigner 接口。 
            使用 DesignerBaseTypeName 属性查找设计器的基类。使用 DesignerTypeName 属性获取与该成员关联的设计器的类型名称。
    示例:下面的示例创建一个名为 MyForm 的类。MyForm 具有两项属性,其中一项为 DesignerAttribute
            它指定此类使用 DocumentDesigner,另一项为 DesignerCategoryAttribute,它指定 Form 类别。
1 [Designer("System.Windows.Forms.Design.DocumentDesigner, System.Windows.Forms.Design.DLL"
2     typeof(IRootDesigner)),
3     DesignerCategory("Form")]
4 public class MyForm : ContainerControl {
5     // Insert code here.
6 }

            下一个示例创建 MyForm 的实例。然后它获取该类的特性,提取 DesignerAttribute,并输出设计器的名称。
 1 [C#] 
 2 public static int Main() {
 3     // Creates a new form.
 4     MyForm myNewForm = new MyForm();
 5 
 6     // Gets the attributes for the collection.
 7     AttributeCollection attributes = TypeDescriptor.GetAttributes(myNewForm);
 8 
 9     /* Prints the name of the designer by retrieving the DesignerAttribute
10      * from the AttributeCollection. */
11     DesignerAttribute myAttribute = 
12        (DesignerAttribute)attributes[typeof(DesignerAttribute)];
13     Console.WriteLine("The designer for this class is: " + myAttribute.DesignerTypeName);
14   
15     return 0;
16 }

2)EditorAttribute 类
    指定用来更改属性的编辑器。无法继承此类。
        System.Object
           System.Attribute
              System.ComponentModel.EditorAttribute
    概要:把一个用户界面(UI)编辑器与类型或属性相关联,也把一个组件编辑器与一个控件相关联。
    应用:类或属性
    样例中的使用:[Editor(typeof(StringEditor),typeof(UITypeEditor))] 
                或者 [Editor(typeof(MyLabelComponentEditor),typeof(ComponentEditor))]
    注意:第一个参数是编辑器的类型,第二个参数是编辑器的基类型。
            当编辑器和类型(或控件)位于不同配件时,后期绑定类型是必要的。
    示例:下面的示例创建 MyImage 类。该类标有 EditorAttribute,它将 ImageEditor 指定为其编辑器。
1 [C#] 
2 [Editor("System.Windows.Forms.ImageEditorIndex, System.Design"
3     typeof(UITypeEditor))]
4 public class MyImage
5 {
6     // Insert code here.
7 } 

            下一个示例创建 MyImage 类的实例。然后,它获取该类的特性,并输出 myNewImage 使用的编辑器的名称。
 1 [C#] 
 2 public static int Main() {
 3     // Creates a new component.
 4     MyImage myNewImage = new MyImage();
 5 
 6     // Gets the attributes for the component.
 7     AttributeCollection attributes = TypeDescriptor.GetAttributes(myNewImage);
 8 
 9     /* Prints the name of the editor by retrieving the EditorAttribute 
10      * from the AttributeCollection. */
11     
12     EditorAttribute myAttribute = (EditorAttribute)attributes[typeof(EditorAttribute)];
13     Console.WriteLine("The editor for this class is: " + myAttribute.EditorTypeName);
14 
15     return 0;
16 }

3)TypeConverterAttribute 类
   
指定用作此特性所绑定到的对象的转换器的类型。无法继承此类。
        System.Object
           System.Attribute
              System.ComponentModel.TypeConverterAttribute
    概要:把一个类型转换器与类型或属性关联
    应用:类或属性
    样例中的使用:[TypeConverter(typeof(MyClassConverter))]
    注意:当类型转换器和类型(或控件)位于不同配件时,后期绑定类型是必要的。
            用于转换的类必须从 TypeConverter 继承。
            使用 ConverterTypeName 属性来获取为该特性所绑定到的对象提供数据转换的类名。
    示例:以下示例通知 MyClass 使用名为 MyClassConverter 的类型转换器。此示例假定已在其他地方实现了 MyClassConverter。实现转换器 (MyClassConverter) 的类必须从 TypeConverter 类继承。
1 [C#] 
2 [TypeConverter(typeof(MyClassConverter))]
3 public class MyClass {
4     // Insert code here.
5 }

            下一个示例创建 MyClass 的实例。然后,它获取该类的特性,并输出 MyClass 所用类型转换器的名称。
 1 [C#] 
 2 public static int Main() {
 3     // Creates a new instance of MyClass.
 4     MyClass myNewClass = new MyClass();
 5 
 6     // Gets the attributes for the instance.
 7     AttributeCollection attributes = TypeDescriptor.GetAttributes(myNewClass);
 8 
 9     /* Prints the name of the type converter by retrieving the 
10      * TypeConverterAttribute from the AttributeCollection. */
11     TypeConverterAttribute myAttribute = 
12         (TypeConverterAttribute)attributes[typeof(TypeConverterAttribute)];
13     
14     Console.WriteLine("The type conveter for this class is: " + 
15         myAttribute.ConverterTypeName);
16 
17     return 0;
18 }

解析期attribute

    下列attribute被页面解析器用来解析.aspx的语法,为相应页面中的类生成代码。

1)ControlBuilderAttribute 类
    指定用于在 ASP.NET 分析器内生成自定义控件的 ControlBuilder 类。无法继承此类。
        System.Object
           System.Attribute
              System.Web.UI.ControlBuilderAttribute
    概要:将控件与自定义的控件生成器相关联。
    应用:控件
    样例中的使用:[ControlBuilderAttribute(typeof(CustomParseControlBuilder))]
    注意:ControlBuilder类与基类Control相关联,因此也和每个服务器控件相关联。仅当想把自定义控件生成器和控件相关联时,才应用ControlBuilderAttribute。
    示例:下面创建一个自定义选择列表,它用于基于在运行时定义的 SelectedIndexMessage 值显示消息。下面的命令行用于生成可执行文件。
            csc /t:library /out:myWebAppPath/bin/cs_MyControlBuilderAtt.dll ControlBuilderAtt.cs
  1 [C#] 
  2 
  3 /* File name: controlBuilderAttribute.cs. */
  4 
  5 using System;
  6 using System.Web;
  7 using System.Web.UI;
  8 using System.Web.UI.WebControls;
  9 using System.Collections;
 10 
 11 
 12 namespace CustomControls
 13 
 14 {
 15   public class MyCS_Item : Control 
 16   /* Class name: MyCS_Item. 
 17    * Defines the child control class.
 18    */
 19     {
 20 
 21       private String _message;
 22 
 23       public String Message 
 24       {
 25         get 
 26         {
 27           return _message;
 28         }
 29         set 
 30         {
 31            _message = value;
 32         }
 33      }
 34     }
 35 
 36 
 37     public class CustomParseControlBuilder : ControlBuilder 
 38     /* Class name: CustomParserControlBuilder.
 39      * Defines the functions and data to be used in building custom controls. 
 40      * This class is referenced using the ControlBuilderAttribute class. See class below.
 41      */
 42     {
 43       [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] 
 44       public override Type GetChildControlType(String tagName, IDictionary attributes) 
 45       {
 46         if (String.Compare(tagName, "customitem"true== 0
 47         {
 48            return typeof(MyCS_Item);
 49         }
 50         return null;
 51       }
 52     }
 53 
 54 
 55     [ 
 56        ControlBuilderAttribute(typeof(CustomParseControlBuilder)) 
 57     ]
 58     public class MyCS_CustomParse : Control 
 59     /* Class name: MyCS_CustomParse.
 60      * Performs custom parsing of a MyCS_CustomParse control type 
 61      * child control. 
 62      * If the child control is of the allowed type, it is added to an 
 63      * array list. This list is accessed, using the container control attribute 
 64      * SelectedIndex, to obtain the related child control Message attribute to be displayed.
 65      */
 66     {
 67 
 68        private ArrayList _items         = new ArrayList();
 69        private int       _selectedIndex = 0;
 70 
 71        public int SelectedIndex 
 72        { 
 73            get 
 74            {
 75               return _selectedIndex;
 76            }
 77            set 
 78            {
 79               _selectedIndex = value;
 80            }
 81        }
 82 
 83        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] 
 84        protected override void AddParsedSubObject(Object obj) 
 85        /* Function name: AddParsedSubObject.
 86         * Updates the array list with the allowed child objects.
 87         * This function is called during the parsing of the child controls and 
 88         * after the GetChildControlType function defined in the associated control 
 89         * builder class.
 90         */
 91        {
 92           if (obj is MyCS_Item) 
 93          {
 94               _items.Add(obj);
 95            }
 96        }
 97 
 98        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] 
 99        protected override void Render(HtmlTextWriter output) 
100        /* Function name: Render.
101         * Establishes the rules to render the built control. In this case, a message is
102         * rendered that is a function of the parent control SelectedIndex attribute and 
103         * the related child Message attribute.
104         */
105        {
106           if (SelectedIndex < _items.Count) 
107          {
108               output.Write("<span style='background-color:aqua; color:red; font:8pt tahoma, verdana;'><b>" +
109               ((MyCS_Item) _items[SelectedIndex]).Message + "</b></span>" );
110          }
111        }
112     }    
113 }

            下面的示例使用上面定义的自定义控件。尤其是,它在运行时分配 SelectedIndexMessage 值来确定要呈现的消息。
            请注意,在 Register 指令中显示的值反映上一个命令行。
 1 [C#] 
 2 <%@ Register TagPrefix="custom" Assembly="myControlBuilderAtt" Namespace="CustomControls" %>
 3 <h4>Using ControlBuilderAttribute Class<h4>
 4 <form runat="server">
 5 <custom:MyCS_CustomParse SelectedIndex="2" runat=server>
 6 <customitem Message="C# version. Item One selected"/>
 7 <customitem Message="C# version. Item Two selected"/>
 8 <customitem Message="C# version. Item Three selected"/>
 9 <customitem Message="C# version. Item Four selected"/>
10 </custom:MyCS_CustomParse>
11 </form>

2)ParseChildrenAttribute 类
   
定义可在开发 ASP.NET 服务器控件时使用的元数据属性。使用它可以指示当在页上以声明方式使用控件时,嵌套在服务器控件标记内的 XML 元素是应视为属性还是应视为子控件。无法继承此类。
        System.Object
           System.Attribute
              System.Web.UI.ParseChildrenAttribute
    概要:通知解析器是否把控件内的嵌套内容翻译为属性或者子控件。
    应用:控件
    样例中的使用:[ParseChildren(true, "Employees")] 或者 [ParseChildren(true)]
    注意:构造器接收一个Boolean值,指示解析器是否把嵌套内容解析为属性。
            Control没有标记这个attribute,就意味着解析器把嵌套内容当作控件。
            WebControl标记为ParseChildren(true),因此解析器把嵌套内容当作属性。
            可以通过重新把这个attribute应用到控件来重载和基类有关联的解析逻辑。
            这个attribute的两个参数形式中的第二个是属性名,使用两个参数形式时,控件标签内的嵌套内容必须和第二个参数设定的属性一致。
            当 String 传递到该类的构造函数中时,它定义父服务器控件的默认属性。
    示例
  1 [C#] 
  2 // When compiling this class, name it ParseChildren.dll.
  3 // Create a namespace that defines two classes: one is a custom control 
  4 // named Employee, which is created for every instance of a child
  5 // element with its name declared in a page associated with this namespace,
  6 // and the other, named Employees, that contains these child elements.
  7 using System;
  8 using System.Collections;
  9 using System.Web;
 10 using System.Web.UI;
 11 using System.Web.UI.WebControls;
 12 
 13 namespace ParseChildrenSamples
 14 {
 15    // The child element class.
 16    public class Employee
 17    {
 18       private String name;
 19       private String title;
 20       private String alias;
 21 
 22       public Employee():this ("","",""){}
 23       
 24       public Employee (String name, String title, String alias)
 25       {
 26          this.name = name;
 27          this.title = title;
 28          this.alias = alias;
 29       }
 30       public String Name
 31       {
 32          get
 33          {
 34             return name;
 35          }
 36          set
 37          {
 38             name = value;
 39          }
 40       }
 41       
 42       public String Title
 43       {
 44          get
 45          {
 46             return title;
 47          }
 48          set
 49          {
 50             title = value;
 51          }
 52       }
 53       
 54       public String Alias
 55       {
 56          get
 57          {
 58             return alias;
 59          }
 60          set
 61          {
 62             alias = value;
 63          }
 64       }
 65    }
 66    // Use the ParseChildren attribute to set the ChildrenAsProperties
 67    // and DefaultProperty properties. Using this constructor, the
 68    // control parses all child controls as properties and must define
 69    // a public property named Employees, which it declares as
 70    // an ArrayList. Nested (child) elements must correspond to
 71    // child elements of the Employees property or to other
 72    // properties of the control.   
 73    [ParseChildren(true"Employees")]
 74    public class CollectionPropertyControl : Control
 75    {  
 76       private String header;
 77       private ArrayList employees = new ArrayList();
 78       
 79       public String Header
 80       {
 81          get
 82          {
 83             return header;
 84          }
 85          set
 86          {
 87             header = value;
 88          }
 89       }
 90 
 91 
 92       
 93       public ArrayList Employees
 94       {
 95          get 
 96          {
 97             return employees;
 98          }
 99       }
100       // Override the CreateChildControls method to 
101       // add child controls to the Employees property when this
102       // custom control is requested from a page.
103       protected override void CreateChildControls()
104       {
105          Label label = new Label();
106          label.Text = Header;
107          label.BackColor = System.Drawing.Color.Beige;
108          label.ForeColor = System.Drawing.Color.Red;
109          Controls.Add(label);
110          Controls.Add(new LiteralControl("<BR> <BR>"));
111 
112          Table table = new Table();
113          TableRow htr = new TableRow();
114 
115          TableHeaderCell hcell1 = new TableHeaderCell();    
116          hcell1.Text = "Name";
117          htr.Cells.Add(hcell1);
118 
119          TableHeaderCell hcell2 = new TableHeaderCell();
120          hcell2.Text = "Title";
121          htr.Cells.Add(hcell2);
122          
123          TableHeaderCell hcell3 = new TableHeaderCell();
124          hcell3.Text = "Alias";
125          htr.Cells.Add(hcell3);
126          table.Rows.Add(htr);
127 
128          table.BorderWidth = 2;
129          table.BackColor = System.Drawing.Color.Beige;
130          table.ForeColor = System.Drawing.Color.Red;
131          foreach (Employee employee in Employees)
132          {
133             TableRow tr = new TableRow();
134 
135             TableCell cell1 = new TableCell();
136             cell1.Text = employee.Name;
137             tr.Cells.Add(cell1);
138             
139             TableCell cell2 = new TableCell();
140             cell2.Text = employee.Title;
141             tr.Cells.Add(cell2);
142             
143             TableCell cell3 = new TableCell();
144             cell3.Text = employee.Alias;
145             tr.Cells.Add(cell3);
146             
147             table.Rows.Add(tr);
148          }
149          Controls.Add(table);
150          
151       }
152    }
153 }

3)TemplateContainerAttribute 类
   
声明在创建后将包含模板的 INamingContainer 的类型。
        System.Object
           System.Attribute
              System.Web.UI.TemplateContainerAttribute
    概要:将ITemplate属性的容器控件的类型通知解析器。解析器把这个类型作为数据绑定表达式中的Container的确切类型。
    应用:类型为ITemplate的属性
    样例中的使用:[TemplateContainer(typeof(FirstTemplateContainer))]
    示例
 
  1 /* File name:templatecontainerattribute.cs. */
  2 
  3 using System;
  4 using System.Web;
  5 using System.Web.UI;
  6 using System.Web.UI.WebControls;
  7 using System.Collections;
  8 
  9 namespace CustomControls
 10 {
 11   [ParseChildren(true)]
 12   public class TemplatedFirstControl : Control, INamingContainer
 13   {
 14     private ITemplate firstTemplate;
 15     private String text = null;
 16     private Control myTemplateContainer;
 17     
 18     [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]         
 19     protected override void OnDataBinding(EventArgs e) 
 20     {
 21       EnsureChildControls();
 22       base.OnDataBinding(e);
 23     }
 24 
 25 
 26     [TemplateContainer(typeof(FirstTemplateContainer))]
 27     public ITemplate FirstTemplate
 28     {
 29       get 
 30       {
 31         return firstTemplate;
 32       }
 33       set
 34       {
 35         firstTemplate = value;
 36       }
 37     }
 38             
 39     public String Text
 40     {
 41       get 
 42       {
 43         return text;
 44       }
 45       set
 46       {
 47         text = value;
 48       }
 49     }
 50             
 51     public String DateTime
 52     {
 53       get 
 54       {
 55         return System.DateTime.Now.ToLongTimeString();
 56       }
 57                   
 58     }
 59             
 60     public Control MyTemplateContainer
 61     {
 62       get
 63       {
 64         return myTemplateContainer;
 65       }
 66     }
 67     
 68     [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]         
 69     protected override void CreateChildControls ()
 70     {
 71       if (FirstTemplate != null)
 72       {
 73         myTemplateContainer = new FirstTemplateContainer(this);
 74         FirstTemplate.InstantiateIn(myTemplateContainer);
 75         Controls.Add(myTemplateContainer);
 76       }
 77       else
 78       {
 79         Controls.Add(new LiteralControl(Text + " " + DateTime));
 80       }
 81     }
 82             
 83     }
 84 
 85 
 86     public class FirstTemplateContainer : Control, INamingContainer
 87     {
 88       private TemplatedFirstControl parent;
 89       public FirstTemplateContainer(TemplatedFirstControl parent)
 90       {
 91         this.parent = parent;
 92       }
 93             
 94       public String Text
 95       {
 96         get
 97         {
 98           return parent.Text;
 99         }
100       }
101      
102       public String DateTime
103       {
104         get 
105         {
106           return parent.DateTime;
107         }
108                   
109       }
110     }    
111   }