navigation
 Monday, March 10, 2008

I'm a fan of declarative programming whenever possible. ASP.NET's ControlParameters are a great tool for programming DataSources declaratively, but they have a flaw that frustrated me for quite a while: they can only bind to controls within a page, not a page property. Or can't they?

The key to understanding how ControlParameters work is knowing that they use DataBinder.Eval() to evaluate their value at runtime, using ControlID to find a control in the page, and then passes that as the first parameter, and the value of PropertyName as the second parameter. This means that if you can figure out a way to get from a control up to the page via properties, you can reference any page property from there, and indeed you can!

<asp:ControlParameter Name="ID" Type="Int32" ControlID="SqlDataSource1" PropertyName="NamingContainer.APublicProperty" />

There are really only two things you need to do:

  1. Set the ControlID to the ID of any control contained directly by the page. I tend to prefer to use the DataSource's ID, but any other top-level control will do.
  2. Set the PropertyName to "NamingContainer." + the name of the page property you want to bind to.

When the ControlParameter is evaluated, it will use reflection to navigate from the DataSource to its NamingContainer, which is the page, and then to the page property you want to evaluate to.

This technique will work for pages without a master page and UserControls, but not for pages with a master page. For those, you must replace NamingContainer with Page.