在不使用转换器的情况下将单选按钮绑定到其枚举值

时间:2013-03-12 14:05:42

标签: c# wpf mvvm radio-button

我在列表视图中有一个单选按钮组。此列表视图的行(其中包含单选按钮grp)是一个可观察的集合。

我写的代码是这样的:

Xaml:

    <RadioButton Content="EnumValueName1"
             GroupName="RadButGrp1"
             IsChecked="{Binding propertyName,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=EnumValueName1}" >
 </RadioButton>
 <RadioButton Content="EnumValueName2" 
              GroupName="RadButGrp1"
              IsChecked="{Binding propertyName,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=EnumValueName2}">
 </RadioButton>
<RadioButton Content="EnumValueName3" 
              GroupName="RadButGrp1"
              IsChecked="{Binding propertyName,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=EnumValueName3}">
 </RadioButton>

我试图直接绑定到我的数据结构中名为propertyName的数据字段,该数据结构定义了包含这些值的表。我的ViewModel类中没有此视图用于此视图。我这样做是为了避免跟踪我目前正在填充的集合的索引。 (或者我想想!)

转换器:

 public class EnumBooleanConverter : IValueConverter
 {
    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 (value == null || 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 || value.Equals(false))
            return DependencyProperty.UnsetValue;

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

问题是在Enum.Parse行的ConvertBack函数中,会发生以下Argument异常:

  
    

提供的类型必须是枚举。     参数名称:enumType

  

有没有办法将枚举类型返回到绑定?如何告诉单选按钮它代表哪个枚举值?如何编写一个函数,为绑定返回相应的枚举值?

希望你们能提供帮助。提前谢谢!

3 个答案:

答案 0 :(得分:0)

试试这个,这是我EnumToBoolConverter的版本:

public class EnumToBoolConverter : BaseConverterMarkupExtension<object, bool>
{
    public override bool Convert(object value, Type targetType, object parameter)
    {
        if (value == null)
            return false;

        return value.Equals(Enum.Parse(value.GetType(), (string)parameter, true));
    }

    public override object ConvertBack(bool value, Type targetType, object parameter)
    {
        return value.Equals(false) ? DependencyProperty.UnsetValue : parameter;
    }
}

答案 1 :(得分:0)

好的,一旦我理解了这个概念,解决方案就相对简单了。我做了以下部分解决了我的问题。

 <RadioButton Content="EnumValueName1" 
              GroupName="RadBtnGrp1"
              IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ParentControl}},
                                  Path=DataContext.propName,
                                  Mode=TwoWay,
                                  Converter={StaticResource EnumToBoolConverter},ConverterParameter=EnumValueName1}">

 </RadioButton>

我的ConvertBack函数中的targetType现在是正确的枚举类型。希望这有帮助!

现在我必须弄清楚如何使radiobuttons在listview的多行中保留选择。目前,他们在第一行中的选择取消选择其余行中的相同组。

感谢您的帮助。如果有人能指出我解决新问题的解决方案真的很棒!

答案 2 :(得分:0)

建议您动态创建单选按钮,ListBox可以帮助我们做到这一点,而无需使用转换器。此方法的优点如下: 如果某天您的枚举类更改,则无需更新GUI(XAML文件)。

此方法的步骤如下:
创建一个ListBox并将该listbox的ItemsSource设置为枚举,并将ListBox的SelectedItem绑定到selected属性。 然后将为每个ListBoxItem创建单选按钮。

  • 第1步:重新定义您的枚举。
public enum EnumValueNames
{ 
   EnumValueName1, 
   EnumValueName2, 
   EnumValueName3
}

然后将以下属性添加到您的DataContext(或MVVM的ViewModel)中,该属性记录了选中的选中项。

public EnumValueNames SelectedEnumValueName { get; set; }
  • 第2步:将枚举添加到Window,UserControl或Grid等的静态资源中。
    <Window.Resources>
        <ObjectDataProvider MethodName="GetValues"
                            ObjectType="{x:Type system:Enum}"
                            x:Key="EnumValueNames">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:EnumValueNames" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
  • 第3步:使用列表框和Control Template作为单选按钮填充其中的每个项目
    <ListBox ItemsSource="{Binding Source={StaticResource EnumValueNames}}" SelectedItem="{Binding SelectedEnumValueName, Mode=TwoWay}" >
        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <RadioButton
                                Content="{TemplateBinding ContentPresenter.Content}"
                                IsChecked="{Binding Path=IsSelected,
                                RelativeSource={RelativeSource TemplatedParent},
                                Mode=TwoWay}" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
    </ListBox>

参考: https://www.codeproject.com/Articles/130137/Binding-TextBlock-ListBox-RadioButtons-to-Enums