将单选按钮绑定到单个属性?

8
  • I'm having few RadioButtons and I don't want to bind "IsChecked" property of each one of them to unique property in the code.
  • I want to have a single property like "CurrentSelected" and according to that to set the "IsChecked".
  • In addition I don't want to use converters.
  • I tried to use the behavior "ChangePropertyAction" but it looks like it's working only in one way. here is my code:

    <RadioButton
        x:Name="UpRadioButton"
        Margin="5"
        Content="Up"
        >
        <i:Interaction.Triggers>
            <ei:DataTrigger Binding="{Binding IsChecked, ElementName=UpRadioButton}" Value="True">
                <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedDirection" Value="{x:Static Enums:DirectionEnum.Up}" />
            </ei:DataTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
    
    <RadioButton
        x:Name="DownRadioButton"
        Margin="5"
        Content="Down"
        >
        <i:Interaction.Triggers>
            <ei:DataTrigger Binding="{Binding IsChecked, ElementName=DownRadioButton}" Value="True">
                <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedDirection" Value="{x:Static Enums:DirectionEnum.Down}" />
            </ei:DataTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
    
    <RadioButton
        x:Name="LeftRadioButton"
        Margin="5"
        Content="Left"
        >
        <i:Interaction.Triggers>
            <ei:DataTrigger Binding="{Binding IsChecked, ElementName=LeftRadioButton}" Value="True">
                <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedDirection" Value="{x:Static Enums:DirectionEnum.Left}" />
            </ei:DataTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
    
    <RadioButton
        x:Name="RightRadioButton"
        Margin="5"
        Content="Right"
        >
        <i:Interaction.Triggers>
            <ei:DataTrigger Binding="{Binding IsChecked, ElementName=RightRadioButton}" Value="True">
                <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedDirection" Value="{x:Static Enums:DirectionEnum.Right}" />
            </ei:DataTrigger>
        </i:Interaction.Triggers>
    </RadioButton>               
    

我的视图模型非常简单:MainViewModel.cs
public class MainViewModel : ViewModelBase
{ 
    private DirectionEnum _selectedDirection;

    public DirectionEnum SelectedDirection
    {
        get { return _selectedDirection; }
        set
        {
            if (_selectedDirection != value)
            {
                _selectedDirection = value;
                RaisePropertyChanged();
            }
        }
    }
    public MainViewModel()
    {     
        SelectedDirection = DirectionEnum.Up;            
    }  
}

从代码中可以看出,“Up”单选按钮应该已经被选中了,那我错过了什么?


1
可能只有单向工作,因为您的绑定只是单向的...另外,转换器有什么问题吗?有一个非常适合这个问题的。 - BradleyDotNET
转换器需要维护... - kaycee
所以一般来说代码也是如此...这是你的选择,但是说你不喜欢转换器因为它们需要“维护”是一个相当糟糕的理由/借口。 - BradleyDotNET
Bradley,请参考Rachel建议的解决方案。你不觉得这比使用2路转换器更优雅吗? - kaycee
个人 认为这更加优雅吗?不是的。对于动态数据,我可以理解,但如果你从一开始就知道单选按钮的数据,那么 ValueEqualsConverter 就会变得非常优雅/简单。 - BradleyDotNET
1个回答

16

我通常使用一个ListBox,其中包含选择行为,然后覆盖模板以将项目绘制为RadioButton。

我的XAML模板通常看起来像这样:

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>

                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

样式应用方式如下:

<ListBox ItemsSource="{Binding Directions}"
         SelectedValue="{Binding SelectedDirection}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

相比在我的代码后台维护很多IsChecked属性或使用转换器,我发现这种方法更加清晰,用于管理分组的RadioButtons的选择行为。


1
Rachel,你的解决方案非常完美。谢谢。 - kaycee
1
在尝试了一段时间后,我终于找到了您的另一篇帖子,其中解释了为什么DisplayMemberPath不能正常工作-https://dev59.com/dms05IYBdhLWcg3wCNlG#7487670。非常高兴您也更新了那篇文章! - StayOnTarget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接