ASP. NET custom controls fold panel custom controls on the fourth day

Source: Internet
Author: User
1. Introduction

In the previous tasks, we developed a star control and gradually added a new feature to it. In this task, we will develop a complicated custom control, this custom control needs to be used to fold the panel. You can add a widget to the panel control. After the widget is displayed, you can decide whether to display the hide button Based on your settings, if yes, you can click the expand/collapse button to show or hide the panel, and capture the expand/collapse event on the server side for more control. The control runs as follows:


2. Analysis

After determining that the control can be rendered in HTML, we should consider selecting a suitable base class for the custom control. From the perspective of functions to be implemented, the control is divided into two parts: one is the title line containing the expand/collapse button, and the other is the container containing the button placed by the user, obviously, this container can use the Panel class. In order to retain the feature of defining the Panel neutron tag directly by the user, the custom control can directly inherit from the Panel class and decide whether to display the title row based on the settings, in addition, an appropriate expand or collapse icon is displayed based on the panel status.

Since Panel can be regarded as a container control, what kind of results will be generated when Multiple widgets are used on the page? Can the sub-controls in the container be unique? You can try to write a custom control that inherits the custom panel class customercontrol and add a text box with the ID of TXT to its control set (CONTROLS attribute, when two such custom controls are placed on the page, two text boxes are generated (no doubt, because they are two custom controls), but their ID attributes are txt, similar to the followingCode:

<Span id = "PC3"> <input name = "TXT" type = "text" id = "TXT"/> </span>
<Span id = "CC2"> <input name = "TXT" type = "text" id = "TXT"/> </span>

To avoid this, you only need to make the customercontrol class implement the inamingcontainer interface. preview the page again and you will find that the generated text box has a unique ID:

<Span id = "PC3"> <input name = "PC3 $ TXT" type = "text" id = "ccw.txt"/> </span>
<Span id = "CC2"> <input name = "CC2 $ TXT" type = "text" id = "cc2_txt"/> </span>

Therefore, our custom controls also need to implement the inamingcontainer interface to ensure that all child controls have unique ID attributes. As you can see, you only need to mark the implementation of the inamingcontainer interface without writing any additional methods. This is the so-called "tag interface", and like this, there are iserializable and so on.

To make the folding control more flexible, developers are allowed to set whether the control can be expanded or collapsed. At the same time, you can write properties so that you can only perform the expand/collapse operation on the client without using the server-side submission method. You also need to be able to remember the expand/collapse status of the control even if you disable the view status. Therefore, you need to use the control status to save the status settings, finally, some additional attributes are provided to help you set the title style.

Therefore, the custom control should have the following attributes:

Attribute Description
Enabledropdown Whether to expand/collapse
Enableclientscript Whether to allow the use of client scripts to perform the expand/collapse action
Showexpanded Whether the initial status is expanded
Cpation Title
Captionbackcolor Title background color
Captionforecolor Title foreground

To trigger server-side events when users expand or collapse, you can simply use the server-side image button control to display the expand/collapse icon, when handling this server-side event, you may need to know the status of the current Panel (expand or collapse, you can simply use the Boolean variable identifier), and usually need an attribute of the event parameter to identify, however, the existing event parameter classes are not suitable for this function. Therefore, we also need to write our own event classes and define panel state attributes.

Events in. NET are based on delegation. in ASP. NET, you can use eventhandler delegation (which also defines generic delegation) to define events. event parameters include event-related data. For more information about delegation, events, and generics, see related books.

The last thing to consider is how to expose the event to developers if a server-side event is triggered by submitting the event. In fact, there are multiple implementation methods for this requirement:

    • Implement the ipostbackeventhandler interface to handle the send-back event.
    • Expose child control events as top-level events.
    • Use the Bubble Method to spread events along the include level to a proper position.

In this task, we will use the second method, and the other two methods will be described in future tasks. To expose a child control event as a top-level event, follow these steps:

    1. Define events for Custom Controls
    2. To ensure that the event has been subscribed to When triggered, write a secondary method to check whether the event is null)
    3. Write child control event processingProgramGenerate event parameters as needed to raise the event (call the auxiliary method in step 1) and execute other operations.

The above is the analysis of the panel control. Next we will implement the control according to the analysis results.

3. Implementation

3.1 Add the extendpanel class to the controllibrary class library of the solution and define related attributes based on the analysis:

