How to get a group of toggle buttons to act like radio buttons in WPF?

WpfXaml

Wpf Problem Overview


I have a group of buttons that should act like toggle buttons, but also as radio buttons where only one button can be selected / pressed down at a current time. It also need to have a state where none of the buttons are selected / pressed down.

The behavior will be kind of like Photoshop toolbar, where zero or one of the tools are selected at any time!

Any idea how this can be implemented in WPF?

Wpf Solutions


Solution 1 - Wpf

This is easiest way in my opinion.

<RadioButton Style="{StaticResource {x:Type ToggleButton}}" />

Enjoy! -- Pricksaw

Solution 2 - Wpf

The easiest way is to style a ListBox to use ToggleButtons for its ItemTemplate

<Style TargetType="{x:Type ListBox}">
    <Setter Property="ListBox.ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <ToggleButton Content="{Binding}" 
                              IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
				/>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Then you can use the SelectionMode property of the ListBox to handle SingleSelect vs MultiSelect.

Solution 3 - Wpf

Hey, here is my solution:

<RadioButton Content="Point" >
    <RadioButton.Template>
        <ControlTemplate>
            <ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                          Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
        </ControlTemplate>
    </RadioButton.Template>
</RadioButton>

it works for me, enjoy!

Solution 4 - Wpf

you could always use a generic event on the Click of the ToggleButton that sets all ToggleButton.IsChecked in a groupcontrol(Grid, WrapPanel, ...) to false with the help of the VisualTreeHelper; then re-check the sender. Or something in the likes of that.

private void ToggleButton_Click(object sender, RoutedEventArgs e)
    {
        int childAmount = VisualTreeHelper.GetChildrenCount((sender as ToggleButton).Parent);

        ToggleButton tb;
        for (int i = 0; i < childAmount; i++)
        {
            tb = null;
            tb = VisualTreeHelper.GetChild((sender as ToggleButton).Parent, i) as ToggleButton;

            if (tb != null)
                tb.IsChecked = false;
        }

        (sender as ToggleButton).IsChecked = true;
    }

Solution 5 - Wpf

you can put grid with radiobuttons in it, and create button like template for raduiobuttons. than just programmaticaly remove check if you don't want buttons to be toggled

Solution 6 - Wpf

You can also try System.Windows.Controls.Primitives.ToggleButton

 <ToggleButton Name="btnTest" VerticalAlignment="Top">Test</ToggleButton>

Then write code against the IsChecked property to mimick the radiobutton effect

 private void btnTest_Checked(object sender, RoutedEventArgs e)
 {
     btn2.IsChecked = false;
     btn3.IsChecked = false;
 }

Solution 7 - Wpf

I did this for RibbonToggleButtons, but maybe it's the same for regular ToggleButtons.

I bound the IsChecked for each button to a "mode" enum value using EnumToBooleanConverter from here https://stackoverflow.com/questions/397556/how-to-bind-radiobuttons-to-an-enum (Specify the enum value for this button using the ConverterParameter. You should have one enum value for each button)

Then to prevent unchecking a button that's already checked, put this in your code behind for the Click event for each of the RibbonToggleButtons:

    private void PreventUncheckRibbonToggleButtonOnClick ( object sender, RoutedEventArgs e ) {

        // Prevent unchecking a checked toggle button - so that one always remains checked
        // Cancel the click if you hit an already-checked button

        var button = (RibbonToggleButton)sender;
        if( button.IsChecked != null ) { // Not sure why checked can be null but that's fine, ignore it
            bool notChecked = ( ! (bool)button.IsChecked );
            if( notChecked ){ // I guess this means the click would uncheck it
                button.IsChecked = true; 
            }
        }
    }

Solution 8 - Wpf

To help people like Julian and me (two minutes ago...). You can derive from the RadioButton like this.

class RadioToggleButton : RadioButton
{
    protected override void OnToggle()
    {
        if (IsChecked == true) IsChecked = IsThreeState ? (bool?)null : (bool?)false;
        else IsChecked = IsChecked.HasValue;
    }
}

Then, you can use it like Uday Kiran suggested...

<Window x:Class="Sample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Sample"
    Title="MainWindow" Height="600" Width="600">
    <StackPanel>
        <local:RadioToggleButton Content="Button" Style="{StaticResource {x:Type ToggleButton}}" />
    </StackPanel>
</Window>

This method allows only one ToggleButton to be Checked at a time, and it also allows UnChecking.

Solution 9 - Wpf

I took a few piece of the answers and added some extra code. Now you can have different groups of toggle buttons which act like one toggle button:

<UserControl.Resources>
    <Style x:Key="GroupToggleStyle" TargetType="ToggleButton">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding GroupName, RelativeSource={RelativeSource Self}}" Value="Group1"/>
                    <Condition Binding="{Binding BooleanProperty}" Value="true"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter Property="IsChecked" Value="true"/>
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

And the different groups of radio buttons which look like toggle buttons:

<Radio Button GroupName="Group1" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group1" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group2" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group3" Style="{StaticResource {x:Type ToggleButton}}">

Solution 10 - Wpf

One simplistic implementation could be where you maintain a flag in your code behind such as:

ToggleButton _CurrentlyCheckedButton;

Then assign a single Checked event handler to all your context ToggleButtons:

private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
   if (_CurrentlyCheckedButton != null)
      _CurrentlyCheckedButton.IsChecked = false;

   _CurrentlyCheckedButton = (sender as ToggleButton);
}

And, a single Unchecked event handler:

private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
    if (_CurrentlyCheckedButton == (sender as ToggleButton))
       _CurrentlyCheckedButton = null;
}

This way you can have the 'zero or one' selection you desire.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncode-zoopView Question on Stackoverflow
Solution 1 - WpfUday Kiran ThummalapalliView Answer on Stackoverflow
Solution 2 - WpfBryan AndersonView Answer on Stackoverflow
Solution 3 - WpfRoKKView Answer on Stackoverflow
Solution 4 - WpfSamView Answer on Stackoverflow
Solution 5 - WpfArsen MkrtchyanView Answer on Stackoverflow
Solution 6 - WpfJojo SardezView Answer on Stackoverflow
Solution 7 - WpfSimon FView Answer on Stackoverflow
Solution 8 - WpfPrince OwenView Answer on Stackoverflow
Solution 9 - WpfStrawberryshrubView Answer on Stackoverflow
Solution 10 - WpfheapoverflowView Answer on Stackoverflow