Declarative data binding on User Controls
I had this problem a few years ago and figured that there was no good solution, but I am older and wiser now so figured it’s time look for a better solution.
I have a GridView, and inside the ItemTemplate I call one of my own UserControls:
<asp:GridViewID="grdMessages"runat="server" ... > ... <ItemTemplate><uc1:EmailAddressID="EmailAddress1"runat="server"
DataSource='<%# (MailAddress)Eval("FromAddress") %>'/>ItemTemplate> ... asp:GridView>
But the DataSource property of the EmailAddress user control is never set. If I have a plain <%# Eval("FromAddress") %> right next to the
My original solution was to just set the value of the user control’s properties in the code behind class. But I shouldn’t have to do that. (It’s also a bit annoying to do that because I’d have to handle the GridView’s DataBinding event and then find the control and update it.)
There’s got to be a better way!
I overrode the user control’s DataBind and DataBindChildren methods, to see if they were being called. They were.
So then I tried it with a Literal control, setting the Text property. Probably the simplest .NET Web Control there is. Obviously that worked, because that’s how data binding is supposed to work. So there must be something that the Literal control does that mine doesn’t. Time to pull out Reflector!
The Literal.Text property has an attribute called Bindable. Could this be it? It makes sense. Its full name is System.ComponentModel.Bindable. Does it work? Nope.
Hang on a tick… the DataSource property is being set now. So what is my problem? The code that’s doing the work is in the Load event handler. But the DataSource property is being set after Load. So I’ve moved that code to PreRender and…
So what have we learnt?
To make a UserControl’s property bindable, you must use the [Bindable] attribute. And those properties will not get bound until after Load, so don’t put code that relies on your bound properties in the Load event handler!