How to Allow Generic Controls in ASP.NET Pages

Did you ever want to have a Repeater<Customer> control on your page? And its events were all strongly typed to recognize that each row was bound to a Customer object? Well, I came up with a way of doing it using some lesser known features of ASP.NET.

Today it's possible to use generic controls in ASP.NET, but you can't directly have a generic control in the tag markup. You'd typically have to do some trick such as deriving a concrete type from the generic type or instantiating the control from code-behind and adding it to a placeholder on the page.

My solution involves using a ControlBuilder to alter how the ASP.NET tag gets parsed. Typically ASP.NET parses a tag such as <cc:GenericControl runat="server" /> and instantiated a type called GenericControl in the mapped "cc" namespace. My ControlBuilder overrides that behavior by returning an instance of GenericControl<TDataItem> whenever that tag is encountered.

Here's an outline of my sample control:

namespace GenericControls {
    public class GenericControl<TDataItem> : Control where TDataItem : new() {
        public event EventHandler<GenericEventArgs<TDataItem>> Stuffing {
            add;
            remove;
        }
    }
}

Note that the control itself is generic over TDataItem, and that is exposes an event called "Stuffing" that uses a generic EventHandler with generic EventArgs also bound to TDataItem. So, if you have an instance of the GenericControl<Customer>, the event handler should take event arguments of type EventArgs<Customer>. Now you don't have to cast your event arguments to get to your data object!

To use the control you specify the generic argument in the form of a pseudo-property on the control tag itself called ObjectType:

        <gc:GenericControlGeneric runat="server" ID="CustomerGeneric"
            ObjectType="MyStuff.Customer, App_Code"
            OnStuffing="CustomerGeneric_Stuffing">
        </gc:GenericControlGeneric>

Yes, my naming convention is horrible. Unless you thing GenericControlGeneric sounds good. But it doesn't sound good; it's horrible! :)

And before anyone asks, the topic of generic syntax in tags has been discussed at length, so I won't repeat that here.

In summary, I encourage you to check it out and see if it helps solve any problems you've had, hopefully without creating any new problems. This was just a pet project I did to see whether it was possible to create generic controls in markup.

And finally, a caveat:

While this seems to work great at runtime, I've encountered some weird problems in Visual Studio to support this. For example, when you try to add an event handler for the Stuffing event through the property grid you might get some weird behavior.

Download the project source code here: GenericControl.zip

Attachment: GenericControl.zip
Published Tuesday, December 4, 2007 2:00 PM by Eilon
Filed under: , ,

Comments

# re: How to Allow Generic Controls in ASP.NET Pages

Wednesday, December 5, 2007 3:50 AM by Fredrik N

Nice.

Now you only need to spend some time making copy of all of yours data-bound controls and make the new one support Generics ;)

If you have plans of doing that the ObjectType could be set internally if we use a ObjectDataSource control, because the ObjectDataSource already specifies the type of the object to bind, wouldn't that be cool ;)

# re: How to Allow Generic Controls in ASP.NET Pages

Wednesday, December 5, 2007 9:05 AM by Ivan Atanasov

why do you have to use Generic Controls,

when microsoft build them in ObjectDataSource.

# re: How to Allow Generic Controls in ASP.NET Pages

Wednesday, December 5, 2007 2:28 PM by RichardD

See also:

www.codeproject.com/.../TypedRepeater.aspx

# re: How to Allow Generic Controls in ASP.NET Pages

Thursday, December 6, 2007 4:32 PM by Fredrik N

Ivan Atansov:

Most of the time when we need to add something to a control, like extending the GridView, we can use the DataBound event. By using the event args we can get the DataItem, to get the right interface we need to do a cast. This could be avoided by using a Generic GirdView control.

# re: How to Allow Generic Controls in ASP.NET Pages

Friday, December 7, 2007 12:26 PM by tony_lombardo

Very cool stuff, thanks for sharing!

# re: How to Allow Generic Controls in ASP.NET Pages

Friday, December 7, 2007 5:42 PM by Cyril Durand

Using a ControlBuilder make hard to create custom generic control. We have to implement a lot of specific class.

I already encounter this problem, and I think about a custom build provider with a custom PageParseFilter. Thus no dummy specific control or specific ControlBuilder will be necessary.

But it need a lot of work, and I opt for an easier solution.

By the way, I prefer this approach : <vc:SomeGenericControl-SomeObjectType1.SubType1-SomeObjectType2.SubType2 runat="server" />

# re: How to Allow Generic Controls in ASP.NET Pages

Tuesday, December 11, 2007 11:11 AM by David Fauber

My (I'm sure heavily flawed) approach has been

# re: How to Allow Generic Controls in ASP.NET Pages

Tuesday, December 11, 2007 11:17 AM by David Fauber

My approach has been something like this:

[code]

<mytag:myview

 ID="PubNameGrid"

 runat="server"

 Title="Publication List"

 RelativeLayoutPath="/layouts/publications.xml" />

<myview>

 <Columns>

   <Column name="PublicationName" display="Publication Name" type="string" />

...

 </Columns>

</myview>[/code]

I'm sure there are a thousand reasons that is horrible to do, but it allowed me to encapsulate what I wanted to reuse (all of the html and javascript that is the same regardless of what kind of data it contains), and configure controls with xml files that our "powerusers" can make use of.

# re: How to Allow Generic Controls in ASP.NET Pages

Tuesday, January 1, 2008 8:26 AM by ysw

have you tried to get typed DataItem property for use in data binding expressions?

# re: How to Allow Generic Controls in ASP.NET Pages

Monday, January 7, 2008 3:21 PM by Phil

I wonder if there's a way to "automatically" declare the GenericControlGeneric of this page as a GenericControl<MyStuff.Customer> in the page's designer file (default.aspx.designer.cs)?

because in the code behind, i'd like to interact with the specific type (MyStuff.Customer) and not a simple object.

Thanks

Phil

# re: How to Allow Generic Controls in ASP.NET Pages

Sunday, February 17, 2008 6:09 PM by Ivan Atanasov

yes for casting,

and for performance your solution is best!

# re: How to Allow Generic Controls in ASP.NET Pages

Thursday, July 17, 2008 5:38 PM by Ronald Rogers

I didn't like the -.- proposal.

Using a dash for this purpose struck me as counter-intuitive. SomeGenericControl-SomeObjectType looks like all one word.

I'd propose using a double-colon to start the declaration and colons thereafter.

<vc:SomeGenericControl::SomeObjectType1.SubType1:SomeObjectType2.SubType2 runat="server" />

# re: How to Allow Generic Controls in ASP.NET Pages

Sunday, October 18, 2009 10:07 AM by shadow

Hi,

1. great work

2. change line in your code:

Type genericType = typeof(GenericControl<>);

to:

Type genericType = type.BaseType.GetGenericTypeDefinition();

this way class GenericControlBuilder works with any generic control ;-)