Custom C# ASP.NET webcontrols
A couple of months back I developped a set of custom webcontrols for a friend's website:
- a selector control to select multiple entries from a list easily,
- and a context menu control that can be binded to other controls.
You can try demos here:
- Selector,
- ContextMenu,
- Selector with a ContextMenu.
I think they are a pretty good introduction to anyone trying to develop custom webcontrols, as they explore many of the aspects of the framework. The source for the demos above is available here (cvsweb) and as a zip file.
Although I didn't spend the time to make them look pretty, their display is entirely customizable thru CSS, as the html only contains a couple of divs with CSS classes attributes.
Update: the demos are back online, from my desktop box. They will be broken again during the month of November, as I'll be moving during that time.
Introduction
ASP.NET has a pretty nice framework to componentize web pages. It's based on the concept of webcontrols, which are classes that encapsulate both the UI and the logic behind UI items like button, dropdowns or input fields. They not only offer an programmatic API that allows the request handling code (called codebehind) to access them at runtime, they also bring server-side events and callback that represent client-side action from the user.
The SDK comes with a set of predefined classes for most of the standard html items. But the framework is also extensible.
Webcontrol lifecycle
The heart of the webcontrol paradigm is the lifecyle these server controls follow, from handling postback data to rendering themselves. Here are the steps of a control's life. You'll find further reference on MSDN.
Initializing
This is the first chance to customize the behavior of the control after the client request has come in. The OnInit() method allows the developper to set up some initial state.
Loading ViewState
Right after the control is initialized, it is populated with the values (if any) that it previously contained (during the previous request) and were saved in the ViewState. A webcontrol uses the LoadViewState() method to customize this process.
The ViewState is an StateBag object that is saved in an optionnally encrypted hidden form field (__VIEWSTATE) that the framework automatically adds to your html form to maintain data client-side from a request to the next.
For example, a text input control could load it's previous value, so that any changes done by the user could be detected during postback data processing.
Processing Postback data
If the control implements the IPostBackDataHandler interface, it can process whatever data was posted to update it's state.
For example, if the user selects a checkbox input and posts the form, the checkbox server control can look through the post data and update itself to be selected.
Loading
The Load() method is called when the server control is loaded into the Page object.
Sending Postback Change Notification
If the control implements the IPostBackDataHandler interface, it can raise some events to notify other controls from the change in state.
Handling Postback Events
The client-side event that triggered the postback can be handled here. For example, RaisePostBackEvent() is the method where a button control would raise the server-side "OnClick" event, for the form code to handle the button click.
Pre-rendering
Occurs when the server control is about to render to its containing Page object. This is a good place to register any common block of client script, via RegisterClientScriptBlock.
Saving ViewState
The SaveViewState() method is the last opportunity for the server control to save it's state, before the __VIEWSTATE hidden form control is written.
Only certain types of data can natively be saved in the ViewState (strings, integers, arrays, hashtables and a couple more).
Rendering
The control renders whatever is sent back to the client, by overriding the Render() method.
More advanced topics
Other types of server controls are available, like Templated controls (for example, the Repeater) and Composite controls (you can author new controls by combining existing controls using class composition).
I haven't played with either of these, so I can't go in any details.
Other topics I hope I'll can dig some more into are Custom Control Builders (that dictate how tags with a runat=server are processed during the parsing of the page) and Design-Time support (have your custom webcontrol integrate nicely in VS.net).
The main reference page for developing ASP.NET server controls.
You can also read the docs and source code for some IE webcontrols (TreeView, MultiPage, ToolBar, and TabStrip), shared by Microsoft.
A great (the best?) reference book on the subject Professional ASP.NET Server Controls (Building Custom Controls with C#).
Future custom server controls
Here are a couple ideas I have for future week-end projects:
Ordered list control
It'll allow to re-order a list of items easily, for example a list of mp3s.
Smart completion drop-down
A drop-down that would pull results dynamically from the server, based on partial match, using remote javascript. DBCombo is very similar to what I would like to do.
Links
A great article on the ViewState
Some nice slides from TechEd on custom webcontrols:
http://www.nikhilk.net/Entry.aspx?id=10
I'm not sure how easy they are to understand for a novice, but if you worked with webcontrols already then they can be a good refresher or complement.
You can get more TechEd blogs at http://www.techedbloggers.net/
Posted by: Dumky at June 5, 2003 10:50 AMI'm looking some info for integrate ASP.net treeview provided from Microsoft with a custom contextmenu. So I arrived to this page but I can't see the demos... :-(
Posted by: Marco at June 23, 2003 06:19 AMSorry, the server died (fried RAM) so the demos are unavailable. I'll try to make them available again.
Dumky
Posted by: Dumky at June 23, 2003 11:28 AMA post detailling some useful ASP.NET features (ResolveUrl and TemplateSourceDirectory) to handle resources like image and script file in custom webcontrols: http://weblogs.asp.net/dmarsh/posts/8188.aspx
Scott Guthrie's ASP.NET slides from his presentations: http://www.scottgu.com/
A detailled list of steps in a Page's lifecycle: http://www.aspalliance.com/PaulWilson/Articles/?id=6
An detailled article on using client script in custom webcontrols: http://weblogs.asp.net/asmith/posts/25465.aspx It explains a method "RegisterArrayDeclaration" that complements the RegisterClientScriptBlock and RegisterStartupScript methods .
Posted by: Dumky at July 16, 2003 10:50 PMDear sir,
this is session is very useful for me. but i need to maintain the viewstate value in JavaScript itsely can you help me how to save the viewsatevalue using java script. I am able to add the value in client Side in Serverside control
Posted by: Nagarajan at November 18, 2003 04:29 AMI want instantiate an event that is declared in a user control, where should I do this?
Posted by: Cris at January 26, 2006 06:32 AMCristina,
I'm not sure what you mean by "instantiate", but you could invoke/trigger the event.
This control should have a method to let you do that. Most of the time there should be a corresponding "OnAbcd" method for event "Abcd".
Hope that helps.
Posted by: Julien Couvreur at January 26, 2006 08:54 AMI have a user control with a button and a text box; I put that User control in a Web Form; When I press the button I want to write on the form(in a lable) the text that is in the text box; I'm asking where should I put this line of code: UCL.Trimite += new ModifyEventHandler(Executa);("Trimite" is the event)? wich event on the page?