In the development of custom controls, we often add properties of complex types to the controls. Using declarative persistence (declarative persistence) enables page developers to enable page developers to declaratively set these complex property values in an ASP. NET page, without having to write any C # or vb.net code.
See the example below:
- The DataKeyNames property of the GridView, whose data type is string[]:
<asp:gridview id="GridView1" runat="server" datakeynames ="ID, Title, Author"></asp:GridView>
The RowStyle property of the GridView, whose data type is System.Web.UI.WebControls.TableItemStyle:
<asp:gridview id="GridView1 " runat="server"> <rowstyle backcolor="Red" forecolor="Black"/> </asp:GridView>
The Columns property of the GridView, whose data type is: System.Web.UI.WebControls.DataControlFieldCollection
<asp:gridview id="GridView1"runat="Server"Datasourceid="ObjectDataSource1"> <Columns> <asp:boundfield datafield="Title"headertext="Title"sortexpression="Title"/> <asp:boundfield datafield="ID"headertext="ID"sortexpression="ID"/> </Columns></asp:GridView>
The PagerTemplate property of the GridView, whose data type is System.Web.UI.ITemplate:
<asp:gridview id="GridView1 " runat="server"> <PagerTemplate> <div> <span>pager template</span> </div> </ Pagertemplate></asp:gridview>
How can you implement these complex attributes declaratively in aspx?
I'll go through the stories behind each of these properties, and the focus of this article is not on how to maintain the state of these properties, but how to build from ASPX markup to complex attributes.
One, from ASPX Markup to C # or vb.net class
1. Asp. NET pipeline
For the ASPX page request, ASP. The goal of the net pipeline is to find a managed class that completely represents the requested page, and if the class does not exist, it is created and compiled immediately.
Asp. NET page consists of markup (Markup) and code (codebehind) files, the entire page compilation process consists of two main steps: First loading the aspx Markup into a C # suitable for the ASP. NET class Hierarchy or vb.net the temporary class, we can find the file containing the class from the temporary folder of ASP. Next, compile the temporary class into an assembly, and finally load the resulting assembly into the AppDomain that hosts the application.
For a particular request, the HttpApplication object gets the processing object from the config file to serve the request, as we can see from the following code snippet. aspx resources are associated with pagehandlerfactory. The PageHandlerFactory object in the ASP. NET pipeline creates an instance of the current request page, which is then referred to the page for processing.
"*.aspx"verb="*"Type="System.Web.UI.PageHandlerFactory"Validate="True"/> <add path="*.ashx"verb="*"Type="System.Web.UI.SimpleHandlerFactory"Validate="True"/>2. PageHandlerFactory
PageHandlerFactory is responsible for locating the assembly that contains the request page class, and if the Assembly has not yet been created, it is created on the fly. The request page class is created by parsing the markup code of the ASPX resource and is stored in the temporary folder of ASP.%appdata% "Local" Temp "Temporary ASP.
3. ControlBuilder
The ControlBuilder class, in turn, is responsible for parsing the ASPX markup declaration into an ASP. Each control on the page is typically associated with a default ControlBuilder class. During the ASPX page parsing process, the ASP. NET page framework first generates the ControlBuilder object tree corresponding to the page control tree, and then the ControlBuilder tree is used to generate the page code and create the control tree.
ControlBuilder defines how to parse the contents of a control tag, we can override this default behavior by customizing the ControlBuilder class.
During page parsing, ControlBuilder checks to see if the ASP. ParseChildren (True) Attribute is indicated by the Web server control. If marked, the nested child nodes within the control will be resolved to the child properties of the control, otherwise the node will be resolved to the ASP. NET server control and added to the Controls collection of the original control, see the next section for the attribute.
Second, the related attributes
1. ParseChildrenAttribute
ParseChildrenAttribute is applied to a custom control class, the attribute tells the ASPX page parser how to resolve nested nodes inside a custom control.
The following table describes in detail the use of ParseChildrenAttribute:
Attribute Usage |
Describe |
ParseChildren (True) |
Nested child nodes must correspond to the properties of the current control, and a parse error will result if the corresponding property is not found. In addition, no text nodes are allowed inside the tag of the current control. Example: Repeater and other data-bound controls. |
ParseChildrenAttribute (True, "PropertyName") |
The current control must contain a public property with the property name equal to the parameter propertyname. The property should be the data type of a collection class. The nested byte point must correspond to the child element of the attribute. Example: HtmlTable, HtmlTableRow control. |
ParseChildrenAttribute (False) ParseChildrenAttribute (False, "PropertyName") ParseChildrenAttribute is not applied to the control. |
The nested child nodes must be an ASP. The page parser creates a child control based on the node, and then calls the IParserAccessor.AddParsedSubObject method on the current control, which is the default implementation of adding the resolved child control to the Controls collection of the current control. Any literal text node will be created as an example of LiteralControl. Example: Panel control. |
ParseChildrenAttribute (Type childcontroltype) |
The nested child nodes must be the specified ASP. NET server control type. Example: MultiView control. |
The WebControl class is already marked with ParseChildrenAttribute (True), so each control that derives directly or indirectly from WebControl supports internal property declaration persistence by default.
In the following example, the RowStyle node will be parsed as a sub-property of the GridView control:
<asp:gridview id="GridView1 " runat="server"> <rowstyle backcolor="Red" forecolor="Black"/> </asp:GridView>
The ASP. NET server control can modify the parsing logic described above by ControlBuilderAttribute to specify a specific controlbuilder.
2. Persistchildrenattribute
Persistchildrenattribute is applied to a custom control class and is a Designtime attribute. To specify whether to resolve a nested node inside a custom control to a child control, true will mean that the node is parsed as a control.
The WebControl class is already marked with Persistchildrenattribute (False), and the Panel class is Persistchildrenattribute (True).
Example:
[ParseChildren (false), PersistChildren (true)] Public class mycontrol:webcontrol{}
Add a button control to mycontrol at design time:
<cc1:mycontrol2 id="MyControl21"runat="Server"borderstyle="dotted"height="56px"Width="349px"> <asp:button id="Button2"runat="Server"text="Button"/></cc1:mycontrol2>
At this point the user can select the Neutron button control in the VS IDE's Design view, and if MyControl is Persistchildrenattribute (False), the child control button cannot be selected.
3. PersistenceModeAttribute
PersistenceModeAttribute is applied on the ASP. NET Server control property, is a designtime attribute that specifies how the control property is to be asp.netserver at design time Save to ASP page
Or, in the ASPX mrakup, how to declare the property.
Persistencemode.innerproperty specifies that properties are persisted as nested tags in the ASP. NET server control.
Third, see the example again
1. The DataKeyNames property of the GridView, whose data type is string[]:
<asp:gridview id="GridView1" runat="server" datakeynames ="ID, Title, Author"></asp:GridView>
By default, the ASP. NET page resolution engine sets the value of the DataKeyNames property in ASPX markup directly to that property, and the direct setting will fail because the property has a data type of string[].
What did the GridView do? See the following code snippet:
[TypeConverter (typeof(Stringarrayconverter))] Public Virtual string [] datakeynames{getset
That is, by adding a specific typeconvertor to the property to implement the property settings, in the example above Stringarrayconvter the string as string[], set to the DataKeyNames property.
2. The RowStyle property of the GridView, whose data type is Tablerowstyle:
<asp:gridview id="GridView1 " runat="server"> <rowstyle backcolor="Red" forecolor="Black"/> </asp:GridView>
Because the GridView control has already marked ParseChildrenAttribute (True), its inner nested nodes are parsed into their own properties.
Additionally, the RowStyle property adds PersistenceModeAttribute to specify how the ASPX markup code is generated.
[PersistenceMode (persistencemode.innerproperty)] Public TableItemStyle rowstyle{get
3. The Columns property of the GridView, whose data type is datafieldcollection:
<asp:gridview id="GridView1"runat="Server"Datasourceid="ObjectDataSource1"> <Columns> <asp:boundfield datafield="Title"headertext="Title"sortexpression="Title"/> <asp:boundfield datafield="ID"headertext="ID"sortexpression="ID"/> </Columns></asp:GridView>
Asp. NET page is how to parse the above section of code? First the columns node will be parsed to the properties of the GridView, but how is the child node inside the columns parsed and added to the Columns collection?
Also, why does the VS IDE help us list all the sub-types that can be instantiated when I prepare to add the child node code of the Columns property in the VS IDE source view?
Let's take a look at the data type of the Columns property: Datacontrolfieldcollection.
Asp. NET page parser when parsing properties of a control, if it is found that the property implements the IList interface, after parsing the child nodes of the property, it calls the Add method of the property and adds the child element.
Also at design time, the property data type's item sub-property gets the sub-element type that can be instantiated, and is displayed by smart hints.
In other words, these collection class properties must implement the IList interface to implement the declaration persistence of the attribute.
Take a look at the C # code for the markup code for the example above, and note the code line 16,17.
1[System.Diagnostics.DebuggerNonUserCodeAttribute ()] 2Private Global:: System.Web.UI.WebControls.BoundField @__buildcontrol__control23 ()3{ 4 Global:: System.Web.UI.WebControls.BoundField @__ctrl;5@__ctrl =New Global:: System.Web.UI.WebControls.BoundField ();6@__ctrl. DataField ="ID"; 7@__ctrl. HeaderText ="ID"; 8@__ctrl. SortExpression ="ID"; 9 return@__ctrl;Ten} One A[System.Diagnostics.DebuggerNonUserCodeAttribute ()]13Private void@__buildcontrol__control22 (System.Web.UI.WebControls.DataControlFieldCollection @__ctrl) -{ the Global:: System.Web.UI.WebControls.BoundField @__ctrl1; -@__ctrl1 = This[email protected]__buildcontrol__control23 (); -@__ctrl. ADD (@__ctrl1); -} + -[System.Diagnostics.DebuggerNonUserCodeAttribute ()]21Private Global:: System.Web.UI.WebControls.GridView @__buildcontrolgridview1 () A{ at Global:: System.Web.UI.WebControls.GridView @__ctrl; -@__ctrl =New Global:: System.Web.UI.WebControls.GridView (); - This. GridView1 =@__ctrl; -@__ctrl. Applystylesheetskin ( This); -@__ctrl.id ="GridView1"; - in This[Email protected]__buildcontrol__control22 (@__ctrl. Columns); - to return@__ctrl; +}
Referring to the points above, we can write out the declaration persistence of custom collection class properties.
Of course, this just implements ASPX to CS, and we also need to add code about state Management (implementing the IStateManager Interface) to the collection class and the sub-element to use in the actual project, which I will not repeat.
4. The PagerTemplate property of the GridView, whose data type is itemplate:
In fact, inside the ITemplate node is a collection of controls, and Templatebuilder is responsible for building the tag into a group of controls.
At runtime we put an instantiated template into the specified container through the InstantiateIn method of the ITemplate interface.
Complete the full text.
Reprint Address: http://www.cnblogs.com/tedzhao/archive/2008/05/10/1190772.html
Go Asp. NET custom Control complex property declaration persistence analysis