I have read lots of useful posts on the topic of the Winforms ComboBox ValueMember property, but none of them have answered my specific question. First, I will describe a simple example that works just fine, then I will describe how I want to change it, and ask how to do that (I will also offer one of my attempts).
First, the working example. Just a form with a comboBox control, and this code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.DataSource = Enum.GetValues(typeof(Enum1));
comboBox1.SelectedItem = Enum1.MultiWordValue2;
}
}
public enum Enum1 : int
{
Undefined,
MultiWordValue1,
MultiWordValue2
}
No problem, this works just fine. I run the app and the comboBox gets the appropriate items, and selects the appropriate value.
However, these enum values are ugly, and I want my users to have a better experience, so I create an extension method to give the values better a display.
public static class ExtensionMethods
{
public static string ToDisplayString(this Enum1 me)
{
switch (me)
{
case Enum1.MultiWordValue1:
return "Multi Word Value 1";
case Enum1.MultiWordValue2:
return "Multi Word Value 2";
default:
return string.Empty;
}
}
}
My question is, how best do I utilize this extension method while preserving the ability to build the comboBox items from the list of enum values, and be able to set the selected comboBox item (or value) by the enum value?
Below is my first attempt. I create a simple class to wrap the enum value and display string and set the comboBox DisplayMember and ValueMember to the properties of the new class. This partially works; the items of the combobox populate correctly with the display value, but I cannot set the SelectedValue:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.DisplayMember = "Display";
comboBox1.ValueMember = "Value";
foreach (Enum1 e in Enum.GetValues(typeof(Enum1)))
comboBox1.Items.Add(new ValueDisplayEnum(e, e.ToDisplayString()));
comboBox1.SelectedValue = Enum1.MultiWordValue2;
}
}
public enum Enum1 : int
{
Undefined,
MultiWordValue1,
MultiWordValue2
}
public static class ExtensionMethods
{
public static string ToDisplayString(this Enum1 me)
{
switch (me)
{
case Enum1.MultiWordValue1:
return "Multi Word Value 1";
case Enum1.MultiWordValue2:
return "Multi Word Value 2";
default:
return string.Empty;
}
}
}
public class ValueDisplayEnum
{
public object Value { get; set; }
public string Display { get; set; }
private ValueDisplayEnum() { }
public ValueDisplayEnum(object _Value, string _Display)
{
Value = _Value;
Display = _Display;
}
}
Why doesn't setting the SelectedValue this way work? And how do I accomplish a comboBox of enums with better display strings?
Aside: I thought it might be because the underlying data type of the Value property of ValueDisplayEnum is an object, and not Enum1. However, if I change the type to Enum1, the SelectedValue still doesn't set correctly.
Thanks for any help!
Edit 1: Specifying one solution based on the suggestion by Mike:
Added the following templatized method:
public static void SetEnumCombo<T>(ComboBox _ComboBox, T _Value)
{
foreach (ValueDisplayEnum vde in _ComboBox.Items)
if (((T)vde.Value).Equals(_Value))
_ComboBox.SelectedItem = vde;
}
Instead of assigning SelectedValue or SelectedItem directly, called this:
foreach (Enum1 e in Enum.GetValues(typeof(Enum1)))
comboBox1.Items.Add(new ValueDisplayEnum(e, e.ToDisplayString()));
SetEnumCombo(comboBox1, Enum1.MultiWordValue2);
And everything worked like a charm. I'm still not sure why setting by value doesn't work, but this is a very compact resolution to the problem. But not as compact as response marked as the answer!
In your first attempt, you could select desired item with:
comboBox1.SelectedItem = comboBox1.Items.Cast<ValueDisplayEnum>().First(x => (Enum1)x.Value == Enum1.MultiWordValue2);