6

I have the following enum:

public enum ViewMode
{
    [Display(Name = "Neu")]
    New,
    [Display(Name = "Bearbeiten")]
    Edit,
    [Display(Name = "Suchen")]
    Search
}

I'm using xaml and databinding to show the enum in my window:

<Label Content="{Binding CurrentViewModel.ViewMode}" Grid.Column="2" VerticalContentAlignment="Bottom" Height="43" HorizontalContentAlignment="Right"/>

But this doesn't show the display name attribute. How can I do so?

In my viewModel I can get the display name attribute by using an extension method:

public static class EnumHelper
{
    /// <summary>
    /// Gets an attribute on an enum field value
    /// </summary>
    /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
    /// <param name="enumVal">The enum value</param>
    /// <returns>The attribute of type T that exists on the enum value</returns>
    public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute
    {
        var type = enumVal.GetType();
        var memInfo = type.GetMember(enumVal.ToString());
        var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
        return (attributes.Length > 0) ? (T)attributes[0] : null;
    }
}

Usage is string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;. However, this doesn't help in XAML.

mosquito87
  • 4,270
  • 11
  • 46
  • 77
  • 1
    You can use a `IValueConverter` in your binding to do the conversion of the Enum to the DisplayValue. http://www.wpftutorial.net/ValueConverters.html – Aron Feb 23 '15 at 10:46
  • http://stackoverflow.com/questions/3985876/wpf-binding-a-listbox-to-an-enum-displaying-the-description-attribute – Carbine Feb 23 '15 at 10:50
  • @CarbineCoder: I saw this example. What I didn't get is how to use it for just a label that has a binding to a viewmodel. – mosquito87 Feb 23 '15 at 13:18

1 Answers1

11

Create a class implementing the System.Windows.Data.IValueConverter interface and specify it as the binding's converter. Optionally, for easier usage, you can create a "provider" class implementing System.Windows.Markup.MarkupExtension (actually you can do both with just one class). Your end result could resemble this example:

public class MyConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((Enum)value).GetAttributeOfType<DisplayAttribute>().Name;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

And then in XAML:

<Label Content="{Binding CurrentViewModel.ViewMode, Converter={local:MyConverter}}" Grid.Column="2" VerticalContentAlignment="Bottom" Height="43" HorizontalContentAlignment="Right"/>
Grx70
  • 10,041
  • 1
  • 40
  • 55
  • Somehow this leads to a null reference exception?! – mosquito87 Feb 23 '15 at 13:40
  • @mosquito87 That's weird, the only possibilities that come to my mind are that either the `value` parameter of the `Convert` method is null or for some reason the `GetAttributeOfType` method returns null... Can you use the debugger to pinpoint the exact line on which the exception is thrown? – Grx70 Feb 23 '15 at 14:28
  • Ok, as silly as it seems to be, the `Convert` method tried to get a `System.ComponentModel.DescriptionAttribute` (I blindly followed your usage example) whereas the enum members are decorated with `System.ComponentModel.DataAnnotations.DisplayAttribute`, so no wonder `GetAttributeOfType` returned null. The issue was obscured by the fact that both these classes have `Description` property... Also, I think what you mean to do is to get the `Name` property. I've updated the answer accordingly. – Grx70 Feb 23 '15 at 14:33