ASP. NET control development quick tutorial: generate a Composite Control

Source: Internet
Author: User
ASP. NET control development quick tutorial: generate a Composite Control From msdn



Release date: 2006-6-24 | Updated on: 2006-6-24


Applicable:
Microsoft ASP. Network 2.0
Visualized basic 2005
Visual C #2005
. Net frameworks
Visual Web Developer 2005



Abstract:Dino Esposito has been writing a series of tutorials on ASP. NET control development, and describes how to use and create a composite control in the fourth section below.



With Visual BasicAnd C #Two TypesSource code. Please referHereDownload.


Content on this page


Introduction
What are the key points of a composite control?
Common solutions for composite controls
Rendering Engine of composite controls
Compositecontrol for Solving Design Issues
Generate a Data Binding Composite Control
Conclusion


Introduction


Composite controls are just common ASP. NET controls and are not another type of ASP. NET Server controls to be discussed. In this case, why do we always set aside special chapters in books and documents to discuss composite controls? What are the special features of ASP. NET composite controls?



As the name suggests, a composite control is a control that aggregates multiple other controls on a single top and under a single API. If a custom control consists of a label and a text box, it can be said that the control is a composite control. The word "composite" indicates that the control is essentially composed of other components at runtime. The method set and attribute set exposed by the composite control are usually (but not mandatory) provided by the methods and attributes that constitute the component, and some new members are added. Composite controls can also trigger custom events and process events caused by child controls.



Composite controls are not so special in ASP. NET because they may be representative of new types of server controls. More specifically, it is because it is supported by ASP. NET runtime during rendering.



Composite controls are powerful tools that can generate rich and complex components that generate the interaction of Self-active objects rather than the markup output of some string generator objects. A composite control is displayed as a control tree. Each component control has its own lifecycle and events, and all components constitute a new API, and abstract as much as possible as needed.



In this article, I will discuss the internal architecture of composite controls to illustrate the benefits it brings to you in many situations. Next, I will generate a composite list control with my previousArticleThe function set of the Control described in is richer than that of the control.


What are the key points of the composite control?


