Supporting Templates with ASP.NET User Controls

ASP.NET User Controls (those files with the .ascx extensions) provide a really easy way to encapsulate functionality within an application, and allow it to be re-used across multiple pages and projects (note: for a tutorial on how to create re-usable user control libraries with the VS 2005 Web Application Project check out the C# one here, and the VB one here).

Most developers who create user-controls know that it is possible to easily expose public properties from them so that you can customize them from a page that is using them.  This allows a page developer to declare properties like so on the user-control tag (as well as access them from the code-behind):

   <MyLibrary:MyUserControl id="UC1" someproperty="somevalue" runat="server"/>

  

What is less well known is that in addition to exposing standard properties from user controls, you can also expose template properties.  This allows a page developer to pass templates to the user control like so:

 

 

   <MyLibrary:MyUserControl id="UC1" someproperty="somevalue" runat="server">

  

      <TitleTemplate>

           Some custom content I want rendered in the title...

      </TitleTemplate>

 

      <ItemTemplate>

           Here is a calendar: <asp:calendar id="cal1" runat="server" />

      </ItemTemplate>

 

   </MyLibrary:MyUserControl>

 

This allows you to provide much richer UI customization and further re-use.

Robert Seder has posted a nice blog post here that describes how to-do this.

Update: Kris also pointed me at some MSDN documentation that shows the syntax to support this with VB.  You can read it here.

Hope this helps,

Scott

 

20 Comments

  • What a great post!



    Thanks Scott.

  • Kris - good pointer. Thx!

  • Did you actually try his instructions Scott?



    Yeah - it works, but it is pretty ugly when used from VS 2005. &nbsp;The designer breaks with a &quot;Error Creating User Control - User Control does not have public property names DescriptionTemplate&quot; error.



  • I know I am asking something not related to this Topic. But can u give us any update on when are the next set of Atlas control going to come and what are the new controls that are being added. You also mentioned earlier that you would be blogging about whatever Microsoft is about to come up with in the month. I do not see anything like that. Thanks Vikram

  • Some of the new .NET controls like the Login Control use an even better kind of template. In this example the template can contain any controls the user of the control wants it to, but they don't interact with the user control itself. That is, unless the user control does a 'findcontrol' on the controls within the template and then uses the found control (if any) instead of its own internal version. The login control does that for the username, password, etc controls. That allows the template designer to make the UI of the control look like anything they want it to even if the structure is completely different -- for example, make the password box appear BEFORE the user name box. The template designer just has to name the controls with the correct ID so the parent control can find them. The whole idea is similar to the concept of user controls themselves -- except with user controls, the ascx file is the template, and the code behind for it is the control.

  • My wish is that in the future this experience can be similar to creating Master Pages.

  • Excellent! Thanks!

  • Brilliant! Much simpler than wip up a composite control.

  • Good point! Thanks.

  • Another important tip, to make the controls nested in the templates directly accessible on the Page that contains the user control, is to add an [TemplateInstance(TemplateInstance.Single)] attribute to the ITemplate properties of the User Control. Scott, the designer error is really annoying. The User Control designer doesn’t recognize any inner property of the User control and throws an error. What can be done to correct it? Cheers, Rui

  • How can add design time support in VS2005?

    I need to just expose one panle and allow people drag controls on it at design time but designer seems broken when using the code described.

    Manu

  • Hi Manu,

    For design-time support, you are best off using the new CompositeControl base class within ASP.NET. This blog post points a few articles you can read about this: http://weblogs.asp.net/scottgu/archive/2006/02/14/438234.aspx

    Hope this helps,

    Scott

  • Thanks... I'm trying that way. Composite control support in 2.0 seems far better than in 1.1.

    Manu

  • Well I am having a problem. &nbsp;I would like to have a templated user control, which I can use, let's say on a page, and then have the ability to access the controls within the template from the PAGE. &nbsp;Example. &lt;uc:myTemplateUC runat="server"&gt; &nbsp;&lt;asp:label id="myLabel" runat="server" /&gt; &lt;/uc:myTemplateUC&gt; I would like to be able to access 'myLabel' from the page which uses 'myTemplateUC'. The problem is here. &nbsp;If I add the attribute to the user control: [ParseChildren(false)] It actually works, but then, I cannot use any code blocks in my usercontrol! &nbsp;i get this fun error: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;). And if I use: [ParseChildren(true)] Intelisense shows the myLabel on the page, but If I try to do anything with it, I get a null reference exception. &nbsp;Events also don't seem to fire in this case, as from an asp:button Please help! &nbsp;I have a very slick page template system, which is lacking only this fix.

  • Ok, in the end I found my mistake. &nbsp; I was trying to get access to my nested controls within the template of a templated user control, from the page instantiating that user control. Do this: Must use: [ParseChildren(true)] &nbsp; //on user control class [PersistenceMod(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl)), TemplateInstance(TemplateInstance.Single) ] &nbsp; // on template property And then must InstanceIn the template property on the override OnInit() in the user control. &nbsp; My problem the entire time was that I was using the user control PreRender instead of the OnInit to InstanceIn the controls, ugh...

  • I've been looking at creating a databound user control and struggling. What I was trying to do was expose the itemtemplate from a data repeater using similar techniques discussed above but without success.



    Has anyone made a user control that is databound? Essentially I'm after a user control repeater.

  • A general advice to everybody:

    Make sure you don't give your template property the name &quot;Body&quot;, or the designer will break. I guess this applies to other reserved words also.

  • In a previous post Dave Reed was talking about the templates of the Login Control. You can change the template, and have the same result, as long as you have the correct ID's for components on the template.
    Is it possible to switch the template of the Login Control runtime (say based on a value in Profile or database)?
    Thanks, Jaap.

  • Hi there,
    I'm currently developing an asp.net application. I have a usercontrol .ascx that is a datagrid bound to
    some data allowing the user to click the records and display the complete details for the
    chosen record.

    My dilemma is that I know have introduced a new admin.aspx page, on this I need to display
    the same grid of data but when clicking on records I will be loading the record for editing in a different interface, not
    loading it for viewing. The grid will also need to be a slightly different template layout in the admin.aspx
    page.

    So I want to use all the functionality of the datagrid usercontrol in both places but change
    a couple of pieces of functionality.

    What is the thought process that I should apply to these sort of problems? Do you create a new
    usercontrol and strip out/add in as required or do you use one usercontrol and adjust it
    for each scenario (which always seems to result in an 'if this', 'if that' type scenario)

    Would appreciate everyones thoughts on this?

  • Hi Kieran,

    You can programmatically allow editing/deleting of values from a Grid column by retrieving its column and then setting the ShowEditButton or ShowDeleteButton to true/false. This would allow you to have one user control but customize it depending on the user role.

    Hope this helps,

    Scott

Comments have been disabled for this content.