6
\$\begingroup\$

I had to jump through some hoops to get a localized enum working. I went through dozens of SO articles that never actually answered the relevant conundrum with a working solution. So I made my own:

I have two resource files: LocalizedStrings.resx and LocalizedStrings.es-MX.resx With two corresponding lines:

GENDER_FEMALE Female
GENDER_MALE Male

... and ...

GENDER_FEMALE Mujer
GENDER_MALE Hombre

... respectively.

I have an Enum Extension:

public static class EnumExtensionMethods
{
 public static string GetDisplay(this Enum enumValue)
 {
 object[] attr = enumValue.GetType().GetField(enumValue.ToString())
 .GetCustomAttributes(typeof(DisplayAttribute), false);
 return attr.Length > 0
 ? ((DisplayAttribute)attr[0]).GetName()
 : enumValue.ToString();
 }
}

My actual Enum:

public enum Gender
{
 [Display(ResourceType = typeof(LocalizedStrings), Name = "GENDER_MALE")]
 Male = 1,
 [Display(ResourceType = typeof(LocalizedStrings), Name = "GENDER_FEMALE")]
 Female = 0
}

I load the values into a Winforms ComboBox’s items, (I could not get binding it to an entity to work) with the OnLoad event:

foreach (Gender value in Enum.GetValues(typeof(Gender)))
{
 GenderComboBox.Items.Add(new KeyValuePair<string, Gender>(value.GetDisplay(), value));
}
GenderComboBox.DisplayMember = "Key";
GenderComboBox.ValueMember = "Value";
GenderComboBox.SelectedIndex = 1;

Finally, I have to set the entity value with this event:

private void GenderComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
 if (!GenderComboBox.Focused)
 return;
 if (GenderComboBox.SelectedIndex == -1)
 return;
 KeyValuePair<string, Gender> gender = (KeyValuePair<string, Gender>) GenderComboBox.SelectedItem;
 Person person = (Person)PersonBindingSource.Current;
 person.Gender = gender.Value;
}

All of the previous code just to get a Localized Enum. Is there not a better way?

asked Aug 22, 2016 at 17:41
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

You really shouldn't mix event and data-binding together.

The proper way of updating value from UI, would be using ComboBox.DataBindings.Add(Binding). And, not patching it via ComboBox.SelectedSomethingChanged.

Here is how I would do it :

// mock model
var person = new Person { Gender = Gender.Female };;
// mock data source
var personBindingSource = new BindingSource();
personBindingSource.DataSource = new List<Person> { person };
// initialize
var combo = new ComboBox();
// you may want to set DropDownStyle to ComboBoxStyle.DropDownList
// from the designer to disable text input.
//
// choose one of the two below :
// combo.DisplayMember = "Value";
// combo.ValueMember = "Key";
// combo.DataSource = EnumHelper.GetEnumDefinitions<Gender>();
combo.BindTo<Gender>();
// databind
combo.DataBindings.Add(new Binding(
 nameof(combo.SelectedValue), personBindingSource, nameof(person.Gender), false, DataSourceUpdateMode.OnPropertyChanged));

public static class EnumHelper
{
 public static IList GetEnumDefinitions<TEnum>()
 where TEnum : struct, IConvertible
 {
 var type = typeof(TEnum);
 if (!type.IsEnum)
 throw new ArgumentException($"'{type}' is not an enum type.");
 return type
 .GetFields(BindingFlags.Public | BindingFlags.Static)
 .ToDictionary(x => (TEnum)x.GetValue(null), x =>
 x.GetCustomAttribute<DisplayAttribute>()?.GetName() ?? x.GetValue(null).ToString()
 )
 .ToList();
 }
 public static void BindTo<TEnum>(this ComboBox combo)
 where TEnum : struct, IConvertible
 {
 combo.DisplayMember = "Value";
 combo.ValueMember = "Key";
 combo.DataSource = EnumHelper.GetEnumDefinitions<TEnum>();
 }
}
answered Aug 22, 2016 at 19:30
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.