Jerry Nixon @Work: Binding to an ENUM in Windows 8

Jerry Nixon on Windows

Monday, March 4, 2013

Binding to an ENUM in Windows 8

imageYou create a Settings flyout for your app so users can configure their experience. Sometimes, your settings are based on a ENUM that you use throughout your app. But how do you bind to an ENUM in XAML?

Our sample ENUM

The first thing you should know is that you cannot really bind to a ENUM, but with some code we can expose an ENUM as a type you can bind to. Let’s take a look at the code:
In the code above, we have our ENUM. We have two custom attributes in our ENUM. The first attribute is System.ComponentModel.DataAnnotations.DisplayAttribute which we use to change the presentation of our ENUM in the UI – this is mostly because spaces and special characters aren’t allowed in an ENUM. The second attribute is System.ComponentModel.DefaultValueAttribute which we use to indicate which ENUM member should be selected by default – before the user makes a manual selection.

Binding to an enum

To expose our ENUM as a type we can bind to, we do this:
In the code above, we create the property ThemeItemsSource. ThemeItemsSource can be bound to a List’s ItemsSource property. Creating a static cache of the list helps with performance of our application as the user may return to our flyout more than once, and we might reuse our view model in several locations. GetEnumAsList() is the reusable method that parses an ENUM.

Letting the user choose

Showing the list of options to the user is only the first step in a settings dialog. The second step is to let them choose a member and store that member in our app’s settings. We need a property that can be bound to a List’s SelectedItem property. Like this:
In the code above, we create the ThemeSelectedItem property which we can bind to the SelectedItem of our List. As long as we define the binding Mode as TwoWay, when the user selects an option in the list, ThemeSelectedItem will be set. If you look closely, ThemeSelectedItem persists its value in the static Theme property. A static property allows you to reference this setting value from any other part of the application without having to instantiate the view model or some other class.
The static Theme property uses my StorageHelper to store the value of the property across user sessions. In other words, when the user closes your app and re-opens it, the value they selected will be retained. This adds to a good user experience.

Determining the default

You might notice a reference to the GetEnumDefault() method. This method is responsible for parsing the ENUM and finding the member decorated with DefaultValueAttribute, if there is one. This is handy because, at first, the user may not have chosen anything and you need a value to use. This method looks like this:
In the code above we look for custom attributes and return the DefaultValue if there is one. If there isn’t one then we get the ENUM returned by default() – which is either the first in the ENUM or the one with an integer value of 0 (zero). The best part of this generic method is that you can use it again and again. If you don’t want to use the Default attribute, it won’t break anything.

Displaying the grid

We aren’t done though. In order to display this in our XAML all we need to do is to make reference to our view model and bind to the two properties: ThemeItemsSource and ThemeSelectedItem. It’s really as simple as that, and it looks like this:
In the code above, we generate a UI for the user. We present all the ENUM values in a GridView with ThemeItemsSource and bind the currently selected (or default) item to ThemeSelectedItem. I mentioned it before, but I want to reiterate that SelectedItem is bound using the Mode of TwoWay so that when the user makes a selection that action is written back to the view model.

Displaying custom text

Another interesting part of that XAML is the use of the EnumConverter. This converter looks at the value of the ENUM member to display and shows it. But if the developer has leveraged the DisplayAttribute, then the converter will use whatever is provided there. Using a DisplayAttribute might be where you add logic to enable localization of your app.
The converter looks like this:
In the code above, we create a simple IValueConverter which accepts an ENUM member and interrogates it to see if there is a custom DisplayAttribute with which to switch the default string. Reflection is far less costly than in early .Net, but it’s still not free. Since this is a settings flyout, it’s a worthwhile cost. But be aware when using this technique in large grids – you could see a performance impact. Odds are, if your ENUM is less than 100 members, you won’t notice anything.

imageThat’s it, by the way!

The actual UI will be up to you. To the right you can see what mine looks like. It’s cool how it dynamically updates the Settings UI when I update the ENUM. There’s a lot of power and reusability here; I hope this helps you make better apps.

Want the code? Get it here.

Oh, did I mention this works in design-time?
Best of luck!