Why does ValueMember override an empty DisplayMember - c#

When I set a DataSource on a control and want to use .ToString() as DisplayMember, I need to set the DisplayMember last or the ValueMember will override it.
MSDN on empty string as display member:
The controls that inherit from ListControl can display diverse types of objects. If the specified property does not exist on the object or the value of DisplayMember is an empty string (""), the results of the object's ToString method are displayed instead.
Code to reproduce:
Class:
class SomeClass
{
public string PartA { get; set; }
public string PartB { get; set; }
public string WrongPart { get { return "WRONG"; } }
public override string ToString()
{
return $"{PartA} - {PartB}";
}
}
Form:
var testObj = new SomeClass() { PartA = "A", PartB = "B" };
comboBox1.DataSource = new [] { testObj };
comboBox1.DisplayMember = "";
comboBox1.ValueMember = "WrongPart";
comboBox2.DataSource = new[] { testObj };
comboBox2.ValueMember = "WrongPart";
comboBox2.DisplayMember = "";
You can try it by making a new form and adding 2 combobox's.
Result:
Conclusion and question:
This can be easily fixed by setting them in the correct order however this is prone to errors, it also does not show this behavior if I use an actual property as DisplayMember instead of ""/ToString.
I would really like to know why it displays this behavior and if I could possibly set .ToString() explicitly as DisplayMember (for code clarity).

