-
Silverlight 4 ComboBox databinding to an Enum
Posted on April 8th, 2010 2 commentsAs 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:
-
Silverlight 4 RC WebBrowser’s lack of binding support (for MVVM)
Posted on April 7th, 2010 2 commentsRecently in a new project powered by Silverlight 4, I’ve begun the shift away from code-behind and into the MVVM world. Honestly I was skeptical and maybe I’ll have a future post explaining my thoughts on it but let’s just say that both Laurent Bugnion’s views on MVVM as well as his excellent MVVM Light Toolkit definitely made me much more comfortable. Since our initial prototype was code-behind, I was able to compare apples to apples to our MVVM prototype and I must say, I’ve had a fun time rewriting my original code to adapt to the bind-ability inspiration of MVVM… for the better I must say.
Anywho, enough about my experiences with MVVM, this post is specifically about the WebBrowser control in Silverlight 4 RC… and to be even more specific, it’s NavigateToString() method. In an MVVM environment where binding is your friend, we’ve got a nice implementation of using the WebBrowser control and binding it to a property in our VM which represents a URL. All fun and games there… but if you want to take advantage of the cool new SL4 NavigateToString() method with proper binding in MVVM, you’re out of luck (at least I think). In order for us to use this method, we used the excellent Messenger class that the MVVM Light toolkit provides which allows our ViewModel to talk to the View.
Just to lay it out… we did this:
- In our ViewModel, on our Set method of our property, we set up message of type string using the Messenger and send the string containing HTML out.
- In our View’s code-behind’s (blech) constructor, we set up the Messenger to receive the string message and call the WebBrowser’s NavigateToString() method on the value.
So we effectively have a datagrid whose SelectedItem is bound to this property so when the user selects an item in the grid, this Messenger is called and the HTML string is sent… we could also easily do this with commanding. The Messenger then receives the HTML string, sets the WebBrowser control to navigate to it, and voila, we have content in our WebBrowser.
Microsoft, please make this functionality bindable in the future where, in our MVVM setup, we can simply bind this in our View to a property in the ViewModel and we’d be set.
FYI – If this is already available or there is a better way to do this, let me know so I can fix my code cause right now I feel violated

