In this part we are going to take the custom DropDown html control that we created in part 1 and create an ASP.NET server control so we can use it in our Web Forms.
The control in part 1 was a fully working drop down control that behaves very close to the regular <select> html control but, if you set a specific width to the control, it expands the list of options to show the full width of the options in IE6 & 7 (which does not happen with the regular select html control).
To create a server control for our drop down, we are going to inherit from the regular DropDownList control to get all its databinding functionality and we are going to override some of the rendering members to emit a different html markup. We also going to implement IPostBackDataHandler to manage the post back data. So our class declaration will be:
Then we override the RenderBeginTag to emit the same markup as we created it in part 1:
Nothing really special here, we created the same markup as in part 1 up to where the data for the options has to be inserted... and that's the job of the RenderContents member so we override that one too, and create a <li> for each option:
Note that we are using the Items collection from the DropDownList base control so all the functionality for databinding, and accessing the items collection still works the same, we are just emitting new html. Then we need to render the closing html tags for our control, and that is done in the RenderEndTag member:
Now, you may notice that we are registering a closeDropDown script also, the problem is that in IE there's a strange behavior when you set the initial state of the list of options (the listbox) to display:none: when you display it, it does not stretches correctly and does not show the overflow scrolls correctly, so we just hide it on every postback.
The Postback data
The only extra thing we need to do is handle the postback data in our control by implementing the IPostBackDataHandler interface
When our control generates a postback, we get called on the LoadPostData with the values of the postback, so if the selected value has changed, we change it and return true, so the framework calls the RaisePostDataChangedEvent
One last thing we need to do and that has to do with the way DropDownList control handles the SelectedValue and SelectedIndex properties. Before we bind the data to our control using the base class, we need to remember our SelectedValue and set it back after the binding. During the binding step, the DropDownList control uses an internal cache for selected items that we (at the derived class) don't have access, so it will try to set the SelectedValue from that cache and there's where we loose our selection, so we do:
You can download the full server control code here
Some improvements could still be made to the control:
- Still fills a bit sluggish when you have a lot of options in the drop down, so some optimizations may improve this.