Public class extendpanel: panel, inamingcontainer
{
[Themeable (false)]
Public bool enabledropdown
{
Get
{
Object o = viewstate ["enabledropdown"];
If (O = NULL)
Return false;
Return (bool) O;
}
Set {viewstate ["enabledropdown"] = value ;}
}

// Whether the client script is used
[Themeable (false)]
Public bool enableclientscript
{
Get
{
Object o = viewstate ["enableclientscript"];
If (O = NULL)
Return false;
Return (bool) O;
}
Set {viewstate ["enableclientscript"] = value ;}
}

// Whether it is expanded
[Themeable (false)]
Public bool showexpanded
{
Get
{
Object o = viewstate ["showexpanded"];
If (O = NULL)
Return true;
Return (bool) O;
}
Set
{
Viewstate ["showexpanded"] = value;
}
}

// Title
[Themeable (false)]
Public String Caption
{
Get
{
Object o = viewstate ["caption"];
If (O = NULL)
Return "Panel ";
Return (string) O;
}
Set {viewstate ["caption"] = value ;}
}

// Title background color
Public color captionbackcolor
{
Get
{
Object o = viewstate ["captionbackcolor"];
If (O = NULL)
Return color. skyblue;
Return (color) O;
}
Set {viewstate ["captionbackcolor"] = value ;}
}

// Title foreground
Public color captionforecolor
{
Get
{
Object o = viewstate ["captionforecolor"];
If (O = NULL)
Return color. White;
Return (color) O;
}
Set {viewstate ["captionforecolor"] = value ;}
}
}

Attributes such as enabledropdown are defined in the topic and do not affect the display style of the Control. Therefore, these attributes are defined using the themable feature, which specifies that the attributes are not affected by the appearance of the topic and control.

3.2 next, we will define a Boolean private variable to identify whether the current panel is in the expanded or collapsed State. To avoid the impact of the view State, we will store the attribute value in the control state:

Private bool _ paneldisplayed;

Protected override void oninit (eventargs E)
{
Base. oninit (E );
Page. registerrequirescontrolstate (this); // register the control status
}

Protected override object savecontrolstate ()
{
Pair P = new pair ();
P. First = base. savecontrolstate ();

P. Second = _ paneldisplayed;

Return P;
}

Protected override void loadcontrolstate (Object savedstate)
{
If (savedstate = NULL)
Return;

Pair P = (pair) savedstate;

Base. loadcontrolstate (P. First );

_ Paneldisplayed = (bool) p. Second;
}

3.3 override the createchildcontrols method and decide whether to display the title bar based on the enabledropdown attribute settings:

Protected override void createchildcontrols ()
{
If (enabledropdown) // If the drop-down is allowed, a title bar is created.
{
Base. createchildcontrols ();
Createcontrolhierarchy ();
}
Else
{
Base. createchildcontrols (); // If drop-down is not allowed, the original control is displayed.
}
}

3.4 The createcontrolhierarchy method is called in the createchildcontrols method to create a child control hierarchy. This method first performs two operations, creates a table, and adds the title and operation icon of the first row; add the control in the original panel container to the second row of the table, add the table to the control set, and clear the original control:

 protected virtual void createcontrolhierarchy () 
{< br> table t = new table ();
tablerow row1 = new tablerow ();
T. rows. add (row1);
tablecell cell1 = new tablecell ();
row1.cells. add (cell1);
cell1.text = "& nbsp;" + Caption;
tablecell cell2 = new tablecell ();
row1.cells. add (cell2);
cell2.horizontalalign = horizontalalign. right;
tablerow row2 = new tablerow ();
T. rows. add (row2);
tablecell body = new tablecell ();
body. id = "body";
row2.cells. add (body);
body. columnspan = 2;
Control [] Rg = new control [controls. count];
controls. copyto (RG, 0);
foreach (control CTL in RG)
body. controls. add (CTL);
controls. clear ();
controls. add (t);

Because the control on the server side is of reference type, you must call controls instead of directly adding the control to a control set. copyto copies the original control to the target control array. Otherwise, the controls is called. when the clear method is used, the control is still removed, resulting in incorrect running results.

3.5 next, in this method, determine whether to use the enableclientscript attribute. If this attribute is set to false, it indicates that the server submits the request, therefore, add the server-side image button to the cell in the row header and process the Click Event of the control (the event handler will be implemented later ):

Webcontrol IMG;
If (! Enableclientscript)
{
IMG = new imagebutton ();
(Imagebutton) IMG). Click + = new imageclickeventhandler (onclick );
Cell2.controls. Add (IMG );
}

3.6 if the show/hide action is performed on the client, the client script is registered on the page and appended to the Click Event of the icon:

Else
{
IMG = new system. Web. UI. webcontrols. Image ();
IMG. ID = "icon ";
Cell2.controls. Add (IMG );

// Add a style
IMG. attributes ["onmouseover"] = "This. style. cursor = \" hand \";";
IMG. attributes ["onmouseout"] = "This. style. cursor = \"\";";
IMG. attributes ["onclick"] = "_ toggle ()";
If (! Page. clientscript. isclientscriptblockregistered ("_ toggle "))
{
String JS = buildscript (body );
Page. clientscript. registerclientscriptblock (this. GetType (), "_ toggle", JS, true );
}
}

In the above code snippet, The buildscript method is called to generate a Javascript script. The following is the implementation of this method (of course, you can use a resource file ):

Private string buildscript (tablecell body)
{
Stringbuilder sb = new stringbuilder ();
SB. appendline ("function _ toggle (){");
SB. appendformat ("Var body = Document. getelementbyid (\" {0} \ "); \ r \ n", body. clientid );
SB. appendline ("Var display = body. style. display ;");
SB. appendline ("If (display = \"\"){");
SB. appendline ("body. style. Display = \" None \";");
SB. appendline ("} else {");
SB. appendline ("body. style. Display = \"\";");
SB. appendline ("}");
SB. appendline ("}");

Return sb. tostring ();
}

