views:

9071

answers:

6

I've got an enum like this:

public enum MyLovelyEnum
{
  FirstSelection,
  TheOtherSelection,
  YetAnotherOne
};

I got a property in my DataContext:

public MyLovelyEnum VeryLovelyEnum { get; set; }

And I got three RadioButtons in my WPF client.

<RadioButton Margin="3">First Selection</RadioButton>
<RadioButton Margin="3">The Other Selection</RadioButton>
<RadioButton Margin="3">Yet Another one</RadioButton>

Now how do I bind the RadioButtons to the property for proper two-way-binding?

+2  A: 

I would use the RadioButtons in a ListBox, and then bind to the SelectedValue.

This is an older thread about this topic, but the base idea should be the same: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4c9f-8d99-fecf45522395/

Martin Moser
You get a working **two-way**-binding this way?
Sam
I get a two-way binding doing a similar method using a ListBox and DataTemplate so you should.
Bryan Anderson
This bug: http://geekswithblogs.net/claraoscura/archive/2008/10/17/125901.aspx ruined a day for me.
Nasit
A: 

You could use the same solution that I suggested in this similar question: http://stackoverflow.com/questions/326802/how-can-you-two-way-bind-a-checkbox-to-an-individual-bit-of-a-flags-enumeration#375288

Tip: Don't spend too much time looking at the question; just take a look at the accepted answer.

PaulJ
+38  A: 

You could use a more generic converter

public class EnumBooleanConverter : IValueConverter
{
  #region IValueConverter Members
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
      return DependencyProperty.UnsetValue;

    if (Enum.IsDefined(value.GetType(), value) == false)
      return DependencyProperty.UnsetValue;

    object parameterValue = Enum.Parse(value.GetType(), parameterString);

    return parameterValue.Equals(value);
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
        return DependencyProperty.UnsetValue;

    return Enum.Parse(targetType, parameterString);
  }
  #endregion
}

And in the XAML-Part you use:

<Grid>
    <Grid.Resources>
      <l:EnumBooleanConverter x:Key="enumBooleanConverter" />
    </Grid.Resources>
    <StackPanel >
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=FirstSelection}">first selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=TheOtherSelection}">the other selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=YetAnotherOne}">yet another one</RadioButton>
    </StackPanel>
</Grid>
Lars
Worked like a charm for me. As an addition I modified ConvertBack to also return UnsetValue on "false", because silverlight (and presumably WPF proper) calls the converter twice - once when unsetting the old radio button value and again to set the new one. I was hanging other things off the property setter so I only wanted it called once.-- if (parameterString == null || value.Equals(false)) return DependencyProperty.UnsetValue;
Marc
Excelellent! works out of the box! +1
Oscar Cabrero
From what I can tell, this *must* be done unless the radio buttons are in different groups (and AFAIK buttons without GroupName set that have the same parent are by default in the same group). Otherwise, the calls to set the property "bounce" and result in odd behavior.
nlawalker
A: 

The answer doesn't work for me. When I select a differnt radio button in the UI, both radio buttons remain selected (probably because the radio buttons are not mutually exclusive because they are in different groups).

How do you alter the converter to handle this?

Brian
+14  A: 

Using the accepted answer, you must type out the enums as strings in xaml, and do more work in your converter than needed. Instead, you can explicitly pass in the enum value instead of a string representation:

ConverterParameter={x:Static local:YourEnumType.Enum1}

<StackPanel>
    <StackPanel.Resources>          
        <local:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />          
    </StackPanel.Resources>
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:YourEnumType.Enum1}}" />
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static local:YourEnumType.Enum2}}" />
</StackPanel>

Then simplify the converter:

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 DependencyProperty.UnsetValue;
        else
            return parameter;
    }
}
Scott
Simpler solution, I like it and it worked well.
Steve Cadwallader
I agree, I believe this is a better solution. Also, using this conversion will cause the project to break at compile time, not run time, if the enumeration values are changed, which is a big advantage.
CrimsonX
+1  A: 

For the EnumToBooleanConverter answer: Instead of returning DependencyProperty.UnsetValue consider returning Binding.DoNothing for the case where the radio button IsChecked value becomes false. The former indicates a problem (and might show the user a red rectangle or similar validation indicators) while the latter just indicates that nothing should be done, which is what is wanted in that case.

http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback.aspx http://msdn.microsoft.com/en-us/library/system.windows.data.binding.donothing.aspx

anon