Databinding a ListBox to List
-
Hi The gist of my problem is that I want to bind an ASP.NET
ListBox
to aList< T >
and have theValue
field populated by a property of an object in theList
and theText
field populated by the result of the callToString()
on the object in theList
(the format of which is dictated by theDataTextFormatString
propery of theListBox
): I have two classesPersonInfo
- has properties PersonId / FirstName / LastName. This class implementsIFormattable
allowing customized string representation of any instantiated object.PersonInfoList
which derives fromList< PersonInfo >
(so stores objects of typePersonInfo
). I want to use PersonInfoList as the DataSource to a ListBox:PersonInfoList pil = new PersonInfoList(); ListBox1.DataSource = pil; ListBox1.DataTextFormatString = "{0:l, f}"; //formats output as [LastName], [FirstName] ListBox1.DataBind();
By not specifying theDataTextField
orDataValue
field, theIFormattable ToString()
method is called on eachPersonInfo
object in thePersonInfoList
and both theText
andValue
properties are populated with [LastName], [FirstName] as expected. The problem is that I want theValue
field to contain PersonId and theText
field to contain the Person's name (formatted) as above. If I add PersonId to theListBox1.DataValueField
and do not specify a value forListBox1.DataTextField
, the PersonId is used for bothText
andValue
. The only way that I have found around this is to add a Me property thePersonInfo
class:public PersonInfo Me { get{ return this; } }
and then setListBox1.DataTextField = "Me";
YUCK! This produces the desired output, but there has to be a better way to do this! :confused: Any ideas would be much appreciated. Chris -
Hi The gist of my problem is that I want to bind an ASP.NET
ListBox
to aList< T >
and have theValue
field populated by a property of an object in theList
and theText
field populated by the result of the callToString()
on the object in theList
(the format of which is dictated by theDataTextFormatString
propery of theListBox
): I have two classesPersonInfo
- has properties PersonId / FirstName / LastName. This class implementsIFormattable
allowing customized string representation of any instantiated object.PersonInfoList
which derives fromList< PersonInfo >
(so stores objects of typePersonInfo
). I want to use PersonInfoList as the DataSource to a ListBox:PersonInfoList pil = new PersonInfoList(); ListBox1.DataSource = pil; ListBox1.DataTextFormatString = "{0:l, f}"; //formats output as [LastName], [FirstName] ListBox1.DataBind();
By not specifying theDataTextField
orDataValue
field, theIFormattable ToString()
method is called on eachPersonInfo
object in thePersonInfoList
and both theText
andValue
properties are populated with [LastName], [FirstName] as expected. The problem is that I want theValue
field to contain PersonId and theText
field to contain the Person's name (formatted) as above. If I add PersonId to theListBox1.DataValueField
and do not specify a value forListBox1.DataTextField
, the PersonId is used for bothText
andValue
. The only way that I have found around this is to add a Me property thePersonInfo
class:public PersonInfo Me { get{ return this; } }
and then setListBox1.DataTextField = "Me";
YUCK! This produces the desired output, but there has to be a better way to do this! :confused: Any ideas would be much appreciated. ChrisHi there, When a control is not suitable for my need, I might think of customizing the control. So IMHO, in this case you might want to create a custom ListBox control by inheriting from the standard ListBox control and simply override the
PerformDataBinding
method which is where you can put your own data binding logic. -
Hi there, When a control is not suitable for my need, I might think of customizing the control. So IMHO, in this case you might want to create a custom ListBox control by inheriting from the standard ListBox control and simply override the
PerformDataBinding
method which is where you can put your own data binding logic.Hi Thanks for the repsonse. Just strikes me as odd that this functionality isn't available out of the box (it very nearly is - just not quite. I discovered that I can get the functionality by using Dictionary< T > with PersonId as Key and the PersonInfo object as Value (and setting DataTextField="Value" and DataValueField="Key") - but then I can't sort the output by value (as far as I can tell) which is another requirement. Ah well - gives me a good excuse to dig into the PerformDataBinding method I guess! Thanks again for your help. C
-
Hi Thanks for the repsonse. Just strikes me as odd that this functionality isn't available out of the box (it very nearly is - just not quite. I discovered that I can get the functionality by using Dictionary< T > with PersonId as Key and the PersonInfo object as Value (and setting DataTextField="Value" and DataValueField="Key") - but then I can't sort the output by value (as far as I can tell) which is another requirement. Ah well - gives me a good excuse to dig into the PerformDataBinding method I guess! Thanks again for your help. C
Basically, the
ListBox
control inherits from the base classListControl
, when data is bound to the control thePerformDataBinding
gets executed internally. And this method contains the default logic to build the items collection from the specified data source with the settings like DataTextField, DataValueField and DataTextFormatString. Fortunately, this method is overridable, so you're not happy with the default behavior, you can change it the way you want by overriding this method in your custom control. In addition, you may consider using the generic Dictionary as you discovered only when you bind data to the control. By this I mean, you can sort data with the List generic collection, you then copy it to the Dictionary and bind it to the control. However, this step is unnecessary to me. Adding a public property like Me is also an option, but it's not really a good choice IMHO as it requires you to change your object design. -
Basically, the
ListBox
control inherits from the base classListControl
, when data is bound to the control thePerformDataBinding
gets executed internally. And this method contains the default logic to build the items collection from the specified data source with the settings like DataTextField, DataValueField and DataTextFormatString. Fortunately, this method is overridable, so you're not happy with the default behavior, you can change it the way you want by overriding this method in your custom control. In addition, you may consider using the generic Dictionary as you discovered only when you bind data to the control. By this I mean, you can sort data with the List generic collection, you then copy it to the Dictionary and bind it to the control. However, this step is unnecessary to me. Adding a public property like Me is also an option, but it's not really a good choice IMHO as it requires you to change your object design.I agree that the Me property is less than desirable. Interesting point about transferring it to a Dictionary prior to binding. Hadn't thought of that! Ultimately, I'll probably just follow your advice and subclass ListBox and any other controls that I need to use this in. As I said, it strikes me as odd that this isn't available out of the box. It's surely not that unusual a requirement to be able to use a property of an object as the Value field and the ToString() representation of that object as the Text field and to be able to acheive this via data binding. Any way, your feedback has been most useful and has given me something to dig into. So many thanks for your time. C