理解ParseChildren用法

我们知道,在开发ASP.NET 服务器控件时,ParseChildrenAttribute 类指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容,下边我引用MSDN的解释,然后用实例对其进行进一步的说明。

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

以元数据属性 (Attribute) ParseChildren(true) 标记服务器控件将指示分析器把包含在服务器控件标记内的元素解释为属性 (Property)。在这种情况下,ChildrenAsProperties 属性为 true。

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

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

如果我们仅仅看上面的解释,我相信大家都很郁闷。

针对ParseChildren(true,"<Default Property>") 这种情况,MSDN给出了一个例子:
http://msdn.microsoft.com/zh-cn/library/system.web.ui.parsechildrenattribute(VS.80).aspx

其中这段html

ContractedBlock.gif ExpandedBlockStart.gif Code
      <AspSample:CollectionPropertyControl id="CollectionPropertyControl1" 
                                           runat
="server">
        
<AspSample:Employee Name="Employee 1" 
                            Title
="Title 1" 
                            Alias
="Alias 1" />
        
<AspSample:Employee Name="Employee 2" 
                            Title
="Title 2" 
                            Alias
="Alias 2" />
      
</AspSample:CollectionPropertyControl>   

 产生的临时代码如下(我做了一些整理,和实际的文件会有出入):

ContractedBlock.gif ExpandedBlockStart.gif Code
 1        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
 2ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.Employee @__BuildControl__control4() {
 3            global::Samples.AspNet.CS.Controls.Employee @__ctrl;
 4            @__ctrl = new global::Samples.AspNet.CS.Controls.Employee();
 5            @__ctrl.Name = "Employee 1";
 6            @__ctrl.Title = "Title 1";
 7            @__ctrl.Alias = "Alias 1";
 8            return @__ctrl;
 9        }

10        
11        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
12ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.Employee @__BuildControl__control5() {
13            global::Samples.AspNet.CS.Controls.Employee @__ctrl;
14            @__ctrl = new global::Samples.AspNet.CS.Controls.Employee();
15            @__ctrl.Name = "Employee 2";
16            @__ctrl.Title = "Title 2";
17            @__ctrl.Alias = "Alias 2";
18            return @__ctrl;
19        }

20        
21        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
22ExpandedBlockStart.gifContractedBlock.gif        private void @__BuildControl__control3(System.Collections.ArrayList @__ctrl) {
23            global::Samples.AspNet.CS.Controls.Employee @__ctrl1;
24            @__ctrl1 = this.@__BuildControl__control4();
25            @__ctrl.Add(@__ctrl1);
26
27            global::Samples.AspNet.CS.Controls.Employee @__ctrl2;
28            @__ctrl2 = this.@__BuildControl__control5();
29            @__ctrl.Add(@__ctrl2);
30        }

31        
32        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
33ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.CollectionPropertyControl @__BuildControlCollectionPropertyControl1() {
34            global::Samples.AspNet.CS.Controls.CollectionPropertyControl @__ctrl;
35            @__ctrl = new global::Samples.AspNet.CS.Controls.CollectionPropertyControl();
36            this.CollectionPropertyControl1 = @__ctrl;
37            @__ctrl.ID = "CollectionPropertyControl1";
38            this.@__BuildControl__control3(@__ctrl.Employees);
39            return @__ctrl;
40        }

 可以看出,在应用了[ParseChildren(true, "Employees")]元数据属性,产生的Employee对象加入到一个ArrayList对象中,这个ArrayList对象又赋值给CollectionPropertyControl的Employees属性。

那么针对ParseChildren(false)这种情况,要实现同样的效果,我们应该怎么办呢?
MSDN告诉我们,这种情况由ControlBuilder来处理,我对MSDN提供的类文件做了一些修改:

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Permissions;

namespace Samples.AspNet.CS.Controls
ExpandedBlockStart.gifContractedBlock.gif
{
    [AspNetHostingPermission(SecurityAction.Demand,
Level 
= AspNetHostingPermissionLevel.Minimal)]
    
public class MyControlBuilder : ControlBuilder
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{

        
public override Type GetChildControlType(string tagName, IDictionary attribs)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
// Allows TableRow without "runat=server" attribute to be added to the collection.
            if (String.Compare(tagName, "AspSample:Employee"true== 0)
                
return typeof(Employee);
            
return null;
        }


        
public override void AppendLiteralString(string s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
// Ignores literals between rows.
        }


    }


    
// The child element class.
    [AspNetHostingPermission(SecurityAction.Demand,
       Level 
= AspNetHostingPermissionLevel.Minimal)]
    
public sealed class Employee
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
private String name;
        
private String title;
        
private String alias;

ExpandedSubBlockStart.gifContractedSubBlock.gif        
public Employee() : this(""""""{ }

        
public Employee(String name, String title, String alias)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
this.name = name;
            
this.title = title;
            
this.alias = alias;
        }

        
public String Name
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return name;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                name 
= value;
            }

        }


        
public String Title
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return title;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                title 
= value;
            }

        }


        
public String Alias
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return alias;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                alias 
= value;
            }

        }

    }

    
// Use the ParseChildren attribute to set the ChildrenAsProperties
    
// and DefaultProperty properties. Using this constructor, the
    
// control parses all child controls as properties and must define
    
