Generate a Data Binding ASP. NET 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 rows or cells that normally constitute a 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. The DataGrid control is used as an example.
A DataGrid consists of one row. Each row represents a record bound to the data source. Each grid row is represented by a class derived from TableRow by a DataGridRow object. When a grid row is created and added to the final grid table, events such as ItemCreated and ItemDataBound are triggered to the page. When you create a DataGrid through data binding, the number of rows is determined by the number of bound items and page size. What if a page with a DataGrid is sent back?
In this case, if the response is caused by the DataGrid itself, for example, the user clicks to sort or label the page), the new page will be displayed through data binding again. This is obvious, because the DataGrid needs to refresh the data for display. For homepage sending back, the situation is different, because another control on the page, such as a button, is clicked ). In this case, the DataGrid is not bound to the data and must be rebuilt from the view State. If the view status is disabled, the display grid can only be displayed through data binding .)
The data source is not saved in the view State. As a composite control, the DataGrid contains child controls. Each child control saves its own state to the view State and restores it from the view State. The DataGrid only needs 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, You can derive your composite control from the CompositeDataBoundControl class.
Let's try to use a grid-like control that displays extensible data bound to a news title line. In this process, we will use the Headline control discussed previously.
- public class HeadlineListEx :CompositeDataBoundControl
- {
- :
- }
The HeadlineListEx control contains an Items set property that collects all bound data Items. 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 achieved through a pair of attribute DataTextField and DataTitleField. These two attributes indicate fields in the data source that will be used to fill the news title and text. The Items set is saved to the view State.
To convert the HeadlineListEx control to a real ASP. NET Composite Control, you must first derive it from CompositeDataBoundControl and then replace CreateChildControls. Interestingly, you will notice that CreateChildControls is an overload method.
- override int CreateChildControls()
- override int CreateChildControls(IEnumerable data, bool dataBinding)
The first overload method replaces the method defined in the Control class. 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:
Replace CreateChildControls.
Implement the Rows set attribute to track all components of the control.
The Rows attribute is different from the Items attribute because it is not stored in the view State and has the same lifetime as the request, and references the help program object instead of Binding data Items.
- public virtual HeadlineRowCollection Rows
- {
- get
- {
- if (_rows == null)
- _rows = new HeadlineRowCollection();
- return _rows;
- }
- }
The Rows set is filled when the control is generated. Let's take a look at the CreateChildControls replacement method. 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 IntCreateChildControls (IEnumerable dataSource,BoolDataBinding)
- {
- If(DataBinding)
- {
- StringTextField = DataTextField;
- StringTitleField = DataTitleField;
- If(DataSource! =Null)
- {
- Foreach(ObjectOInDataSource)
- {
- HeadlineItem elem =NewHeadlineItem ();
- Elem. Text = DataBinder. GetPropertyValue (o, textField,Null);
- Elem. Title = DataBinder. GetPropertyValue (o, titleField,Null);
- Items. Add (elem );
- }
- }
- }
-
- // Start generating the control hierarchy
- Table t =NewTable ();
- Controls. Add (t );
- Rows. Clear ();
- IntItemCount = 0;
-
- Foreach(HeadlineItem itemInItems)
- {
- HeadlineRowType type = HeadlineRowType. Simple;
- HeadlineRow row = CreateHeadlineRow (t, type,
- Item, itemCount, dataBinding );
- _ Rows. Add (row );
- ItemCount ++;
- }
-
- ReturnItemCount;
- }
-
When binding data, you must first fill in the Items set. Traverse the bound set, extract data, and then fill in the new instance of the HeadlineItem class. Next, traverse the Items set. This set may contain additional Items that are added programmatically.
- HeadlineRow CreateHeadlineRow (Table t, HeadlineRowType rowType,
- HeadlineItem dataItem,IntIndex,BoolDataBinding)
- {
- // Create a new row for the most external table
- HeadlineRow row =NewHeadlineRow (rowType );
-
- // Create a cell for the Child Control
- TableCell cell =NewTableCell ();
- Row. Cells. Add (cell );
- Headline item =NewHeadline ();
- Cell. Controls. Add (item );
-
- // The HeadlineRowCreated event is triggered.
-
- // Add this row to the created HTML table
- T. Rows. Add (row );
-
- // Bind the processing data object
- If(DataBinding)
- {
- Row. DataItem = dataItem;
- Headline ctl = (Headline) cell. Controls [0];
- Ctl. Text = dataItem. Text;
- Ctl. Title = dataItem. Title;
- // The HeadlineRowDataBound event is triggered.
- }
- ReturnRow;
- }
-
The CreateHeadlineRow method creates and returns an instance of the HeadlineRow class derived from TableRow. In this case, the row contains a cell filled with the Headline control. 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 the DataItem attribute is set only when a data binding event is triggered. 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;
On the example Page, everything is executed as usual. You can define the handler on the control tag and write a method to the code file. Example.
- < cc1:HeadlineListEx runat="server" ID="HeadlineListEx1"
- DataTextField="notes" DataTitleField="lastname"
- DataSourceID="MySource" OnHeadlineRowDataBound="HeadlineRowCreated" />
The code of the HeadlineRowCreated event handler is as follows.
- protected void HeadlineRowCreated(object sender, HeadlineRowEventArgs e)
- {
- if (e.DataItem.Title.Contains("Doe"))
- e.Item.BackColor = Color.Red;
- }
-
Figure 7: Running HeadlineListEx Control
By mounting a Data Binding event, all items containing Doe are displayed in a red background.
- ASP. NET composite controls and CompositeControl
- Rendering Engine of ASP. NET composite controls
- Overview of ASP. NET composite controls
- Analysis on Composite Control Event Processing Based on ASP. NET control development
- Analysis of compound controls based on ASP. NET control development