Bind RadioButtons to single property?
Asked Answered
C

1

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>               
    

my view model is very simple: 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;            
    }  
}

as you can see from the code, the "Up" RadioButton should be already checked... What am I missing ?

Cuspidor answered 17/2, 2015 at 21:18 Comment(5)
It might only be working one way since your bindings are only one way... Also, whats wrong with converters? There's one that is great for thisOch
converters require maintenance...Cuspidor
So does code in general... Its your choice, but saying that you don't like converters because they require "maintenance" is a pretty poor reason/excuse in my book.Och
Bradley, please refer in the solution Rachel advised.don't you think it's more elegant way then holding 2 way converter ?Cuspidor
Do I personally think that it's more elegant? No. For dynamic data, I could see it, but if you know your radio button's data from the start, a ValueEqualsConverter is extremely elegant/easy.Och
S
16

A common solution for me is to use a ListBox, which contains Selection behavior, and overwrite the Template to draw items as RadioButtons instead.

My XAML template usually looks something like this :

<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>

The style is applied like this:

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

I find this much cleaner for managing selection behavior of grouped RadioButtons than maintaining a lot of IsChecked properties in my code-behind, or using converters.

Schwarz answered 17/2, 2015 at 21:27 Comment(2)
Rachel, Your solution is more than perfect. ThanksCuspidor
After trying to make this work for a while I finally found your other post which explains why it doesn't work with DisplayMemberPath - https://mcmap.net/q/82227/-how-can-i-overwrite-my-listbox-39-s-itemtemplate-and-still-keep-the-displaymemberpath So glad you updated that one too!Laresa

© 2022 - 2024 — McMap. All rights reserved.