当我们在Visual Studio添加一个自定义控件时,它都会给我们以下默认的代码。
[DefaultProperty("Text")] [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")] public class WebCustomControl1 : WebControl { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] public string Text { get { String s = (String)ViewState["Text"]; return ((s == null) ? String.Empty : s); } set { ViewState["Text"] = value; } } protected override void RenderContents(HtmlTextWriter output) { output.Write(Text); } } [DefaultProperty("Text")] [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")] public class WebCustomControl1 : WebControl { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] public string Text { get { String s = (String)ViewState["Text"]; return ((s == null) ? String.Empty : s); } set { ViewState["Text"] = value; } } protected override void RenderContents(HtmlTextWriter output) { output.Write(Text); } }
在这个控件中有个默认的属性"Text",在这个属性有[DefaultValue("")]相应的特性,来给该属性设置默认值。以前一直
想不明白微软是怎么实现的,直到昨天看了《你必须知道的.Net》中讲“特性”这一章受到了启发。于是我马上去试试,
还真的可以。废话少说,来看看我的实现方法。
首先我们先创建一个自己默认值特性SelfDefaultValueAttribute:
[AttributeUsageAttribute(AttributeTargets.All, // 可以对任何应用程序元素应用属性 AllowMultiple = true, // 允许指定多个实例 Inherited = false)] // 不继承到派生类 public class SelfDefaultValueAttribute : System.Attribute { public SelfDefaultValueAttribute(object defaultVale) { this.AttrValue = defaultVale; } public object AttrValue { get; set; } } [AttributeUsageAttribute(AttributeTargets.All, // 可以对任何应用程序元素应用属性 AllowMultiple = true, // 允许指定多个实例 Inherited = false)] // 不继承到派生类 public class SelfDefaultValueAttribute : System.Attribute { public SelfDefaultValueAttribute(object defaultVale) { this.AttrValue = defaultVale; } public object AttrValue { get; set; } }
接着我们创建一个自己的控件父类SelfControl
public class SelfControl { public SelfControl() { Type tp = this.GetType(); PropertyInfo[] propInfoList = tp.GetProperties(); //获得所有的属性 foreach (PropertyInfo p in propInfoList) { //获得当前属性的特性 SelfDefaultValueAttribute m = Attribute.GetCustomAttribute(p, typeof (SelfDefaultValueAttribute)) as SelfDefaultValueAttribute; //判断该属性是否有特性 if (m != null) { //设置默认值 p.SetValue(this, m.AttrValue, null); } else { //设置值为空 p.SetValue(this, null, null); } } } [SelfDefaultValue("")] public virtual string Name { get; set; } } public class SelfControl { public SelfControl() { Type tp = this.GetType(); PropertyInfo[] propInfoList = tp.GetProperties(); //获得所有的属性 foreach (PropertyInfo p in propInfoList) { SelfDefaultValueAttribute m = Attribute.GetCustomAttribute(p, typeof (SelfDefaultValueAttribute)) as SelfDefaultValueAttribute; //获得当前属性的特性 /*判断该属性是否有特性*/ if (m != null) { /*设置默认值*/ p.SetValue(this, m.AttrValue, null); } else { /*设置值为空*/ p.SetValue(this, null, null); } } } [SelfDefaultValue("")] public virtual string Name { get; set; } }
这个控件只有一个属性"Name"默认值为空。说明一下的是,在这里我们用到了反射的机制,所以我们要引入空间:
System.Reflection。
现在,我们就可以创建属于自己定义的控件了。
好了,终于完成了。那我们现在来测试一下。
public class Myrun { public static void Main(string[] args) { TestSelfControl selfCon = new TestSelfControl(); Console.WriteLine("控件宽度:{0}",selfCon.Width); Console.WriteLine("控件高度:{0}", selfCon.Height); Console.WriteLine("控件名字:{0}", selfCon.Name); Console.WriteLine("控件标签:{0}", selfCon.HtmlTag); Console.WriteLine("控件文本:{0}", selfCon.Text); Console.ReadLine(); } } public class Myrun { public static void Main(string[] args) { TestSelfControl selfCon = new TestSelfControl(); Console.WriteLine("控件宽度:{0}",selfCon.Width); Console.WriteLine("控件高度:{0}", selfCon.Height); Console.WriteLine("控件名字:{0}", selfCon.Name); Console.WriteLine("控件标签:{0}", selfCon.HtmlTag); Console.WriteLine("控件文本:{0}", selfCon.Text); Console.ReadLine(); } } 最后的结果就是: view plaincopy to clipboardprint? 控件宽度:100 控件高度:0 控件名字: 控件标签: 控件文本:TestControl 控件宽度:100 控件高度:0 控件名字: 控件标签: 控件文本:TestControl
由于我们没给控件的高度设置默认值、高度类型Int,所以高度默认为0;而名字和标签类型为String,所以为空。