Asp.net| Server | control
In the previous article, we introduced the basic concepts and basic theories of server controls, which are the cornerstones for building all custom server controls. However, relying on this knowledge alone is not enough to create a good server control. Because different types of server controls have different methods of creation, developers must master the basic concepts and theories and learn how to develop different types of server controls. This article and subsequent articles will detail the content associated with creating a composite control. This article focuses on the concepts of composite controls, how to create them, and then, through a typical example, deepens the reader's understanding of the method of creating a composite control.
Composite Control Overview
The word "composite" in a composite control indicates that the type control is essentially composed of multiple components. Also, the externally exposed member objects of a composite control are usually provided by the methods and properties that make up the component, and some new members may be added. A composite control can also implement custom events and handle and raise events caused by child controls. In terms of functionality, the function of a composite control is much more powerful than a simple combination of several controls, and many times it has a certain degree of special nature. For example, the new login control for ASP.net 2.0 is a typical composite control. The control user interface is composed of multiple separate controls and is set up and accessed using a single API. In addition, the login control has the ability to quickly implement a user login because of its integration with functions such as membership.
Perhaps some of the experienced readers will be puzzled when they understand the basic concepts of the composite Control: The composite controls seem very similar to the user controls, so what's the difference between them? When do you create a composite control and when do you create a user control? To answer this question, we must start with the basic concept of user control.
In simple terms, a user control is defined in a project, because the same function modules in many references, such as navigation menu, you can make this piece of code into a user control, and then, in the need to refer to the page to register, directly in the way the control used to refer to, eliminating the duplication of writing the same code work. The difference between a composite control and a user control can be summed up in the following points:
One, the shortest design-time support for composite control authoring, full design-time support for user control authoring. In a visual designer, there is no difference between authoring a user control and authoring a asp.net page.
Second, composite controls are object-oriented programming languages targeting the common language runtime, such as C #, which are authored programmatically using ASP.net page syntax and script blocks for declarative authoring.
Three, composite controls are compiled and persisted as assemblies (. dll). A user control is a text file with an. ascx extension.
Composite controls are ideal for authoring generic, republishing controls that are appropriate for application-specific functionality.
You can add a composite control to the toolbox of the visual designer and drag and drop it onto the page, which can be designed in the property box and can be written only in HTML.
Through the above, I believe that the reader can have a basic understanding of the composite control. Here's how to create a composite control. In this process, developers must grasp the following key points:
First, in general, a composite control class must derive from the System.Web.UI.WebControls.CompositeControl class. This is somewhat different from developing composite controls in the ASP.net 1.x environment. In ASP.net 1.x, the composite control must implement the System.Web.UI.INamingContainer interface. However, under ASP.net 2.0, the base class of the composite control class has changed. Here is a brief introduction to the CompositeControl class.
The CompositeControl class is an abstract class that provides naming containers and control designer functionality for custom controls, and can contain all child controls or use other control features. The Declaration code for the CompositeControl class looks like this:
Public abstract class Compositecontrol:webcontrol, INamingContainer, Icompositecontroldesigneraccessor
As shown in the code above, the CompositeControl class base is WebControl base class and implements the INamingContainer and Icompositecontroldesigneraccessor interfaces. INamingContainer is a markup interface with no methods. When a control implements INamingContainer, the page framework can create a new named range under the control, so you can ensure that child controls have unique names in the control's hierarchical tree. This is important when a composite control exposes template properties, provides data binding, or needs to transfer events to child controls. The Icompositecontroldesigneraccessor interface enables the composite control designer to re-create the child controls of its associated control at design time. The interface contains a method that needs to be implemented Recreatechildcontrols. This method enables the designer of a composite control to re-create the child controls of the control at design time.
Also, if you are creating a data-bound composite control, the base class for the custom control class should be CompositeDataBoundControl. For specific content of this category, please refer to the relevant information.
Second, you must override the CreateChildControls method of the control base class so that the child controls are initialized, instantiated, and added to the control tree. CreateChildControls is used to notify server controls that are based on a composite implementation to create any child controls they contain to prepare for postback or rendering. Overriding this method is the key to implementing a composite control. This type of writing method will be notified. NET Framework about what child controls are contained in a composite control, and the position and relationships of each child control in the control tree. In this way, the composite control uses the implementation provided by the child control for rendering, event handling, styling, and other functions.
In addition to mastering the CompositeControl base class and the CreateChildControls method in implementing the composite control, ASP.net 2.0 also provides other methods and properties related to the composite control, and mastering these members is also important for developing the composite control. These common methods and properties are listed below.
· protected virtual void EnsureChildControls ()
This method is used to determine whether the server control contains child controls. If not, the child control is created. This method first checks the current value of the ChildControlsCreated property. If this value is False, the CreateChildControls method is invoked. This method is called when you need to make sure that the child control has been created. In most cases, developers of custom server controls do not need to override this method. If you do override this method, use it in a manner similar to its default behavior.
· Public virtual Control FindControl (string)
This method is used to search for the specified server control in the current naming container.
· Public virtual bool Hascontrols ()
This method is used to determine whether the server control contains any child controls. True if the control contains other controls, or false otherwise. Because the method only determines whether any child controls exist, it can improve performance by allowing you to avoid unnecessary Controls.Count property calls. Calling this property requires the instantiation of the ControlCollection object. If there are no children, creating the object wastes server resources.
· protected virtual void Databindchildren ()
This method is new to ASP.net 2.0, which binds the data source to the child controls of the server control. This facilitates the development of composite controls with data-binding types. However, it is necessary to note that this method does not bind data to the control when the server control calls this method on. To bind a server control and all its child controls, call the DataBind method.
· protected bool Hasevents ()
This is also a new method for ASP.net 2.0, which returns a value indicating whether to register events for a control or any child controls. True if the event is registered, or false.
· Controls Property
The data type of this property is ControlCollection, which is used to get the ControlCollection object that represents the child controls of the specified server control in the UI hierarchy. The property value specifies the collection of child controls for the server control.
· NamingContainer Property
The data type of this property is control, which is used to get a reference to the server control's naming container, which creates a unique namespace to differentiate between server controls with the same Control.id property values.
· ChildControlsCreated Property
The data type of this property is bool, which is used to get a value indicating whether the child controls of the server control have been created. True if the child control has been created, otherwise false.
Typical Applications
The basics of creating composite controls are described above, with a typical application that will deepen the reader's understanding of the method of composite control implementation, focusing on rendering methods for composite controls.
Most control rendering is implemented by overriding the Render method, however, it is very different in the composite control. A composite control is composed of multiple child controls, whose rendering logic is provided by children.
Thus, in a few simpler cases, a composite control does not have to override the Render method, for example, by creating a composite control that contains text boxes and buttons, so that you can add related controls in CreateChildControls by using the class-writing method without render methods. However, in most cases, the composite control contains both child controls and HTML for formatting and layout.
In this case, if only the implementation method of class composition is taken, it is easy to cause errors, and the resulting composite control performance is greatly affected. The best solution is to rewrite the CreateChildControls method and also to rewrite the Render method. In the CreateChildControls method, add child controls to the composite control, and in the Render method, add HTML for formatting and layout for the HTTP output stream.
The key steps for rendering a composite control are listed below:
· The control base class inherits from the CompositeControl base class. This is the key to creating a composite control in ASP.net 2.0.
· Overrides the CreateChildControls method, completes instantiating, initializes child controls, and adds child controls to the control collection.
· Overrides the Recreatechildcontrls method of the Icompositecontroldesigneraccessor interface.
· If you have HTML for formatting and layout in a composite control, it is recommended that you write the content to the Render method instead of creating and adding the required LiteralControl instance in the CreateChildControls method. In addition, in order for the child controls to use the default build method during the addition of the associated HTML code, each child control must be called the RenderControl method.
In order to facilitate the reader to better understand the above content, the following examples illustrate. In this example, the register control uses child controls to create a user interface (UI) that is used to enter user information to register with the Web site. This user interface includes two TextBox controls (one for entering a user name, another for entering a user's e-mail address), and a button control for submitting information. The Register also associates the RequiredFieldValidator control with two TextBox controls to ensure that the user enters a name and e-mail address. The composite control register source code looks like this:
Using System;
Using System.ComponentModel;
Using System.Drawing;
Using System.Security.Permissions;
Using System.Web;
Using System.Web.UI;
Using System.Web.UI.WebControls;
Namespace webcontrollibrary{
[
Defaultproperty ("ButtonText"),
ToolBoxData ("<{0}:register runat=\" Server\ "> </{0}:Register>"),
]
public class Register:compositecontrol {
Defining Private fields
Private Button Submitbutton;
Private TextBox nameTextBox;
Private Label Namelabel;
Private TextBox Emailtextbox;
Private Label Emaillabel;
Private RequiredFieldValidator Emailvalidator;
Private RequiredFieldValidator Namevalidator;
Implement Properties ButtonText
[
Bindable (True),
Category ("appearance"),
DefaultValue (""),
Description ("The text on the button.")
]
public string ButtonText {
get {
EnsureChildControls ();
return submitbutton.text;
}
set {
EnsureChildControls ();
Submitbutton.text = value;
}
}
Implement property name
[
Bindable (True),
Category ("Default"),
DefaultValue (""),
Description ("User name.")
]
public string Name {
get {
EnsureChildControls ();
return nametextbox.text;
}
set {
EnsureChildControls ();
Nametextbox.text = value;
}
}
Implement Properties Nameerrormessage
[
Bindable (True),
Category ("appearance"),
DefaultValue (""),
Description ("User name validation error message.")
]
public string Nameerrormessage {
get {
EnsureChildControls ();
return namevalidator.errormessage;
}
set {
EnsureChildControls ();
Namevalidator.errormessage = value;
Namevalidator.tooltip = value;
}
}
Implement Properties Namelabeltext
[
Bindable (True),
Category ("appearance"),
DefaultValue (""),
Description ("text next to the User Name text box.")
]
public string Namelabeltext {
get {
EnsureChildControls ();
return namelabel.text;
}
set {
EnsureChildControls ();
Namelabel.text = value;
}
}
Implement attribute Email
[
Bindable (True),
Category ("Default"),
DefaultValue (""),
Description ("Mail address.")
]
public string Email {
get {
EnsureChildControls ();
return emailtextbox.text;
}
set {
EnsureChildControls ();
Emailtextbox.text = value;
}
}
Implement Properties Emailerrormessage
[
Bindable (True),
Category ("appearance"),
DefaultValue (""),
Description ("Mail address validation error message.")
]
public string Emailerrormessage {
get {
EnsureChildControls ();
return emailvalidator.errormessage;
}
set {
EnsureChildControls ();
Emailvalidator.errormessage = value;
Emailvalidator.tooltip = value;
}
}
Implement Properties Emaillabeltext
[
Bindable (True),
Category ("appearance"),
DefaultValue (""),
Description ("text next to the e-mail text box.")
]
public string Emaillabeltext {
get {
EnsureChildControls ();
return emaillabel.text;
}
set {
EnsureChildControls ();
Emaillabel.text = value;
}
}
Recreatechildcontrls method to rewrite Icompositecontroldesigneraccessor interface
protected override void Recreatechildcontrols () {
EnsureChildControls ();
}
Overriding the CreateChildControls method of the control base class
protected override void CreateChildControls () {
Clear all child controls
Controls.clear ();
Namelabel = new Label ();
nameTextBox = new TextBox ();
Nametextbox.id = "nameTextBox";
Namevalidator = new RequiredFieldValidator ();
Namevalidator.id = "Validator1";
Namevalidator.controltovalidate = nametextbox.id;
Namevalidator.text = Nameerrormessage;
Namevalidator.display = validatordisplay.static;
Emaillabel = new Label ();
Emailtextbox = new TextBox ();
Emailtextbox.id = "Emailtextbox";
Emailvalidator = new RequiredFieldValidator ();
Emailvalidator.id = "Validator2";
Emailvalidator.controltovalidate = emailtextbox.id;
Emailvalidator.text = Emailerrormessage;
Emailvalidator.display = validatordisplay.static;
Submitbutton = new Button ();
Submitbutton.id = "Button1";
This. Controls.Add (Namelabel);
This. Controls.Add (nameTextBox);
This. Controls.Add (Namevalidator);
This. Controls.Add (Emaillabel);
This. Controls.Add (Emailtextbox);
This. Controls.Add (Emailvalidator);
This. Controls.Add (Submitbutton);
}
Overriding the Render method
protected override void Render (HtmlTextWriter writer) {
AddAttributesToRender (writer);
Writer. AddAttribute (htmltextwriterattribute.cellpadding, "1", false);
Writer. RenderBeginTag (htmltextwritertag.table);
Writer. RenderBeginTag (htmltextwritertag.tr);
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Namelabel.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Nametextbox.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Namevalidator.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderEndTag ();
Writer. RenderBeginTag (htmltextwritertag.tr);
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Emaillabel.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Emailtextbox.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Emailvalidator.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderEndTag ();
Writer. RenderBeginTag (htmltextwritertag.tr);
Writer. AddAttribute (Htmltextwriterattribute.colspan, "2", false);
Writer. AddAttribute (Htmltextwriterattribute.align, "right", false);
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Submitbutton.rendercontrol (writer);
Writer. RenderEndTag ();
Writer. RenderBeginTag (HTMLTEXTWRITERTAG.TD);
Writer. Write ("");
Writer. RenderEndTag ();
Writer. RenderEndTag ();
Writer. RenderEndTag ();
}
}
}
The source code for the Register of the composite control class is listed above. Although the code is a bit verbose, it is still relatively easy to understand. Figure 1 below lists the Register class structure chart.
Figure 1 class structure diagram
As Figure 1 and the code shows, the register class inherits from the CompositeControl base class, which implements 7 properties and 3 methods. Properties include ButtonText, Email, Emailerrormessage, Emaillabeltext, Name, Nameerrormessage, and Namelabeltext. By naming these attributes, it is believed that the reader can basically understand its meaning.
In addition, 3 methods from different objects are overridden in the Register class.
(1) The Render method is subordinate to the control base class, and in this case it is primarily defined in this method as HTML, which is related to the layout of the controls.
(2) The CreateChildControls method is subordinate to the control base class. In this example, the task of adding a child control to the composite control tree is implemented by overriding the method. Keep in mind that whenever you need to controls a collection, for example, during data binding (if applicable), the server control structure will depend on calls to CreateChildControls. To do this, you must add child controls to the CreateChildControls method.
(3) The Recreatechildcontrols method comes from the Icompositecontroldesigneraccessor interface of the CompositeControl base class. You can implement this method to enable the designer of a composite control to re-create the child controls of the control at design time.
The following is an enumeration of the Default.aspx page source code created for testing the Register control.
<%@ Page language= "C #" autoeventwireup= "true" codefile= "Default.aspx.cs" inherits= "_default"%>
<%@ Register tagprefix= "Sample" assembly= "Webcontrollibrary" namespace= "Webcontrollibrary"%>
! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en" "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<title> implement composite Control rendering </title>
<body>
<form id= "Form1" runat= "Server"
<div>
<sample:register id= "Demo1" runat= "Server" buttontext= "register" emaillabeltext= "e-mail" namelabeltext= "username" Emailerrormessage= "cannot be empty" nameerrormessage= "cannot be empty"/"
</div>
</form>
</body>
The example effect is shown in Figure 2.
Figure 2 Application Effect diagram
As shown in Figure 2, the register of composite controls displays text, text boxes, buttons, and so on in the page, and also provides input validation capabilities. However, when the user clicks the Register button, the page still does not raise the appropriate event handler even if the user name and e-mail input are validated. This is because the event-handling content of the button is not implemented in this example. The event implementation for the composite control is explained in more detail in the following article.
Summary
A composite control is a control that is created by aggregating other controls under a common API. The composite control retains the active instance of its own child controls, and is not limited to rendering those instances. Using a composite control can bring several benefits, such as simplifying the handling of events and postbacks. However, this article does not explain the event implementation of the composite control and other related content, please continue to focus on the following articles in this series.