如何在WPF中使一组切换按钮像单选按钮一样工作?


122

我有一组按钮应该像切换按钮一样工作,但也应作为单选按钮,在这些单选按钮中,当前只能选择/按下一个按钮。它还需要处于没有选择/按下任何按钮的状态。

行为类似于Photoshop工具栏,可随时选择零或其中一种工具!

知道如何在WPF中实现吗?

Answers:


38

最简单的方法是设置ListBox的样式,以便对其项目模板使用ToggleButtons

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

然后,您可以使用ListBox的SelectionMode属性来处理SingleSelect与MultiSelect。


感谢你的分享!我想知道这是否是个好习惯...但它似乎是确定..
GorillaApe

1
@LeeLouviere:您愿意详细说明为什么吗?这不是如何使用项目模板的主要示例吗?
或Mapper

4
这是一个不好的例子,因为您混淆了显示和行为。您可以通过datatemplate更改显示,但是仍然具有列表框的行为,而没有一组单选/切换按钮的行为。键盘交互很奇怪。更好的解决方案是带有RadioButtons的ItemsControl,其样式设置为ToggleButtons(请参阅投票率最高的另一个答案)。
Zarat 2015年

为什么要重新发明轮子?
摇晃

300

我认为这是最简单的方法。

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

请享用!-普里锯


29
到目前为止,应该选择这一答案。为您提供单选按钮的所有优点,而没有绑定到某些控制器的缺点。我首先尝试绑定到单独的不可见单选按钮集,但是这样做有不必要的开销,并最终导致一个错误,即所有单击的按钮看上去都是突出显示的,但不一定要选中。
Lee Louviere

16
或者,如果您需要将此元素应用于元素(例如Grid)中的所有RadioButton ,请使用<Grid.Resources> <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}" /> </Grid.Resources>
罗曼·斯塔科夫

16
此方法的一个缺点是您不能通过单击选中的按钮来取消选中单选按钮。
朱利安

2
可以以某种方式在此类切换按钮上使用自定义样式吗?
温德拉2014年

2
@wondra您只能将单个样式分配给FrameworkElement。但是,您可以改用romkyns解决方案并继承ToggleButton样式:<Style BasedOn="{StaticResource {x:Type ToggleButton}}" x:Key="Blubb" TargetType="RadioButton"><Setter Property="Background" Value="Yellow" /></Style>
Suigi 2015年

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

它对我有用,享受!


我知道这不是问题。但是,如果按钮的行为类似于必须始终选择一个的单选按钮,该怎么办?
卡斯滕

为了回答我自己的问题:请阅读Uday Kiran的回答:-)
Karsten

好的,这就像“切换”按钮一样。单击以选中,然后单击同一按钮以取消选中。当我将所有RadioButtons放在同一个组中时,它就像单选按钮一样。谢谢RoKK!
mili 2014年

2
这是一个很好的解决方案。但是,当我们有一个事件时。它会被调用两次。
Khiem-Kim Ho Xuan 2015年

如果添加的内容不是一个简单的字符串,我会得到一个“元素已经是另一个元素的孩子”的信息。错误。有没有办法解决这个问题?
Tobias Hoefer

5

您总是可以在ToggleButton的Click上使用一个通用事件,该事件在VisualTreeHelper的帮助下将groupcontrol(Grid,WrapPanel,...)中的所有ToggleButton.IsChecked设置为false;然后重新检查发件人。或类似的东西。

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

4

您可以在其中放置带有单选按钮的网格,并为raduiobuttons创建模板之类的按钮。而不是仅通过编程方式删除检查,如果您不想切换按钮


但是通过使用单选按钮可以取消选择所有按钮吗?一旦选择,我看不到取消选择的简单方法!
code-zoop

RadioButton具有IsChecked属性,您可以根据需要在代码中将其设置为false
Arsen Mkrtchyan 2010年

2

您也可以尝试 System.Windows.Controls.Primitives.ToggleButton

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

然后针对该IsChecked属性编写代码以模仿单选按钮效果

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

这不是很通用且可重用……例如,它在ListBoxItems中不可用。
2015年

0

我是针对RibbonToggleButtons这样做的,但对于常规的ToggleButtons来说可能是相同的。

我从这里使用EnumToBooleanConverter将每个按钮的IsChecked绑定到“模式”枚举值。如何将RadioButtons绑定到枚举?(使用ConverterParameter指定此按钮的枚举值。每个按钮应该有一个枚举值)

然后,为防止取消选中已选中的按钮,请将其放在代码中,以保留每个RibbonToggleButtons的Click事件:

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

0

帮助像朱利安和我这样的人(两分钟前...)。您可以从RadioButton这样得出。

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

然后,您可以像Uday Kiran 建议的那样使用它

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

这种方法只允许一个ToggleButtonChecked在一个时间,并且它也允许取消选中。


0

我采取了一些答案,并添加了一些额外的代码。现在,您可以拥有不同的切换按钮组,它们的作用类似于一个切换按钮:

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

还有不同的单选按钮组,它们看起来像切换按钮:

<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}}">
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.