Yet another coding blog covering everything from C#, WPF, SQL, and Silverlight to any other random thought that passes my way…
RSS icon Home icon
  • Silverlight 4 ComboBox databinding to an Enum

    Posted on April 8th, 2010 biggert 2 comments

    As you probably know, databinding to an enum in WPF is terribly easy with a few simple lines of XAML code like so:

    <ObjectDataProvider x:Key="ZoomOptions"
    MethodName="GetNames"
    ObjectType="{x:Type sys:Enum}"
    >
    <ObjectDataProvider.MethodParameters>
    <x:Type TypeName="bll:enumZoomOptions"/>
    </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    
    <ComboBox ItemsSource="{Binding Source={StaticResource ZoomOptions}}" />
    

    And that’s it…  the ComboBox has a nice pretty list of all your enum’s values.

    But in Silverlight 4,  not only is the Enum.GetNames method unavailable, the ObjectDataProvider XAML syntax used above also is a stretch. So here’s how I got by…

    First off, to lay a few things out, the nice thing about the WPF implementation above is that when we add a new value to the enumeration named ‘enumZoomOptions’, we simply add it and don’t have to go change our XAML (or any other code). I wanted to make sure I kept this flexibility. Also, my example code is structured around the MVVM framework but I’d do it the exact same way if code-behind was in play.

    So let’s get started, first, I create my enumeration:

    public enum ZoomOption : int
    {        Fifty = 50,        SeventyFive = 75,        OneHundred = 100    }
    

    Now I set up my properties on my ViewModel to store the enum data:

    private ObservableCollection _zoomOptions;
    public ObservableCollection ZoomOptions
    {
    get
    {
    return _zoomOptions;
    }
    
    set
    {
    _zoomOptions = value;
    RaisePropertyChanged("ZoomOptions");
    
    }
    }
    
    private ZoomOption _selectedZoomOption = ZoomOption.OneHundred;
    public ZoomOption SelectedZoomOption
    {
    get
    {
    return _selectedZoomOption;
    }
    
    set
    {
    _selectedZoomOption = value;
    RaisePropertyChanged("SelectedZoomOption");
    
    }
    }
    

    One note here is the SelectedZoomOption property is not really needed for this specific example except for setting the SelectedItem property so I can default the selected value in the databound ComboBox to 100.

    Now the fun part, I need to populate my ZoomOptions collection with the values from my enumeration. In my ViewModel constructor, I do this:

    // Get the type
    Type enumType = typeof(ZoomOption);
    
    // Set up a new collection
    ZoomOptions = new ObservableCollection();
    
    // Retrieve the info for the type (it'd be nice to use Enum.GetNames here but alas, we're stuck with this)
    FieldInfo[] infos;
    infos = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);
    
    // Add each proper enum value to the collection
    foreach (FieldInfo fi in infos)
    {
    ZoomOptions.Add((ZoomOption)Enum.Parse(enumType, fi.Name, true));
    }
    

    So this effectively iterates through the enumeration value and adds each one to the collection.

    Now the easy part… I simply bind my ComboBox to the collection of enum values and voila, it’s populated.

    <ComboBox Grid.Row="1" Width="100" x:Name="ZoomComboBox" Height="25" ItemsSource="{Binding ZoomOptions}" />
    

    The problem now though is it really isn’t displayed like I want it so simply override the datatemplate and use a converter to show the numerical value with the ‘%’ character afterwards. So I make it a little more user friendly by overriding the DataTemplate and providing a converter to show the actual value of the enum followed by the ‘%’ character.

    Here’s the converter:

    public class ZoomOptionDisplayConverter : IValueConverter
    {
    
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    // This converts out enum values to a more acceptable display text
    if (value != null)
    {
    return System.Convert.ToInt32(value).ToString() + "%";
    }
    else
    return null;
    
    }
    
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    throw new NotImplementedException();
    }
    }
    

    Here’s the new XAML for the ComboBox:

    <UserControl.Resources>
    
    <local:ZoomOptionDisplayConverter x:Key="ZoomOptionDisplayConverter" />
    
    </UserControl.Resources>
    
    <ComboBox Grid.Row="1" Width="100" x:Name="ZoomComboBox" Height="25" ItemsSource="{Binding ZoomOptions}" SelectedItem="{Binding SelectedZoomOption, Mode=TwoWay}" >
    <ComboBox.ItemTemplate>
    
    <DataTemplate>
    
    <TextBlock Text="{Binding Converter={StaticResource ZoomOptionDisplayConverter}}" />                </DataTemplate>
    
    </ComboBox.ItemTemplate>
    
    </ComboBox>
    

    And our final result:

    So I posted up an example project you can download here. In this example project, I go a few steps farther and actually use the enumeration value selected in the combobox for a realistic use case (I hate examples that you’d never use in the real world). So upon selection in the combobox, the text above it will both show the selected value as well as change the scale to the selected value… effectively performing a “zoom”.

    You can try it out here:

    Install Microsoft Silverlight

     

    2 responses to “Silverlight 4 ComboBox databinding to an Enum” RSS icon


    Leave a reply