Show Enum Description Instead of Name

10,829

Solution 1

If you keep this ItemsSource you will have to define a custom ItemTemplate as the DisplayMemberPath is just a path via which you will not be able to retrieve the description.

As for what the template should look like: You can bind a TextBlock to the enum value (the current DataContext) and pipe that through a ValueConverter using Binding.Converter. The code would just be some reflection to retrieve the Description (GetType, GetCustomAttributes etc.)

Alternatives are a custom method that return a usable collection right away (and is used in the ObjectDataProvider) or a custom markup extension which does the same thing.


Method example if we are talking about a ComponentModel.DescriptionAttribute:

public static class EnumUtility
{
    // Might want to return a named type, this is a lazy example (which does work though)
    public static object[] GetValuesAndDescriptions(Type enumType)
    {
        var values = Enum.GetValues(enumType).Cast<object>();
        var valuesAndDescriptions = from value in values
                                    select new
                                        {
                                            Value = value,
                                            Description = value.GetType()
                                                .GetMember(value.ToString())[0]
                                                .GetCustomAttributes(true)
                                                .OfType<DescriptionAttribute>()
                                                .First()
                                                .Description
                                        };
        return valuesAndDescriptions.ToArray();
    }
}
<ObjectDataProvider x:Key="Data" MethodName="GetValuesAndDescriptions"
                    ObjectType="local:EnumUtility">
    <ObjectDataProvider.MethodParameters>
        <x:TypeExtension TypeName="local:TestEnum" />
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ListBox ItemsSource="{Binding Source={StaticResource Data}}"
         DisplayMemberPath="Description"
         SelectedValuePath="Value"/>

Solution 2

This answer is an addition on H.B.'s answer I implemented for my own application:

Check if the Description attribute is added:

Description = (value.GetType().GetMember(value.ToString())[0].GetCustomAttributes(true).OfType<DescriptionAttribute>().Count() > 0 ? 
                                                value.GetType().GetMember(value.ToString())[0].GetCustomAttributes(true).OfType<DescriptionAttribute>().First().Description 
                                                : value)

And Set the following attribute to make sure the correct ID's are used: SelectedValuePath="Value"

Share:
10,829
Nathan Tornquist
Author by

Nathan Tornquist

I am a full stack developer working in Chicago. I primarily develop for iOS and Node, but have a background in Ruby, Java, and C#. I dabble in hardware prototyping, and have a degree in Computer Engineering from Purdue. Outside of work, I enjoy playing the trumpet and reading novels.

Updated on June 07, 2022

Comments

  • Nathan Tornquist
    Nathan Tornquist almost 2 years

    I had databinding set up like this:

    ItemsSource="{Binding Source={my:Enumeration {x:Type credit:OccupationCategory}}}"
                          DisplayMemberPath="Description"
                          SelectedValue="{Binding EmplType}"
                          SelectedValuePath="Value"/>
    

    and it worked really well. Do to a change in the larger software design I can no longer have anything that generates an INotifyPropertyChanged Event so that type of databinding doesn't work. Instead I am manually setting the selectedIndex and building the options from code like this:

    ItemsSource="{Binding Source={StaticResource ResidenceOwnershipType}}"/>
    

    which references

    <UserControl.Resources>
        <ObjectDataProvider x:Key="ResidenceOwnershipType" MethodName="GetValues" ObjectType="{x:Type System:Enum}" >
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="credit:ResidenceOwnershipType" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </UserControl.Resources>
    

    That works as far as the building of the list options is concerned and the linking of all of my data, but I can't get the comboboxes to show the description tag in the enumeration instead of the actual text.

    I've tried something like this:

    DisplayMemberPath="Description"
    

    but that wasn't correct. How would I go about doing this?

    EDIT:

    My Enum:

    [DataContract]
    public enum ResidenceOwnershipType
    {
        [Description("")]
        None = 0,
        [Description("Owns Home Outright")]
        OwnsHomeOutright = 1,
        [Description("Buying Home")]
        BuyingHome = 2,
        [Description("Renting/Leasing")] //Weird order here reflects RouteOne website
        RentingLeasing = 4,
        [Description("Living w/Relatives")]
        LivingWithRelatives = 3,
        [Description("Owns/Buying Mobile Home")]
        MobileHome = 5,
        [Description("Unknown")]
        Unknown = 6
    }