Feeds:
Posts
Comments

Archive for July, 2010

If you have worked with Windows Presentation Foundation (WPF) you should be fully aware of the term data binding. As stated on the MSDN “data binding provides a simple and consistent way for applications to present and interact with data .” It also allows for a clean separation of business logic from the UI and should be used where applicable. A question I commonly see posted on forums is “How do I data bind to an enumeration?”. I hope to clearly address that question here so lets just jump into the code.

First you must create a new WPF project and declare an enumeration. For this example I have created a fruit enum as follows:

public enum Fruit
{
     apples,
     oranges,
     peaches,
     pears,
     strawberries,
}

My MainWindow.cs file will contain only the default constructor and one dependency property of type fruit. One thing to note about the DP is the UIPropertyMetadata. This provides the default value of apples for the DP since that is the first element in the enum. Here is the dependency property:


public Fruit Fruit
{
     get { return (Fruit)GetValue(FruitProperty); }
     set { SetValue(FruitProperty, value); }
}

public static readonly DependencyProperty FruitProperty =
     DependencyProperty.Register("Fruit", typeof(Fruit), typeof(MainWindow), new UIPropertyMetadata(new Fruit()));

Next is the EnumToBooleanConverter which can be seen below. If you are not familiar with binding converters have a look at this.

public class EnumToBooleanConverter : IValueConverter
{
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
          return value.Equals(parameter);
     }

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
          if (value.Equals(false))
               return Binding.DoNothing;
          else
               return parameter;
     }
}

Finally, here is all of the code contained in the MainWindow.xaml file. There are a few things to note here. First, we must include a reference to the local namespace so we can include the binding converter in the Windows.Resources tag. There are also two styles included in the Windows.Resources tag, one for the radio buttons and one for the stack panel. They are referenced using their x:Key.

You can see the binding syntax in the  IsChecked property of each radio button. It is important to note that we are NOT referring to the enums by simply using strings in xaml. We explicitly pass in the enum value using this syntax: x:Static local:Fruit.EnumValue.

<Window x:Class="DatabindingToAnEnumeration.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DatabindingToAnEnumeration"
        Title="MainWindow" Height="250" Width="300"
        x:Name="windowMain">

    <Window.Resources>
        <local:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>

        <Style x:Key="radioButtonStyle" TargetType="RadioButton">
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="Margin" Value="15,0"/>
        </Style>

        <Style x:Key="stackPanelStyle" TargetType="StackPanel">
            <Setter Property="Orientation" Value="Horizontal"/>
            <Setter Property="Background" Value="LightGray"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="Margin" Value="15,0"/>
        </Style>

    </Window.Resources>

    <Grid Background="LightYellow" Height="200">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <RadioButton Content="{x:Static local:Fruit.apples}" Grid.Row="0" Style="{StaticResource radioButtonStyle}"
                     IsChecked="{Binding Path=Fruit, ElementName=windowMain, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Fruit.apples}}"/>

        <RadioButton Content="{x:Static local:Fruit.oranges}" Grid.Row="1" Style="{StaticResource radioButtonStyle}"
                     IsChecked="{Binding Path=Fruit, ElementName=windowMain, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Fruit.oranges}}"/>

        <RadioButton Content="{x:Static local:Fruit.peaches}" Grid.Row="2" Style="{StaticResource radioButtonStyle}"
                     IsChecked="{Binding Path=Fruit, ElementName=windowMain, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Fruit.peaches}}"/>

        <RadioButton Content="{x:Static local:Fruit.pears}" Grid.Row="3" Style="{StaticResource radioButtonStyle}"
                     IsChecked="{Binding Path=Fruit, ElementName=windowMain, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Fruit.pears}}"/>

        <RadioButton Content="{x:Static local:Fruit.strawberries}" Grid.Row="4" Style="{StaticResource radioButtonStyle}"
                     IsChecked="{Binding Path=Fruit, ElementName=windowMain, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:Fruit.strawberries}}"/>

        <StackPanel Grid.Row="5" Style="{StaticResource stackPanelStyle}">
            <Label Content="Chosen Fruit: " VerticalAlignment="Center"/>
            <TextBlock Text="{Binding Fruit, ElementName=windowMain}" VerticalAlignment="Center" FontWeight="Bold"/>
        </StackPanel>
    </Grid>

</Window>

Just to show that everything is working as expected, I placed a stack panel at the bottom of the window. The panel has a TextBlock that is bound to our Fruit dependency property so you should see it update when you select different radio buttons. Here is an image of the running app.

Hopefully this clears things up. Enjoy!

Read Full Post »