ListBox.DisplayMember = [String] Can I somehow workaround it to be other than string in .NET?
-
13-09-2019 - |
Question
The question is asked with respect to an Object DataSource. So Consider that I have a class
public class Customer{
public String name;
public int age;
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
}
And I have databound a list box to a list of these objects. So I say
listBox.DisplayMember = "name";
But my question is that when I refactor my Customer class's name to
public String fullName;
the DisplayMember still stays at "name". This will fail. So it decreases my ability to refactor domain objects. Is there any way around for this?
Solution
The only way i have found around this is to use extra properties on the objects so have a
string DisplayMember
{
get { return 'name'; }
}
and when you refactor your object you then only need to change the returned string to your new property name making it a change in one location rather than in a few.
It's not great but works better than hardcoding in the app!
HTH
OneSHOT
OTHER TIPS
This is a sexier and more flexible solution
Snippet...
To make a long story short, instead of writing:
textBoxCustomerName.DataBindings.Add("Text", bindingSource, "CustomerName");
my suggestion is to write something like:
dataSource.CreateBinding(textBoxCustomerName, ctl => ctl.Text, data => data.Name);
This way, your code will still run without any problems when you refactor your entities (let’s say, if you rename the customer’s
Name
property toCompanyName
).
Pretty sweet eh?
Also some solutions are here How to make Databinding type safe and support refactoring
If you leave the DisplyMember empty then the ListBox will use the default ToString(). When you override this function in your class, the listbox will show the appropiate value. Then if you change the name of the field, your build will break in the ToString() function.
Since C# 6.0 you can use the nameof
operator, which returns the name of a variable/member/type as a string.
listBox.DisplayMember = nameof(Customer.Name);
(assuming there's a class called Customer
with a Name
property in it)
From the official language reference:
Using
nameof
helps keep your code valid when renaming definitions.
Before, you had to use string literals to refer to definitions, which is brittle when renaming code elements because tools do not know to check these string literals.
(emphasis mine)
This is why you should use properties rather than public fields to expose data from your classes. You can more easily refactor the inner working without breaking too much. Although there of course will be instances where you might have to break something.
ReSharper can do this for you ... try to get it - a really great piece of software. Probably CodeRush can do it, too. But I am not sure.
About the only real way I have found to "get around" this "issue", would be to add a new public, ReadOnly property. Name that property "ListDisplay" or something similar. Then you can modify the implementation without any impact to the UI.
It isn't an ideal situation, but it works.