I have searched in the reference source and found this bit:
if (!newValueMember.Equals(valueMember)) {
// If the displayMember is set to the EmptyString, then recreate the dataConnection
//
if (DisplayMember.Length == 0)
SetDataConnection(DataSource, newValueMember, false);
SetDataConnection method signature:
private void SetDataConnection(object newDataSource, BindingMemberInfo newDisplayMember, bool force)
This sets a new DisplayMember
displayMember = newDisplayMember;
so now we've come to the root of the issue

Related

C# populate a combo box from a method

What I would like to do is to populate a drop down menu from a database.
First of all I plan to use a combo box.
I have created an object that contains the data that I need to take from the database. The object is as follows
namespace RLMD
{
public class FlashCardLevel
{
private int intFCLId;
private String strFCLName;
public FlashCardLevel(int intFCLId, String strFCLName)
{
this.intFCLId = intFCLId;
this.strFCLName = strFCLName;
}
public int IntFCLId
{
get { return intFCLId; }
set { this.intFCLId = value; }
}
public String StrFCLName
{
get { return strFCLName; }
set { this.strFCLName = value; }
}
}
}
What I need to do is to add a list of items from a database, but for ease of use I have simulated given some sample data.
public List<FlashCardLevel> Rifle(List<FlashCardLevel> fcLevel)
{
fcLevel.Add(new FlashCardLevel(1, "Severe"));
fcLevel.Add(new FlashCardLevel(2, "Moderate"));
fcLevel.Add(new FlashCardLevel(3, "Mild"));
fcLevel.Add(new FlashCardLevel(4, "Slight"));
return fcLevel;
}
I'm calling the method here.
List<FlashCardLevel> fcLevel = new List<FlashCardLevel>();
talkToDatabase.Rifle(fcLevel);
this.comboCardLevel.DataSource = fcLevel;
this.comboCardLevel.DisplayMember = "Name";
this.comboCardLevel.ValueMember = "Value";
The combobox is displaying no information.
I would appreciate any help
Updated:
The DisplayMember Property should be referring to FlashCardLevel (class), Property StrFCLName and ValueMember should be pointing to IntFCLId.
List<FlashCardLevel> fcLevel = new List<FlashCardLevel>();
talkToDatabase.Rifle(fcLevel);
this.comboCardLevel.DataSource = listFromDatabase;
this.comboCardLevel.DisplayMember = "StrFCLName";
this.comboCardLevel.ValueMember = "IntFCLId";
The DisplayMember and ValueMember should point to your properties name.
this.comboCardLevel.DisplayMember = "IntFCLId";
this.comboCardLevel.ValueMember = "StrFCLName";

How to add value to checkedListBox items

Is it possible to add to checkedListBox item also value and title
checkedListBox1.Items.Insert(0,"title");
How to add also value?
checkedListBox1.Items.Insert(0, new ListBoxItem("text", "value"));
Try setting the DisplayMember and ValueMember properties. Then you can pass an anonymous object like so:
checkedListBox1.DisplayMember = "Text";
checkedListBox1.ValueMember = "Value";
checkedListBox1.Items.Insert(0, new { Text= "text", Value = "value"})
Edit:
To answer your question below, you can create a class for your item like so:
public class MyListBoxItem
{
public string Text { get; set; }
public string Value { get; set; }
}
And then add them like this:
checkedListBox1.Items.Insert(0, new MyListBoxItem { Text = "text", Value = "value" });
And then you can get the value like this:
(checkedListBox1.Items[0] as MyListBoxItem).Value

listbox items not displaying properly

I have a listbox and a ListItem object which I am adding to the listbox so that I can retrieve a value from the selected item which is different then the displayed member.
class ListItem
{
public string DisplayMember;
public string ValueMember;
public ListItem(string n,string v){
DisplayMember = n;
ValueMember = v;
}
}
public CompareTimeFramesForm()
{
InitializeComponent();
listBox1.Items.Add(new ListItem("# of Bookings", null));
listBox1.Items.Add(new ListItem("People", "guaranteed_count"));
}
This is a winform FYI.
The problem I am having is the item shown in the actual listbox has the object rather then the string I would like to be displayed in the first argument of the ListItem constructor.
It looks like Bookings.Helpers.ListItem rather then "# of Bookings"
In the designer I changed the displayMember property to DisplayMember and its not working.
From MSDN:
When an object is being added to the ListBox, the control uses the text defined in the ToString method of the object unless a member name within the object is specified in the DisplayMember property.
ListBox will convert item to string calling ToString(). In your case you just need to change your ListItem class like this:
class ListItem
{
public string DisplayMember;
public string ValueMember;
public ListItem(string n,string v) {
DisplayMember = n;
ValueMember = v;
}
public override string ToString() {
return DisplayMember;
}
}
As alternative you can se the DisplayMember property (in designer or with code) to use your property (you called that property DisplayMember but its name is free because it must be specified and it doesn't use any convention):
listBox1.DisplayMember = "DisplayMember";
try this it should work for you!
class ListItem
{
public string DisplayMember;
public string ValueMember;
public ListItem(string n,string v){
DisplayMember = n;
ValueMember = v;
}
}
public CompareTimeFramesForm()
{
InitializeComponent();
listBox1.Items.Add(new ListItem("# of Bookings", null).DisplayMember);
listBox1.Items.Add(new ListItem("People", "guaranteed_count").DisplayMember);
}

Bind values from a list array to listbox

Could any body give a short example for binding a value from list array to listbox in c#.net
It depends on how your list array is.
Let's start from an easy sample:
List<string> listToBind = new List<string> { "AA", "BB", "CC" };
this.listBox1.DataSource = listToBind;
Here we have a list of strings, that will be shown as items in the listbox.
Otherwise, if your list items are more complex (e.g. custom classes) you can do in this way:
Having for example, MyClass defined as follows:
public class MyClass
{
public int Id { get; set; }
public string Text { get; set; }
public MyClass(int id, string text)
{
this.Id = id;
this.Text = text;
}
}
here's the binding part:
List<MyClass> listToBind = new List<MyClass> { new MyClass(1, "One"), new MyClass(2, "Two") };
this.listBox1.DisplayMember = "Text";
this.listBox1.ValueMember = "Id"; // optional depending on your needs
this.listBox1.DataSource = listToBind;
And you will get a list box showing only the text of your items.
Setting also ValueMember to a specific Property of your class will make listBox1.SelectedValue containing the selected Id value instead of the whole class instance.
N.B.
Letting DisplayMember unset, you will get the ToString() result of your list entries as display text of your ListBox items.

C# combobox overridden ToString

I am experiencing some problems while working with ComboBox.
The display member for my combobox is not being populated by the overridden ToString method of class MAP.
Here is my code:
Form1.cs:
private void Form1_Load(object sender, EventArgs e) {
...
...
MAPList MAP = new MAPList();
comboBox1.DataSource = MAP.All;
comboBox1.ValueMember = "Code";
...
...
}
MAPList.cs:
public class MAPList {
public readonly List<MAP> All;
public MAPList() {
All = new List<MAP>();
var MapData = // Getting map data
foreach(MAP m in MapData) {
All.Add(new Map(m.Name, m.Code));
}
}
}
MAP.cs:
public class MAP {
public readonly string Name;
private string code;
public string Code { get { return code; } }
public RadioCode(string Name, string Code) {
this.Name = Name;
this.code = Code;
}
public override string ToString() {
return String.Format("{0}: {1}", Name, Code);
}
}
ToString will not be called if you set ValueMember. If you do not set ValueMember it will work as expected but then of course Code will not be used as the selected value of the ComboBox.
Alternatively, if you wish to use ValueMember you may also want to set DisplayMember. You can create a property on your MAP that is used for display, i.e.:
public class MAP
{
public readonly string Name;
private string code;
public string Code { get { return code; } }
public string Display { get { return ToString(); } }
public MAP(string Name, string Code)
{
this.Name = Name;
this.code = Code;
}
public override string ToString()
{
return String.Format("{0}: {1}", Name, Code);
}
}
In the form you can then set DisplayMember:
MAPList MAP = new MAPList();
comboBox1.DataSource = MAP.All;
comboBox1.ValueMember = "Code";
comboBox1.DisplayMember = "Display";
This is because you've set your ValueMember property to "Code", so the values in the combobox are not your Map objects but rather the strings corresponding to their Code properties.
If you remove this line:
comboBox1.ValueMember = "Code";
...it will work as you expect.
If you want the ComboBox to display its items according to your Map type's ToString method, then Jakob's answer is right on: create a property on your Map type that provides a string formatted exactly how you want it, and set the DisplayMember property of the ComboBox to the name of this property.
this could be because u r using ValueMember. use DisplayMember Property, add another property on the Map class in the get of this property return the formatted string.
I know this is an old post, but if someone wants to use ToString() without creating a property to just call ToString(), you'll have to explicitly set the DisplayMember value to an empty string like this:
Form1.cs:
private void Form1_Load(object sender, EventArgs e) {
...
...
MAPList MAP = new MAPList();
comboBox1.DataSource = MAP.All;
comboBox1.ValueMember = "Code";
comboBox1.DisplayMember = ""; // Explicitly set it to an empty String
...
...
}

Categories