Introduction
This article demonstrates how to bind a combobox with sorted names from an enum. This can all be accomplished in XAML without code in the XAML code behind page.
Background
I'm in the middle of preparing for a Code Camp presentation this weekend and was reviewing all my code. I noticed an opportunity to refactor some code and then got the idea to just loosen the code and data bind using XAML.
I had previously read Beatriz Costa's great article, How can I bind an ItemsControl to the values of an enumeration? so I knew binding to the names of an enum was real simple.
Question was, how can I sort the names, keep my simple data binding "AND make the code reusable"?
Scenario
Below is an Enum that has been declared. The order of the members in this enum is not friendly to a user using a combobox. We want to use the Enum, but display the member names sorted alphabetically.
Public Enum ZooCreatures
Zebra
Snake
Tiger
Rabbit
Hamster
Mouse
Cat
Dog
Turtle
Lion
Cow
End Enum
Reusable Helper Function
We first need to crank up a reusable helper function that will take an enum type and return a sorted string array that we can use as an ItemsSource for our comboboxes.
For this really simple demo, I've just added the class shown below to the project. Normally, you would put this in your own helper class or help class project where you put all your other helper functions.
Public Class Helpers
Public Function GetSortedEnumNames(ByVal t As Type) As String()
'first do a sanity check, make sure the developer
'is passing us an enum
If t.BaseType.FullName = "System.Enum" Then
Dim strOut() As String = [Enum].GetNames(t)
Array.Sort(strOut)
Return strOut
Else
Throw New ArgumentException("Must be an enum", "t")
End If
End Function
Public Sub New()
End Sub
End Class
How Does It Work
- Sanity Check: use the
BaseType.FullName property of the passed in type to ensure that the calling code actually passed in an Enum, if not, Throw New ArgumentException.
- Get An
Array Of Names From The Enum : use the GetNames shared (static for the C#'ers) method to return an unsorted list of the names in the Enum type. Actually, the names are returned in the order that the Enum type is declared.
- Sort Array : use the
Array.Sort shared method to sort the string array of names.
- Return Sorted Names Array : how easy is this? {remember the old days?}
Let's Do Some Binding!
Here is our very simple, no code WPF Databinding in action. Entire XAML file:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:FillComboboxWithSortedEnum"
x:Class="FillComboboxWithSortedEnumDemo"
Title="Fill Combobox With Sorted Enum"
Height="100"
Width="285"
>
<Window.Resources>
<ObjectDataProvider x:Key="zooCreatureHelpersDS"
d:IsDataSource="True" MethodName="GetSortedEnumNames"
ObjectType="{x:Type local:Helpers}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:ZooCreatures"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="cboZooCreatures"
IsSynchronizedWithCurrentItem="True" Width="Auto"
ItemsSource="{Binding Mode=OneWay,
Source={StaticResource zooCreatureHelpersDS}}"/>
</StackPanel>
</Window>
Breaking It Down
Provider
- Really important to get your namespaces correct and you'll need them all or else you won't be compiling your project any time soon.
- Need to set up an
ObjectDataProvider for each Enum type that you want to data bind to. In our project we only have one combobox that needs to data bind to an Enum, so we'll just set up one ObjectDataProvider.
- The
ObjectDataProvider resource needs a key so that we can reference this resource in the XAML code. In this case, I named the key zooCreatureHelpersDS.
- The
MethodName="GetSortedEnumNames" property instructs the ObjectDataProvider resource to use the GetSortedEnumNames method. This is the name of our above helper method.
- The
ObjectType="{x:Type local:Helpers}" property instructs the ObjectDataProvider resource to use the class Helpers from the name space, FillComboboxWithSortedEnum. Notice how "local" is mapped to our class, FillComboboxWithSortedEnum.
- Now we need to pass in the correct parameter to the
GetSortedEnumNames method. This is easily accomplished using the <ObjectDataProvider.MethodParameters>
- The
<x:Type TypeName="local:ZooCreatures"/> property instructs the <ObjectDataProvider.MethodParameters> resource to pass the Type ZooCreatures to our helper.
Consumer
- Utilizing our new sorted
array of Enum element names is super easy in XAML!
- The
ItemsSource="{Binding Mode=OneWay, Source={StaticResource zooCreatureHelpersDS}}" property of our combobox is bound to the StaticResource zooCreatureHelpersDS we just created.
History
- 19 June 2007 : Initial Release