CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo (.com)

Blog moved to www.jeffreypalermo.com

How to make an ASP.NET user control behave like a custom WebControl - level 200

If you've used User Controls for any amount of time, you've lamented that there is no containing control for attributes.  With any other custom controls, you have WebControl as the base class, and that allows you to use a <span/> by default or change the TagKey to another tag, and when you declaratively set an attribute like [style="padding:10px;"], the attribute automatically gets added to the tag.

Not so with User Controls, but they aren't designed to work that way.  They are meant to be pagelets: a portion of a page.  A User Control can contain anything and doesn't have to be encapsulated in any control, so there is no tag to add attributes to.

I have made a hybrid User-Custom web control.  It inherits from UserControl, so I have the nice declarative layout, but I needed functionality of a WebControl as well.  I added a WebControl as a member of my user control, and on PreRender, I wrap all my user control contents in this WebControl.  Then I bestow all the attributes of the user control on the WebControl and add the WebControl as the only 1st-level child of the user control.  The end result is that I have a user control that wraps itself in a <span/> or whatever tag I want, and I can set attributes on the Page, and they will get rendered to the browser.  This is especially useful when I need to add a style property or "class".

Here's my code-behind.  Feel free to copy/steal my code:

   14     public class Magic : System.Web.UI.UserControl

   15     {

   16         private WebControl _frame;

   17 

   18         public WebControl Frame

   19         {

   20             get {

   21                 this.EnsureChildControls();

   22                 return this._frame;

   23             }

   24         }

   25 

   26         protected override void CreateChildControls()

   27         {

   28             base.CreateChildControls ();

   29 

   30             this._frame = new WebControl(HtmlTextWriterTag.Div);

   31         }

   32 

   33         protected override void OnPreRender(EventArgs e)

   34         {

   35             base.OnPreRender (e);

   36 

   37             Control[] ctrls = new Control[this.Controls.Count];

   38             this.Controls.CopyTo(ctrls, 0);

   39 

   40             foreach(Control ctrl in ctrls)

   41             {

   42                 this.Frame.Controls.Add(ctrl);

   43             }

   44 

   45             foreach(string attribute in this.Attributes.Keys)

   46             {

   47                 this.Frame.Attributes[attribute] = this.Attributes[attribute];

   48             }

   49 

   50             this.Controls.Add(this.Frame);

   51         }

   52 

   53 

   54         private void Page_Load(object sender, System.EventArgs e)

   55         {

   56             // Put user code to initialize the page here

   57         }

   58 

   59         #region Web Form Designer generated code

   60         override protected void OnInit(EventArgs e)

   61         {

   62             //

   63             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

   64             //

   65             InitializeComponent();

   66             base.OnInit(e);

   67         }

   68 

   69         /// <summary>

   70         ///        Required method for Designer support - do not modify

   71         ///        the contents of this method with the code editor.

   72         /// </summary>

   73         private void InitializeComponent()

   74         {

   75             this.Load += new System.EventHandler(this.Page_Load);

   76         }

   77         #endregion

   78     }

Here is my user control markup:

<%@ Control Language="c#" AutoEventWireup="false" Codebehind="Magic.ascx.cs" Inherits="MagicUserControl.Magic" TargetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
This is a tag.
<asp:Label Runat="server">Yo, buddy</asp:Label>

And here is my Page markup (where my User Control is used):

<uc1:Magic id="Magic1" style="margin: 10px;" myAttrib="Palermo" Frame-CssClass="myClass" runat="server"></uc1:Magic>

See how easy it is now to add any sort of attribute and have it render?  I created this control out of necessity because I wanted the simplicity of user controls with the power and flexibility of a WebControl-derived control.



Comments

Jeffrey Palermo said:

As I mentioned before, I'm at a new company, and I'm one of the .Net developers working on Shadows.com.&amp;nbsp;...
# July 19, 2005 12:56 PM

Christopher Steen - Learning .NET said:

ASP.NET Page Profiling using Page Tracing
Channel 9 Forums &amp;raquo; The Videos &amp;raquo; Don Box - What...
# July 19, 2005 7:44 PM

Christopher Steen - Learning .NET said:

ASP.NET Page Profiling using Page Tracing
Channel 9 Forums &#187; The Videos &#187; Don Box - What goes into...
# July 21, 2005 9:15 PM

Christopher Steen - Learning .NET said:

ASP.NET Page Profiling using Page Tracing
Channel 9 Forums &#187; The Videos &#187; Don Box - What goes into...
# July 21, 2005 9:18 PM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# November 20, 2007 11:43 PM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication

News

Headspring Systems

View Jeffrey Palermo's profile on LinkedIn

See my new blog at .jeffreypalermo.com