3.7 at the end of the createcontrolhierarchy method, two methods are called:

Showchildcontrols (_ paneldisplayed );
Showimagebutton (_ paneldisplayed );
}

3.8 implement the showchildcontrols method to display or hide the panel content:

 
Private void showchildcontrols (bool display)
{
If (controls. Count! = 1)
Return;

Table t = (table) controls [0];
Tablerow r = T. Rows [1];
Tablecell body = R. cells [0];
Body. Style ["display"] = (display? "": "NONE ");
}

3.9 place the collapse.bmp and expand.bmp images to this directory in the controllibraryclass directory, set the generated action to embed and add resource file registration in assemblyinfo. CS to display the appropriate icons Based on the panel status:

Private void showimagebutton (bool display)
{
If (controls. Count! = 1)
Return;

Table t = (table) controls [0];
Tablerow r = T. Rows [0];
Tablecell icon = R. cells [1];

// Set the corresponding image
System. Web. UI. webcontrols. Image IMG =
(System. Web. UI. webcontrols. Image) icon. controls [0];

String imagename = "controllibrary.image.expand.bmp ";
If (display &&! Enableclientscript)
Imagename = "controllibrary.image.collapse.bmp ";
IMG. imageurl = page. clientscript. getwebresourceurl (this. GetType (),
Imagename );
}

3.10 next, we will handle server-side click events. First, we will use generic delegation to declare events in the extendpanel class. This generic delegation means that panelclickeventargs is used as the event parameter type, and the class must inherit from eventargs class:

 
Public event eventhandler <panelclickeventargs> panelclick;

Define the panelclienteventargs event parameter class and add the beingclosed attribute to identify the Panel status:

Public class panelclickeventargs: eventargs
{
Public bool beingclosed
{
Get;
Set;
}
}

3.11 According to the analysis of the custom control event, define the auxiliary method in the extendpanel class to check whether the event has been subscribed:

 
Protected virtual void onpanelclick (panelclickeventargs ARGs)
{
If (panelclick! = NULL)
Panelclick (this, argS );
}

3.12 when the server-side image button is triggered to click an event, the onpanelclick method is called after the event parameter class is generated in onclick, and the Panel and Icon display are updated, in this way, the subscribed event handler can participate in the image Button clicking process:

 
Private void onclick (Object sender, imageclickeventargs E)
{
Panelclickeventargs ARGs = new panelclickeventargs ();
Args. beingclosed = _ paneldisplayed;
Onpanelclick (ARGs );






// Update the display status
_ Paneldisplayed =! _ Paneldisplayed;

Showchildcontrols (_ paneldisplayed );
Showimagebutton (_ paneldisplayed );
}

3.13 rewrite the render method to display the control. This method calls the preparentcontrolforrendering method to apply the style of the control to the created table and set the foreground color and background color of the title based on the property:

 
Protected override void render (htmltextwriter writer)
{
Preparecontrolforrendering ();
Base. Render (writer );
}

Protected virtual void preparecontrolforrendering ()
{
If (controls. Count! = 1)
Return;

// Apply the style
Table t = (table) controls [0];
T. copybaseattributes (this );
If (controlstylecreated)
T. applystyle (controlstyle );

T. cellpadding = 1;
T. cellspacing = 0;

// Set the title Style
Tablerow row1 = T. Rows [0];
Row1.backcolor = captionbackcolor;
Row1.forecolor = captionforecolor;
}

3.14 create a test page on the web site of the solution, declare and define custom panel controls, and test the running results.

4. Summary

In this task, we created a user-defined panel control that can be folded/expanded, and applied the eventhandler generic delegation and Custom Event class to publish the image click event as the top-level event of the Panel, in this way, users can subscribe to this event for custom processing. The two important attributes of the panel control are enabledropdown and enableclientscript. The former determines whether to display the additional title bar, and the latter determines whether to generate a Javascript script to expand/collapse on the client, or use the image button to process server click events. If you click an event to submit it to the server for processing, you can use the Custom Event class to save the Panel status, and the Click Event of the image button triggers the Panel top-level event, so that you can customize the processing of click events.

In the next task, we will introduce another method of event processing-using the iposteven thandler interface to add the scoring function based on the original Star control, allows users to freely select scores and trigger server events to get scores selected by users.

ASP. NET Custom ControlsArticle

Preface

Simple star control on the first day

Star controls with custom styles the next day

On the third day, use the star widget in the control status.

Fold panel custom controls on the fourth day

Star controls that can be scored on the fifth day

Star controls that can be bound to data sources on the sixth day

Develop list controls with rich features on the seventh day

Metric days: displays the data binding controls for multiple entry star rating

The ninth day custom gridview

Datalist that implements the paging function on the tenth day

Download all source code

download this series of articles in PDF

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.