The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
All controls that inherit from ListControl (BulletedList, CheckBoxList, DropDownList, ListBox and RadioButtonList) have some annoying behavior in common:
You can only bind the control to a single property using the DataTextField property. For example, if you have a Customer class with properties Id, Name, Surname, etc and you want to show the full name of a customer in any of the ListControls, you have several options:
The truth is that I don’t like any of those options, all of them are hacks.
For nested properties you have the similar problems. You can bind to Id or Name, but you can’t bind to Address.City or Address.Zip.
Today I faced this problem again and I decided to investigate a more innovative solution. The problem itself is in the controls that inherit from ListControl that are very strict in the binding options. So I took a look of how the controls perform the binding to see if I could do anything to overcome those limitations. At first sight I thought I was loosing my time but after a deeper study I found that it was amazingly easy to fix those problems in a very sleek way.
The data binding of the controls is performed in the PerformDataBinding method. The code at ListControl.PerformDataBinding uses DataBinder.GetPropertyValue to retrieve the value to show in the control if you set the DataTextField property. However, DataBinder.GetPropertyValue doesn’t handle nested properties. DataBinder.Eval is a better choice because it does handle nested properties. So using it we solve one problem. The other problem can be solved easily as well. As we have two properties that control how the Text of each ListItem will be extracted and shown from the data source, with a bit more of effort we can handle the new functionality. I have come up with a very intuitive solution:
The code that performs the data binding is:
As we need to call this data binding code instead of the one from ListControl I needed to subclass all controls that inherit from ListControl in order to fix them. So now I have BulletedListEx, CheckBoxListEx, DropDownListEx, ListBoxEx and RadioButtonListEx.
I have created a simple example showing how to use them. Imagine that an Item can be supplied by a set of suppliers, and each supplier sells the item with a different price. The following image shows the properties of the 3 entities of the sample:
I have created a web page with a DropDownList with some items, and when you select an item in the DropDownList you will see a ListBox with the all suppliers of that item with the associated price for the item. Notice how I show the Id and the Name in the DropDownList and how I show the price, supplier Id and supplier name in the ListBox:
The ASPX of the page follows:
As you can see, the solution is really clean and elegant, and backward compatible with the current controls that inherit from ListControl.
That’s all for now,Merry christmas!
ListControlsEx_bin.zip (6.53 KB)