Monday, June 16, 2008

Templated Web User Controls

I wanted to write this great post about how to make Web User Controls that would have templates, just like Repeaters or GridViews or whatever, face any problems, then solve them. Unfortunately, MSDN already has a post like this: How to: Create Templated ASP.NET User Controls. So all I can do is tell you where to use this and what problems you might encounter.

I think the usage is pretty clear and useful: whenever you have as?x code that repeats itself, but has different content, you can use a templated Web User Control. The best example I can think of is a collapsable panel. You have a Panel, with some javascript attached to it, a hidden field to hold the collapse state, some buttons and images and texts to act as a header, but every time the content is different.

Now with the issues one might encounter. In Visual Studio 2005 you get an error, while in VS 2008 you get a warning telling you the inner template, whatever name you gave it, is not supported. This is addressed by the
[ PersistenceMode(PersistenceMode.InnerProperty) ]
decoration of the ITemplate property of the control.
Then there is the issue of the design mode, where you get an ugly error in all Visual Studio versions: Type 'System.Web.UI.UserControl' does not have a public property called '[yourTemplatePropertyName]'. As far as I know there is no way of getting rid of this. It is an issue within Visual Studio. However, the thing compiles and the source as?x code is warning free. I think one could easily sacrifice some design time comfort to reusability.


Anonymous said...

In my experience it compiles but if i try to access to a control inside the template from code behind it doesn't work. Into the file MyUserControl.ascx.designer.cs it doesn't register controls added into the template.

Siderite said...

That's normal for any Templated control. In order to find a control in a TemplatedControl you need to get a reference to the template container and then use container.FindControl("name").

I mean, how could you use in the codebehind the name of a label in a GridView? From what row would you get it?

There would have been a possible solution to return an array of objects for templated controls, but I guess no one really needed it since the index of the array would have no real meaning.