// a public property named Employees, which it declares as
    
// an ArrayList. Nested (child) elements must correspond to
    
// child elements of the Employees property or to other
    
// properties of the control.
    [ControlBuilderAttribute(typeof(MyControlBuilder))]
    
//[ParseChildren(true, "Employees")]
    [AspNetHostingPermission(SecurityAction.Demand,
       Level 
= AspNetHostingPermissionLevel.Minimal)]
    
public sealed class CollectionPropertyControl : Control
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
private String header;
        
private ArrayList employees = new ArrayList();

        
protected override void AddParsedSubObject(object obj)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Employee employ 
= obj as Employee;
            
if (employ != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                employees.Add(employ);
            }


        }


        
public String Header
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return header;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                header 
= value;
            }

        }




        
public ArrayList Employees
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return employees;
            }

        }

        
// Override the CreateChildControls method to 
        
// add child controls to the Employees property when this
        
// custom control is requested from a page.
        protected override void CreateChildControls()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Label label 
= new Label();
            label.Text 
= Header;
            label.BackColor 
= System.Drawing.Color.Beige;
            label.ForeColor 
= System.Drawing.Color.Red;
            Controls.Add(label);
            Controls.Add(
new LiteralControl("<BR> <BR>"));

            Table table 
= new Table();
            TableRow htr 
= new TableRow();

            TableHeaderCell hcell1 
= new TableHeaderCell();
            hcell1.Text 
= "Name";
            htr.Cells.Add(hcell1);

            TableHeaderCell hcell2 
= new TableHeaderCell();
            hcell2.Text 
= "Title";
            htr.Cells.Add(hcell2);

            TableHeaderCell hcell3 
= new TableHeaderCell();
            hcell3.Text 
= "Alias";
            htr.Cells.Add(hcell3);
            table.Rows.Add(htr);

            table.BorderWidth 
= 2;
            table.BackColor 
= System.Drawing.Color.Beige;
            table.ForeColor 
= System.Drawing.Color.Red;
            
foreach (Employee employee in Employees)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                TableRow tr 
= new TableRow();

                TableCell cell1 
= new TableCell();
                cell1.Text 
= employee.Name;
                tr.Cells.Add(cell1);

                TableCell cell2 
= new TableCell();
                cell2.Text 
= employee.Title;
                tr.Cells.Add(cell2);

                TableCell cell3 
= new TableCell();
                cell3.Text 
= employee.Alias;
                tr.Cells.Add(cell3);

                table.Rows.Add(tr);
            }

            Controls.Add(table);

        }

    }

}

对比两个类,可以看出,我添加了一个类 MyControlBuilder,同时对CollectionPropertyControl应用了属性[ControlBuilderAttribute(typeof(MyControlBuilder))],同时,在CollectionPropertyControl类中我们重写了AddParsedSubObject方法
上边的那段html,产生的临时代码如下:
ContractedBlock.gif ExpandedBlockStart.gif Code
 1        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
 2ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.Employee @__BuildControl__control3() {
 3            global::Samples.AspNet.CS.Controls.Employee @__ctrl;
 4            @__ctrl = new global::Samples.AspNet.CS.Controls.Employee();
 5            @__ctrl.Name = "Employee 1";
 6            @__ctrl.Title = "Title 1";
 7            @__ctrl.Alias = "Alias 1";
 8            return @__ctrl;
 9        }
10        
11        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
12ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.Employee @__BuildControl__control4() {
13            global::Samples.AspNet.CS.Controls.Employee @__ctrl;
14            @__ctrl = new global::Samples.AspNet.CS.Controls.Employee();
15            @__ctrl.Name = "Employee 2";
16            @__ctrl.Title = "Title 2";
17            @__ctrl.Alias = "Alias 2";
18            return @__ctrl;
19        }
20        
21        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
22ExpandedBlockStart.gifContractedBlock.gif        private global::Samples.AspNet.CS.Controls.CollectionPropertyControl @__BuildControlCollectionPropertyControl1() {
23            global::Samples.AspNet.CS.Controls.CollectionPropertyControl @__ctrl;
24            @__ctrl = new global::Samples.AspNet.CS.Controls.CollectionPropertyControl();
25            this.CollectionPropertyControl1 = @__ctrl;
26            @__ctrl.ID = "CollectionPropertyControl1";
27            global::Samples.AspNet.CS.Controls.Employee @__ctrl1;
28            @__ctrl1 = this.@__BuildControl__control3();
29            System.Web.UI.IParserAccessor @__parser = ((System.Web.UI.IParserAccessor)(@__ctrl));
30            @__parser.AddParsedSubObject(@__ctrl1);
31            global::Samples.AspNet.CS.Controls.Employee @__ctrl2;
32            @__ctrl2 = this.@__BuildControl__control4();
33            @__parser.AddParsedSubObject(@__ctrl2);
34            return @__ctrl;
35        }

 可以看出,在应用了 [ParseChildren(false]元数据属性,产生的Employee对象加入到CollectionPropertyControl的Controls集合中。在这个过程中,代码会分析添加进来的Control是否是Employee类型,如果是则添加到employees(ArrayList类型)集合中,我们重写AddParsedSubObject方法的目的就在于此。

转载于:https://www.cnblogs.com/fengfeng/archive/2008/07/25/1251495.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值