开发者

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

I have a group of buttons that should act like toggle butto开发者_StackOverflow中文版ns, 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?


This is easiest way in my opinion.

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

Enjoy! -- Pricksaw


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.


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


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


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


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


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


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.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