Some time ago, I tried to study composite controls in ASP. NET. I learned theoretical and practical knowledge from the msdn document, and also designed some good controls. However, only when I saw the following example by accident did I really understand the main points (and advantages) of the composite control ). Assume that two other widgets (LabelAndTextbox. The following describes a feasible method for writing this control. We name itLabeltextbox.


public class LabelTextBox :WebControl, INamingContainer
{
public string Text {
get {
object o = ViewState["Text"];
if (o == null)
return String.Empty;
return (string) o;
      }
set { ViewState["Text"] = value; }
   }
public string Title {
get {
object o = ViewState["Title"];
if (o == null)
return String.Empty;
return (string) o;
      }
set { ViewState["Title"] = value; }
   }
protected override void CreateChildControls()
   {
Controls.Clear();
CreateControlHierarchy();
ClearChildViewState();
   }
protected virtual void CreateControlHierarchy()
   {
TextBox t = new TextBox();
Label l = new Label();
t.Text = Text;
l.Text = Title;
Controls.Add(l);
Controls.Add(t);
   }
}


The control has two common attributes (TextAndTitle) And a rendering engine. These two attributes are saved in the view State and representTextboxAndLabel. This controlRenderMethod is not replaced, andCreatechildcontrolsTo generate its own tag. I will describe the routine process of the presentation phase immediately.CreatechildcontrolsOfCodeFirst, clear the collection of child controls, and then generate a control tree for the components output by the current control.CreatecontrolhierarchyIs a control-specific method that is not required to be marked as protected or virtual. However, note that most built-in composite controls (for exampleDataGridOnly exposes the logic used to generate the control tree through a similar virtual method.



CreatecontrolhierarchyThe method instantiate multiple components as needed and then synthesize the final output. After that, the widgets are added toControlsSet. If you want the output result of the control to be an HTML table, you can createTableControl, and Add rows and cells with their own content. All rows, cells, and controls are the child items of the most external table. In this case, you only needTableAdd controlControlsSet. In the above Code, label and textbox areLabeltextboxAnd add them to the set directly. The display status and running status of the control are normal.



In terms of performance, creating a transient instance of a control is not as efficient as rendering some plain text. Let's consider an alternative method to write the above controls without the need for child controls. This time let's name itTextboxlabel.


 



public class LabelTextBox :WebControl, INamingContainer
{
   :
protected override void Render(HtmlTextWriter writer)
   {
string markup = String.Format(
"<span>{0}</span><input type=text value='{1}'>",
Title, Text);
writer.Write(markup);
   }
}


The control has the same two attributes (TextAndTitle) And replacedRenderMethod. As you can see, the implementation process is quite simple and the code runs faster. You can replace the synthetic child control by merging text in the string generator and outputting final markup for the browser. Similarly, the control is in good state. But can we really say that its running status is also good? Figure 1 shows the two widgets running on the example Page.





Figure 1: similar controls using different rendering engines


Enable the tracking function on the page and run it again. When the page is displayed in the browser, scroll down and view the control tree. It will be as follows:





Figure 2: Control tree generated by two controls


A composite control is composed of activity instances of components. When ASP. NET is running, these sub-controls are found and can be directly communicated with them when processing published data. The result is that the sub-control can process the view status and automatically trigger events.



For tag-based Merging controls, the situation is different. As shown in, this control is nullControlsThe basic unit of code in the set. If an interactive element (text box, button, or drop-down menu) is injected into the page, ASP. NET cannot process the send-back data and events without the control.



Try to enter some text in the two text boxes and click the "refresh" button in figure 1 to initiate a resend. The first control (Composite Control) correctly retains the allocated text after sending it back. UseRenderThe second control of the method will lose New text after sending it back. Why? There are two reasons.



The first reason is that<Input>Mark the name. In this way, its content will not be sent back. Note that you must useNameAttribute to name the element. Let'sRenderThe method is modified as follows.


 



protected override void Render(HtmlTextWriter writer)
{
string markup = String.Format(
"<span>{0}</span><input type=text value='{1}' name='{2}'>",
Title, Text, ClientID);
writer.Write(markup);
}


Inject<Input>The element now uses the same ID as the server control. During page sending, a server control that matches the ID of the published field can be found during ASP. NET running. But it does not know how to deal with the control. To apply all client changes to the server control in ASP. NET, the control must be implemented.IpostbackdatahandlerInterface.



IncludeTextboxComposite Control does not need to worry about sending back, because the embedded control uses ASP. NET to automatically solve this problem. RenderingTextboxThe control must interact with ASP. NET to ensure that the return value can be correctly processed and the event is triggered normally. The following code shows how to scaleTextboxlabelControl to make it fully support sending back.


 



bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
string currentText = Text;
string postedText = postCollection[postDataKey];
if (!currentText.Equals(postedText, StringComparison.Ordinal))
    {
Text = postedText;
return true;
    }
return false;
}
void IPostBackDataHandler.RaisePostDataChangedEvent()
{
return;
}
Back to Top: common solutions for composite controls


Composite controls are suitable for building complex components. In composite controls, multiple child controls are aggregated and interacted with each other and with the outside. The Rendering Control is only used for read-only control aggregation. Its output does not include interactive elements (such as drop-down boxes or text boxes ).



If you are interested in event processing and sending back data, I strongly recommend that you select a composite control. If a child control is used, it is easier to generate a complex control tree and the final result is clearer and more concise. In addition, the interface for sending back must be processed only when additional functions are required.



The rendering control not only requires the implementation of additional interfaces, but also the static part of the tag containing the property value.



The advantages of the composite control are that multiple similar items can be displayed.DataGridThe condition in the control is similar. Enabling each component as an activity object enables you to trigger Creation events and programmatically access their properties. In ASP. NET 2.0, most of the sample code required to fully implement the actual data binding composite controls (the above control is just an example) are hidden in the folding part of the new base class:Compositedataboundcontrol.


Back to header: rendering engine of the Composite Control


Before in-depth discussion of ASP. NET 2.0 encoding technology, let's review the internal routine process of the composite control. As we mentioned, the composite control is centered aroundCreatechildcontrolsMethod.ControlThe base class. You may think that to make the server control display its content, replaceRenderMethods are an essential step. As we have seen before, ifCreatechildcontrolsThis step is not always required. However, when to call in the control call stackCreatechildcontrolsWhat about it?



As shown in, when the page is displayed for the first time, it is called in the pre-rendering stage.Createchildcontrols.





Figure 3: createchildcontrols is called in the pre-presentation phase


In particular, the request processing code (inPageClass) inPrerenderBefore the event is triggered to the page and each sub-control, it is called directly.Ensurechildcontrols. In other words, if the control tree is not completely generated, no control is displayed.



The following code snippet demonstratesEnsurechildcontrols(InControlBased on the definition of another method.


 



protected virtual void EnsureChildControls()
{
if (!ChildControlsCreated)
   {
try {
CreateChildControls();
       }
finally {
ChildControlsCreated = true;
       }
   }
}


This method may be called repeatedly during the lifecycle of pages and controls. To avoid repeated controls,ChildcontrolscreatedProperty is setTrue. If this property is returnedTrue, The method exits immediately.



When the page is sent back,ChildcontrolscreatedIt will be called before the cycle. 4. It is called in the released data processing stage.





Figure 4: Call in the released data processing phase when sending back


When the ASP. NET page starts to process data published from the client, it will try to find a server control whose ID matches the name of the published field. During this step, the page code will callControlClassFindcontrolMethod. Otherwise, this method must ensure that the control tree has been fully generated before the operation, so it callsEnsurechildcontrolsAnd generate the control hierarchy as needed.



InCreatechildcontrolsHow is the code executed inside the method? Although there is no formal guide to follow, it is generally consideredCreatechildcontrolsAt least the following tasks must be completed: ClearControlsSet to generate the control tree and clear the view status of the child control. Not strictly requiredCreatechildcontrolsInternal method settingsChildcontrolscreatedAttribute. In fact, the ASP. NET page framework always passes throughEnsurechildcontrols(This method can automatically set a Boolean flag) to callCreatechildcontrols.


Back to Top: compositecontrol used to solve Design Problems


Along with ASP. NET 2.0,Compositecontrol. Therefore, the new non-data-bound composite control should be derived from this class rather than fromWebcontrol. In terms of development controls,CompositecontrolThe usage has not changed much. You still need to replaceCreatechildcontrolsAnd encoded as described earlier. SoCompositecontrolWhat is the role? Let's start with its prototype:


 



public class CompositeControl :WebControl, 
INamingContainer, 
ICompositeControlDesignerAccessor


This class does not need to be reused.InamingcontainerDecoration controls, but this is not really important, because the interface is just a tag and does not contain any method. More importantly, this class implementsIcompositecontroldesigneraccessor.


 



public interface ICompositeControlDesignerAccessor
{
void RecreateChildControls();
}


This interface is used by the standard designer of the Composite Control to recreate the control tree during design. Below isCompositecontrolThe default implementation process of the method in.


 



void ICompositeControlDesignerAccessor.RecreateChildControls()
{
base.ChildControlsCreated = false;
EnsureChildControls();
}


In short, if youCompositecontrolIf a composite control is derived, it will not encounter design faults, and the control can run properly at runtime and design without the use of skills and tricks.



To fully understand the importance of this interface, you can try to storeLabeltextboxTake the example Page of the composite control as an example and convert it to the design mode. The control works normally during operation, but is invisible during design.





Figure 5: Only compositecontrol controls are derived from compositecontrol for special design-time processing.


If you only useCompositecontrolReplaceWebcontrol, The control continues to work normally during operation, and will also run well during design.





Figure 6: Composite controls that work well at design Back to the top page to generate a Data Binding Composite Control


Most complex server controls are bound to data (or templated) and are composed of various seed controls. These controls retain a list of components (usually the rows or cells of the table. After sending the list back, it is saved in the view State and generated from the bound data or rebuilt from the view State. This control also saves the number of its constituent items in the view State, so that the table structure can be correctly rebuilt when other controls on the page cause a return. I will useDataGridControls.



DataGridA row is composed of one column. Each row represents a record bound to the data source. Each grid row usesDatagridrowObject (fromTablerowA derived class. When the grid rows are created and added to the final grid table, suchItemcreatedAndItemdataboundSuch events will be triggered to the page. When created through data bindingDataGridThe number of lines is determined by the number of bound items and page size. IfDataGridPage sending back?



In this caseDataGridFor example, if the user clicks to sort or mark the page, the new page is displayed again through data binding.DataGrid. This is obvious, becauseDataGridYou need to refresh the data for display. For homepage sending back, the situation is different, because another control (such as a button) on the page is clicked ). In this case,DataGridIt is not bound to data and must be rebuilt from the view status. (If the view status is disabled, it is another case. In this case, you can only bind the data to display the grid .)



The data source is not saved in the view State. As a composite control,DataGridContains sub-controls. Each sub-control saves its own state to the view State and restores it from the view State.DataGridYou only need to track the number of times it must be repeated before all rows and controls are restored from the view State. This number is the same as the number of bound items displayed, and must be stored as part of the control status to the view status. In ASP. NET 1.x, you must learn and implement this mode on your own. In ASP. NET 2.0, the new classCompositedataboundcontrolYou can derive your composite control.



Let's try to use a grid-like control that displays extensible data bound to a news title line. In this process, we will re-useHeadlineControl.


 



Public class headlinelistex: compositedataboundcontrol {:}


HeadlinelistexControl contains a collection of all bound data itemsItemsSet attributes. This set is a public set and can be filled in programmatically when running with most list controls. The support for typical data binding is through a pair of attributes (DatatextfieldAndDatatitlefield. These two attributes indicate fields in the data source that will be used to fill the news title and text.ItemsThe set is saved to the view State.



ToHeadlinelistexTo convert a widget to a real composite widget, you must firstCompositedataboundcontrolAnd then replaceCreatechildcontrols. Interestingly, you will notice thatCreatechildcontrolsIs the overload method.


Override int createchildcontrols () override int createchildcontrols (ienumerable data, bool databinding)


The first overload method replacesControlClass. The second overload method is an abstract method that must be replaced by each composite control. In fact, the development of composite controls is simplified to two main tasks:


    • ReplaceCreatechildcontrols.

    • ImplementationRowsSet Properties to track all components of the control.


RowsDifferent fromItemsBecause it is not stored in the view State and has the same lifetime as the request, and reference the helpProgramObject instead of Binding data items.


 



public virtual HeadlineRowCollection Rows
{
get
    {
if (_rows == null)
_rows = new HeadlineRowCollection();
return _rows;
     }
}


RowsThe set is filled when the control is generated. Let's take a look.Createchildcontrols. This method uses two parameters: the binding item and a Boolean tag. The Boolean tag indicates whether the control is created by data binding or by view status. (Note that the programmer comments in the example program file are in English. In this document, they are translated into Chinese for reference .)


override int CreateChildControls (IEnumerable dataSource, bool dataBinding)
{
if (dataBinding)
    {
string textField = DataTextField;
string titleField = DataTitleField;
if (dataSource! = null)
       {
foreach (object o in dataSource)
          {
HeadlineItem elem = new HeadlineItem ();
elem.Text = DataBinder.GetPropertyValue (o, textField, null);
elem.Title = DataBinder.GetPropertyValue (o, titleField, null);
Items.Add (elem);
          }
       }
    }

// Start generating control hierarchy
Table t = new Table ();
Controls.Add (t);
Rows.Clear ();
int itemCount = 0;

foreach (HeadlineItem item in Items)
    {
HeadlineRowType type = HeadlineRowType.Simple;
HeadlineRow row = CreateHeadlineRow (t, type,
item, itemCount, dataBinding);
_rows.Add (row);
itemCount ++;
     }

return itemCount;
}


When binding data, you must first fill in the items set. Traverse the bound set, extract data, and then fillHeadlineitemClass. Next, traverse the items set (this set may contain additional items that are added programmatically) and create a line in the control.


HeadlineRow CreateHeadlineRow (Table t, HeadlineRowType rowType,
HeadlineItem dataItem, int index, bool dataBinding)
{
// create a new row for the outermost table
HeadlineRow row = new HeadlineRow (rowType);

// create cells for child controls
TableCell cell = new TableCell ();
row.Cells.Add (cell);
Headline item = new Headline ();
cell.Controls.Add (item);

// HeadlineRowCreated event is raised

// add this row to the created HTML table
t.Rows.Add (row);

// Handle data object binding
if (dataBinding)
    {
row.DataItem = dataItem;
Headline ctl = (Headline) cell.Controls [0];
ctl.Text = dataItem.Text;
ctl.Title = dataItem.Title;
                
// HeadlineRowDataBound event is raised
     }
return row;
}


CreateheadlinerowMethod will be created and returnHeadlinerowClass (fromTablerowDerived from. In this case, this row containsHeadlineControl filled cells. In other cases, you can change this part of code to add multiple cells as needed and fill the content accordingly.



It is important to divide the tasks to be completed into two different steps: Creation and data binding. First, create a row layout, raise the row creation event (if any), and add it to the parent table. Next, if you want to bind the control to data, set the attributes of the Child control that is sensitive to data binding. After the operation is completed, a row data binding event is triggered (if any ).



Note that this mode accurately describes the internal architecture of ASP. NET composite controls.



You can use the following code to raise an event.


 



HeadlineRowEventArgs e = new HeadlineRowEventArgs();
e.DataItem = dataItem;
e.RowIndex = index;
e.RowType = rowType;
e.Item = row;
OnHeadlineRowDataBound(e);


Note that this parameter is set only when a data binding event is triggered.DataitemAttribute. The event data structure is set as follows. If you think it is necessary, do your best to change it.


 



public class HeadlineRowEventArgs :EventArgs
{
public HeadlineItem DataItem;
public HeadlineRowType RowType;
public int RowIndex;
public HeadlineRow Item;
}


To actually trigger an event, we usually use a protected method as defined below.


 



protected virtual void OnHeadlineRowDataBound(HeadlineRowEventArgs e)
{
if (HeadlineRowDataBound != null)
HeadlineRowDataBound(this, e);
}


To declare this event, you can use the new general event handler delegate in ASP. NET 2.0.

public event EventHandler <HeadlineRowEventArgs> HeadlineRowDataBound;
In the example page, everything works as usual. You can define a handler on a control tag and write a method to a code file. An example is shown below.

<cc1: HeadlineListEx runat = "server" ID = "HeadlineListEx1"
DataTextField = "notes" DataTitleField = "lastname"
DataSourceID = "MySource" OnHeadlineRowDataBound = "HeadlineRowCreated" />
The code for the HeadlineRowCreated event handler is shown below.

protected void HeadlineRowCreated (object sender, HeadlineRowEventArgs e)
{
if (e.DataItem.Title.Contains ("Doe"))
e.Item.BackColor = Color.Red;
}
Figure 7: HeadlineListEx control in action
By hooking data binding events, all items containing Doe will be rendered with a red background.

Back to top Conclusion
A composite control is a control created by aggregating other controls under a common API. Compound controls retain the active instances of their child controls and are not limited to rendering those instances. You can easily see this by examining the control tree section in the page trace output. There are several benefits to using composite controls, such as simplifying the handling of events and postbacks. Generating complex data-bound controls in ASP.NET 1.x is a bit tricky and requires you to dive into some implementation details. With the introduction of the CompositeDataBoundControl base class, this complexity can basically be solved in ASP.NET. Finally, if you need a non-data-bound composite control in ASP.NET 2.0, you can use the CompositeControl base class. For data-bound composite controls, you can consider CompositeDataBoundControl instead. In either case, you must provide a valid replacement method for CreateChildControls, which is the core of all composite controls for creating child control hierarchies.

About the Author

Dino Esposito is a consultant for Solid Quality Learning and author of "Programming Microsoft ASP.NET 2.0" (Microsoft Press, 2005). Dino lives in Italy and frequently comment on industry events worldwide. Please contact cutting@microsoft.com or join the blog at http://weblogs.asp.net/despos.

Go to original English page

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.