当前位置:首页 > Web基础控件开发–属性(续)

Web基础控件开发–属性(续)

点击次数:1508  更新日期:2010-12-30
\n

主题
关于控件属性的元数据的使用方法
开篇语
上一章中,简单的介绍了属性的分类,如果忘记了,可以返回上一章看看
其实,话又说回来,有的东西,只要知道她是怎么回事就行,没必要硬是给她盖个名字,易或弄个定义,为“定义而定义”,倒是显得有点迂腐
开始了
为了说明属性的一些基本元数据的使用方法,在这里做一个显示name,age,address的自定义People控件,然后我们一一给这些属性加上她们的元数据


\n

1.1定义People的枚举类型职业


\n

using System;


\n

namespace CustomPeople
{
/**//// <summary>
/// 职业
/// </summary>
public enum Metier
{
农场主,运动员,程序设计员
}
}


\n


\n

其实,我不喜欢做程序设计员,倒是想做农场主,放放羊,摘摘葡萄,傍晚拥美女入梦,呵呵,做梦罢了:)
1.2定义People的住址(就是自定义类型的复杂属性)

Code
using System;
using System.ComponentModel;


\n

namespace CustomPeople
{
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Address
{
private String street = null;
private String city = null;
private String state = null;
private String zip = null;


\n

[NotifyParentProperty(true)]
public String Street
{
get
{
return street;
}
set
{
street = value;
}
}


\n

[
Category("Behavior"),
DefaultValue(""),
Description("城市"),
NotifyParentProperty(true),
]
public String City
{
get
{
return city;
}
set
{
city = value;
}
}


\n

[
Category("Behavior"),
DefaultValue(""),
Description("国籍"),
NotifyParentProperty(true),
]


\n

public String State
{
get
{
return state;
}
set
{
state = value;
}
}


\n

[
Category("Behavior"),
DefaultValue(""),
Description("邮编"),
NotifyParentProperty(true)
]
public String Zip
{
get
{
return zip;
}
set
{
zip = value;
}
}
}
}


\n


\n

这年头,做人难,做男人更难,要结婚吧,女方硬是要买房子。北京,上海的房子想都不敢想,所以选了湖南,长沙,河西麓谷,这个小地方

1.3呈现People

Code
using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;


\n

namespace CustomPeople
{
[ParseChildren(true)]
[PersistChildren(false)]
public class People : Control
{
private String name = null;
Address address = new Address();
private Metier metier;
private int age = 0;
private String family = null;


\n

属性#region 属性
[Description("年龄")]

public int Age
{
get
{
return age;
}
set
{
age = value;
}
}


\n

[Description("姓名")]

public String Name
{
get
{
return name;
}
set
{
name = value;
}
}


\n

[Description("是否成家")]


\n

public String Family
{
get
{
return family;
}
set
{
family = value;
}
}


\n

[Description("职业")]
public Metier CustomMetier
{
get
{
return metier;
}
set
{
metier = value;
}
}
[Description("地址集合")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public Address CustomAddress
{
get
{
return address;
}
}


\n

#endregion


\n

protected override void Render(HtmlTextWriter output)
{
output.Write(“姓名: ” + Name + “<br>”);
output.Write(“年龄: ” + Age + “<br>”);
output.Write(“是否成家: ” + Family + “<br>”);
output.Write(“职业: ” + CustomMetier + “<br>”);
output.Write(“具体地址: ” + CustomAddress.Street + “<br> 城市: “
+ CustomAddress.City + “<br> 国籍: ” +
CustomAddress.State + “<br> 邮编: ” + CustomAddress.Zip + “<br>”);
}
}
}


\n

这年头,做技术的,25,26结婚的少,再过两年吧
预备工作都做好了,那么一个个来看元数据

1.4 在设计时要用到的DesignerSerializationVisibility
当设置为Hidden时,你会发现右边可视窗口中的属性,在“源”中,没有生成对应的标记
这是怎么回事呢?当设置为Content时,你会惊奇的发现,生成了对应的标记,哈哈,记住,她的作用就是生成对应的标记,不要想多了
1.5 解决自定义类型相互转换的TypeConverter
当屏蔽掉[TypeConverter(typeof(ExpandableObjectConverter))]的时候,你会发现Address这个复杂属性中的子属性不见了


\n


\n


没错,可能你已经想到了,自定义类型需要转换成String,Int,或者其他…,她就是起这么个作用
虽然,ExpandableObjectConverter类型已经替我们做一些转换工作,但是有时候,我们可以定义自己的ObjectConverter,后面的章节再讲
1.6 还记得事件”冒泡“吗?NotifyParentProperty(true)刚好派上用场
当屏蔽掉复杂属性的每个子属性的NotifyParentProperty(true)时,你会发现,修改复杂属性中的某项时,压根修改不了,又是怎么回事呢?
记得事件冒泡的原理是,把复合控件中的子对象的事件,一层一层向容器,或者说向外传递。复杂属性也是这个“道道”,当我们修改子属性,要想(父亲)复杂属性知道,我们还得标记一下Notify父Property。
1.7 编译生成


结果生成连字符形式的复杂属性


\n

<cc1:people id=”People1″ runat=”server” age=”25″ customaddress-city=”长沙” customaddress-state=”中国”
customaddress-street=”河西麓谷” customaddress-zip=”413000″ family=”未婚” name=”王孟军”></cc1:people>
这样就行了吗?当然不是,这只是我们看到的“连字符”形式的复杂属性,我们来想办法做成“内镶属性”,以方便阅读标记


\n

1.8 内镶复杂属性


\n

设置Address属性[PersistenceMode(PersistenceMode.InnerProperty)]


\n

设置People类型


\n

[ParseChildren(true)]
[PersistChildren(false)]


\n

再次编译运行,你会发现


\n


<cc1:people id=”People1″ runat=”server” age=”25″ family=”未婚” name=”王孟军”>
<CustomAddress Street=”河西麓谷” City=”长沙” State=”中国” Zip=”413000″></CustomAddress>
</cc1:people>


\n

Address变成了内镶属性,呵呵


\n

来看看是怎么生成的,PersistenceMode是一个“属性级别”的元数据,想做成内镶属性,设置为InnerProperty就行,不要去看MSDN上的解释,什么持久化,把人都搞晕!


\n

[ParseChildren(true)]和[PersistChildren(false)]都是“类型级别”的元数据,因为Address属性是要解析成属性,而不是解析成子控件,所以我们Pasee Children as Attribute is true(应该这样翻译,解析子对象作为属性,Yes),而PersistChildren意思刚好相反。


\n

总结


\n

简单的讲了一下,两种复杂属性的实现方法,以及常用的元数据的使用,在下一章,将继续讲自定义类型属性的状态保存,和自定义类型转换,有不妥之处,望大家指点,thanks


\n


demo下载


\n

参考
道不远人
Developing Microsoft ASP.NET Server Controls and Components Microsoft

来源:http://www.cnblogs.com/wmj

\n