当前位置:编程文档 >> ASP.net >> 自定义控件中的ParseChildren
首页

自定义控件中的ParseChildren

所属类别:ASP.net
推荐指数:★★☆
文档人气:8
本周人气:2
发布日期:2008-8-2
今天写demo的时候,居然出现这样的错误:


Parser Error Message: Type 'ServerControl_CachePanel.CachePanel' does not have a public property named 'WebUserControl1'.


静下心来想了一会,发面它可能和自定义控件中的ParseChildren好像有关系.


如果我们在一个textbox控件中嵌入一个label控件的话:

Code
<asp:TextBox ID="TextBox1" runat="server">
<asp:Label runat="server" Text="Label"></asp:Label>
</asp:TextBox>



页面会显示错误信息,asp:TextBox的Text属性不允许子对象,不能通过调试,这显然属于分析器错误 但是你可以这样写:

Code
<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
</asp:DropDownList>



为什么有的控件中可以嵌入其它的标记而有的控件又不行呢.查看了MSDN,才发现其中的原理.

MSDN:


1:在开发ASP.NET 服务器控件时,ParseChildrenAttribute 类指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容.


2:ParseChildrenAttribute 类允许您以 ParseChildrenAttribute 元数据属性标记服务器控件来为自定义服务器控件指定分析逻辑。


3:以元数据属性 (Attribute) ParseChildren(true) 标记服务器控件将指示分析器把包含在服务器控件标记内的元素解释为属性 (Property)。



4:以元数据属性 (Attribute) ParseChildren(true,"<Default Property>") 标记服务器控件将把 DefaultProperty 属性 (Property) 设置为传递到该属性 (Attribute) 的属性 (Property) 名称。



5:以元数据属性 ParseChildren(false)(默认值)标记服务器控件将指示分析器把包含在服务器控件标记中的元素解释为将通过关联的 ControlBuilder 进行分析的内容,即解释为控件


MSDN分别针对应用ParseChildren(true)和ParseChildren(false)给了个demo.具体例子,这里我就不帖了.结论是这样的:


1:在应用了[ParseChildren(true]元数据属性,产生的属性最终会赋值给CollectionPropertyControl的某个属性中。
2:在应用了[ParseChildren(false]元数据属性,产生的控件对象加入到CollectionPropertyControl的Controls集合中.



ParseChildren(false)的使用: 我们平时还可以这样使用ParseChildren(false)


第一:使用默认的页面分析逻辑



Code
[ParseChildren(false)]
public class ContentClass : WebControl
{

protected override void AddParsedSubObject(object obj)
{
if (obj is Content)
base.AddParsedSubObject(obj);
}

protected override void RenderContents(HtmlTextWriter writer)
{
//加载控件
}
}
//子控件
public class Content : Control
{
//省略代码
}


页面代码如下:



Code
<cc1:ContentClass
Runat="server">
<cc1:Content
id="Content1"
Runat="server">
显示的第一项,此不为属性
</cc1:Content>
</cc1:ContentClass>



控件有默认的页面分析逻辑,重写AddParsedSubObject方法,可以向控件添加子控件,也可以不重AddParsedSubObject方法,这样的情况适合加载外部控件以及用户控件.



第二:重写默认的页面分析逻辑


每个控件都有默认的解析逻辑,其通过ControlBuilder 类来实现,可以通过重写其方法来自定义解析逻辑.



Code

//自定义分析器
public class CustomControlBuilder : ControlBuilder
{
public override Type GetChildControlType(string tagName, IDictionary attribs)
{
if (String.Compare(tagName, "content", true) == 0)
return typeof(customControl);
else
return null;
}
}

//定义一个简单的控件
public class customControl : Control
{
//代码省略
}


第一步:CustomControlBuilder类重写了ControlBuilder类的GetChildControlType 方法 获取与子标记对应的控件类型的 Type在此方法中,其以content标签代替了customControl控件,改写了页分析逻辑.


第二步:定义一个简单的customControl控件.还须在父控件中重写AddParsedSubObject方法将customControl控件添加到子控件中:



Code
protected override void AddParsedSubObject(object obj)
{
if (obj is customControl)
base.AddParsedSubObject(obj);
}



第三步:把控件生成器跟控件关联起来,当然还要设置ParseChildren(false)



Code
[ControlBuilder(typeof(CustomControlBuilder))]
[ParseChildren(false)]
public class webCoustomControl : WebControl
{
}

第四步:页面代码:




Code
<cc1:webCoustomControl
Runat="Server">
<content/>
</cc1:webCoustomControl>


至于ParseChildren(true)的使用情况这次就不说了,它是和控件复杂属性相关联的。



总结:在asp.net编程过程中,其实有很多非常小的地方我们平时因为注意的不够,往往对它们没有深入的了解,造成遇到问题的时候会出现难以解决的现象。控件开发是一个非常有趣而且非常有意义的事情,所以有必要对它进入更深入的了解以及应用。本文如有不妥处望大家批评指教。

文档说明:

     

相关文档


读取评论列表……