Dot Net Solutions
George V Place,
4 Thames Avenue
Windsor
Berkshire
SL4 1QP
Great Britain
0845 402 1752
GEO: -0.606174, 51.4843
 
 
 
 

Building a Web Part UI 

Recently I've been spending a lot of time working on various SharePoint projects, none more challenging than the Citroën site launched earlier this year. I'm going to take the time to explain how we put together our web parts and server controls, particularly from the point of view of a WCM scenario where the complexity of our mark-up was significantly greater than that of a traditional "vanilla" intranet SharePoint due to the various accessibility guidelines we needed to adhere to as part of the project.

For a full demo of the code used in this article click here.

Traditionally there are 2 ways of building your web parts/server controls, without the need for third party tools.
a) Override RenderChildren.
b) Override CreateChildControls.

Overriding RenderChildren is a great way to define exactly what mark-up is to be rendered out to the client browser and so in effect achieve very tight control of your mark-up, e.g:

 1: protected override void RenderChildren(HtmlTextWriter writer)
 2: {
 3:    DropDownList listControl = new DropDownList();
 4:    listControl.ID = "listControl";
 5:     writer.AddStyleAttribute(HtmlTextWriterStyle.Left, "5");
 6:     writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "500px");
 7:     writer.RenderBeginTag(HtmlTextWriterTag.Div);
 8:     writer.AddStyleAttribute("float", "left");
 9:     writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
 10:     writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "300px");
 11:     writer.RenderBeginTag(HtmlTextWriterTag.Div);
 12:     listControl.RenderControl(writer);
 13:     //We've only rendered 2 bits of mark-up and a 
 14:     //server control so far, imagine what this would
 15:     //be like in the real world!
 16:     writer.RenderEndTag();
 17:     writer.RenderEndTag();
 18: }

However this method also has several significant drawbacks:
1) As you can see from the example above the code can be incredibly verbose even to achieve some relatively simple controls. What kind of developers would we be if we allowed such messy code into our projects? That’s right... bad developers.
2) The control's state will also not persist over post back. Given that a control's state is stored in ViewState and that view state is saved and loaded before control Rendering - control values are not retained on post back and post back events (Button Click for example) are not fired.
3) It also breaks the Web Part Page Services Component in SharePoint (WPSC).

Overriding CreateChildControls is the generally preferred method in mainstream web part/server control development, mainly because it is respectful of the ASP.NET page/control life-cycle which inherently fixes 2 of the problems highlighted with the RenderChildren() method. Notably the control's state is persisted and it does not break the WPSC. In most cases though, rendering any non "Hello World" UI to the form is still a verbose and long process. e.g:

 1: protected override void CreateChildControls()
 2: {
 3:     HtmlGenericControl containerDiv = new HtmlGenericControl("div");
 4:     containerDiv.Style[HtmlTextWriterStyle.Width] = "400px";
 5:     containerDiv.Style[HtmlTextWriterStyle.Left] = "5px";
 6:  
 7:     HtmlGenericControl dropDownContainerDiv = new HtmlGenericControl("div");
 8:     dropDownContainerDiv.Style[HtmlTextWriterStyle.Position] = "relative";
 9:     dropDownContainerDiv.Style["float"] = "left";
 10:     dropDownContainerDiv.Style[HtmlTextWriterStyle.Width] = "300px";
 11:     containerDiv.Controls.Add(dropDownContainerDiv);
 12:  
 13:     Controls.Add(containerDiv);
 14: }

Now I don't doubt that a large amount of work can be done to keep the mark-up simple and style it with CSS, but there are often times when you have to use more complicated Mark-Up, particuarly in a media rich sites.

Introducing Page.ParseControl()

Page.ParseControl() is a method inside the System.Web.UI.Page class that parses well formed ASP.NET mark-up into a control hierarchy. What this effectively allows is for you to substitute all of your Mark-Up generation code in CreateChildControls() with just a few simple lines. You can then pull out the controls that you are particularly interested in (DropDownList, TextBox, etc) using the FindControl method eg:

 1: protected override void CreateChildControls()
 2: {
 3:     //The String for the UI is stored in a Resource called myControlUI.ascx
 4:     //and referenced in my Resources file.
 5:     Control parsedUI = Page.ParseControl(Resources.myControlUI);
 6:  
 7:     Controls.Add(parsedUI);
 8: }

This has all of the advantages of the CreateChildControls method above plus it keeps the codebase as tidy as possible and makes it much more maintainable. Not only that but I would bet most developers would be more productive being able to a edit Web Part user interface in this familiar .ascx file text editor with intellisense (pictured below), rather than building it up programmatically.

image

One thing to note is that declarative event handler definitions will not be parsed correctly so you do still have to programmatically assign your control events programmatically - but you have to do that in the other methods anyway!

I have added a full demo of each method in action for download.

Published: 24 Nov 2008  09:13
0  Comments  |  Trackback Url  | 0  Links to this post | Bookmark this post with:        

Links to this post

No linkbacks added

Comments

No comments added yet

 
 
 
 

Post comment

Name *:
URL:
Email:
Comments:


CAPTCHA Image Validation