自定义控件中的ParseChildren

本文详细解析了ASP.NET服务器控件中的ParseChildren属性及其应用,包括ParseChildren(true)和ParseChildren(false)的区别,如何自定义控件解析逻辑,并通过实际代码示例进行说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 今天写demo的时候,居然出现这样的错误:


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


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


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

 


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

 

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


<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)


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

 


[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
    
{
      
//省略代码
    }


   页面代码如下:

 


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

 

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

 

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


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

 



    
//自定义分析器
    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控件添加到子控件中:

       


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

 

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

  


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


    第四步:页面代码:

   


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

 

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

 

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

 

注:

  本文参考:

    1:MSDN.

    2:http://www.cnblogs.com/Clingingboy/archive/2006/09/29/514722.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值