Displaying sorted enum values in a ComboBox

Recently Karl Shifflett, a budding WPF developer and author of articles about WPF, posted an article on CodeProject.  The article demonstrates how to bind a ComboBox to a sorted collection of enum values.  His approach aims to be XAML-only, and it came pretty close.  After reading his article I realized that it is possible to take it one final step further toward being purely XAML.

His technique involves using an ObjectDataProvider to call a method in the code-behind which returns a sorted collection of enum values.  The method in the code-behind is responsible for sorting the enum values.  His approach is perfectly valid, and works just fine, but it does involve a dependency on the code-behind.  For something as presentation-oriented as displaying a sorted list of values, I don’t think that the XAML file should depend on the code-behind.

Here is a XAML-only approach to solving the problem.  First we need an unsorted enum:

Sorted enum in ComboBox (enum)

Next we need to create a sorted list of values in the enum, and then bind a ComboBox to that list:

Sorted enum in ComboBox (XAML)

(The System.ComponentModel namespace referenced above lives in the WindowsBase assembly.  I had to clip the assembly name in the image so that it would fit in my blog properly.)

The basic idea here is that we create a CollectionViewSource which, in turn, uses an ObjectDataProvider to get an unsorted list of values for the Animals enum.  The CollectionViewSource also has a SortDescription added to it.  That causes the list of enum values to be sorted in ascending order, based on their names.

Once that data source is declared we bind a ComboBox to it.  The ComboBox looks like this when you run the demo app:

Sorted enum in ComboBox (screenshot)

You can download the demo app here: Sorted enum in ComboBox (demo project)  Be sure to change the file extension from .DOC to .ZIP and then decompress it.

21 Responses to Displaying sorted enum values in a ComboBox

  1. Edward Poore says:

    I’m just curious as to why you always post code as an image, surely there must be a way to paste it as text?

    Note, I’ve never used a blogging tool so can WordPress receive HTML? If so there is a utility for copying code from VS to HTML.

    Just wondering because of the number of times I’ve tried to select the code to paste into an editor… :doh:

  2. Josh Smith says:

    Ed,

    I always post code as images because it makes my life much easier. I encountered a lot of trouble/headache/frustration when trying to paste code as text, particularly XAML because of the overlap between it and HTML syntax. The real problem comes into play when I post something, and then go back in later to edit it. The XAML can get “munged” by whatever handles HTML for my blog…true Hell.

    If I include a code snippet, I always post a link to a demo project for download at the end of the post.

    Thanks,
    Josh

  3. Rob says:

    That seems like an awful lot of XAML just to do something so simple. Why not just use some code?

  4. Josh Smith says:

    Rob,
    I agree, that is a lot of XAML for a simple task. Whether you use only XAML, only code, or a mix is largely a matter of personal preference. Karl’s article aimed for a XAML-only implementation, which is the goal I set for myself.

    There are some scenarios where using a XAML-only approach is preferred. For instance, if you are working in a dynamic UI context (where the UI is loaded from XAML at runtime) then this type of approach is better because it reduces the coupling between the dynamically loaded XAML and the application which consumes it. For more info about dynamic UIs in WPF, check this article out: http://www.codeproject.com/WPF/DynamicUIs.asp
    Thanks,
    Josh

  5. Ted says:

    Is it possible to somehow define the enum collection in XAML aswell? Just curious, not sure why anyone would want to.🙂

  6. Josh Smith says:

    Ted,

    No, it is not possible to define an enum in XAML. You have to do that in code. If all you’re looking for is a list of names/identifiers, and want to create it in XAML, I suppose you could create an array of strings in XAML and then bind to that.

    Josh

  7. Axel says:

    This approach just creates localization nightmares.

  8. Josh Smith says:

    Axel,

    That is true. If localization is a requirement then this technique is inappropriate. I doubt that there is a clean way to implement this functionality in XAML, when localization must be taken into account. Do you know of one?

    Josh

  9. Jérôme says:

    Josh,

    I didn’t succeed in using your code with an enum inside a class:
    Suppose your enum is defined inside a class Zoo: what syntax should I use?
    I tried but that does not work.

    Any idea?

    Thank you.

    Jérôme

  10. Josh Smith says:

    Jerome,

    This should work: Zoo+EnumName

    Josh

  11. Jérôme says:

    Indeed trouble when pasting XAML code, let’s try like this: I tried < x:Type TypeName=”local:Zoo.Animals” /&t; but that does not work.

    Jérôme

  12. Josh Smith says:

    Did you try using + instead of . ?

  13. Jérôme says:

    Yes, it works🙂 I wonder why we have to use + but that’s fine if it works.

    Thanks a lot, Josh.

    Jérôme.

  14. Dan says:

    Hi Josh,

    Can you give me a quick clue as to how you’d go on to bind the SelectedItem of the combobox to something? I’m using this technique within a DataTemplate for a list box (i.e. a list of items with a type editor for each).

    I tried setting it up as follows, but found that *every* list item changed when I altered the value in a single combo! No clue why!

    Cheers,

    Dan

  15. Dan says:

    Whoops… code didn’t work…

    If you reply I’ll send some!!

  16. Iniavel says:

    What is GetNames in the above mentioned example?

  17. Ron says:

    Is there a way to use this technique get used with binding selected item to a value in a data source? i.e.
    Window1.xaml.cs
    public partial class Window1 : System.Windows.Window
    {
    public Window1()
    {
    InitializeComponent();
    Pet pet = new Pet();
    this.DataContext = pet;
    }
    }
    public class Pet
    {
    public Pet() { MyPet = Animals.Mouse; }
    public Animals MyPet { get; set; }
    }
    Window1.xaml …
    ComboBox
    ItemsSource=”{Binding Source={StaticResource SortedAnimalsView}}”
    SelectedItem=”{Binding Path=MyPet}”
    VerticalAlignment=”Center”

    The above idea compiles, but does the combo box does not initialize to the selected item to “mouse”. Any ideas?

  18. Zuff says:

    Hi all,

    I tried to do a hybrid with this website http://www.codeproject.com/KB/cs/LocalizingEnums.aspx
    However, even If I changed my culture to zh-CN, it wouldn’t load the text string stored in the Resource.zh.resx filed under the Properties folder, similar to the default Resource.resx.

    What did I do wrongly?

    Thanks
    Zuff

  19. Zuff says:

    Opps..
    I did a silly mistake,
    I should have used Resource.zh-CN.resx instead.

    public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context,
    System.Globalization.CultureInfo culture, object value, Type destinationType)
    {

    //However I have to hardcode this part, in order to see that the Chinese text is loaded.
    culture = new CultureInfo(“zh-CN”);
    if (value != null && destinationType == typeof(string))
    {
    object result = (_isFlagEnum) ?
    GetFlagValueText(culture, value) : GetValueText(culture, value);
    return result;
    }

    ….
    If not it will only load the enum text from the english resource file.
    How do I change the culture?
    Thread.CurrentThread.CurrentCulture = new CultureInfo(“zh-CN”);
    but this dun seesm to be working.

    My guess is because my WPF that referencing to the Gender enum and the other neccessary file are in different assembly.

    i.e.:
    UI in XXX.exe
    Models, enum are in XXX.Domain.exe

    Any advices?

    Thanks,
    Zuff

%d bloggers like this: