如何让一组切换按钮像WPF中的单选按钮一样?

时间:2010-03-02 11:08:31

标签: wpf

我有一组按钮,它们应该像切换按钮一样,但也可以作为单选按钮,在当前时间只能选择/按下一个按钮。它还需要具有不选择/按下任何按钮的状态。

行为有点像Photoshop工具栏,可随时选择零个或一个工具!

知道如何在WPF中实现这一点吗?

11 个答案:

答案 0 :(得分:279)

在我看来,这是最简单的方式。

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

享受! - Pricksaw

答案 1 :(得分:38)

最简单的方法是将ListBox设置为将ToggleButtons用于其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>

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

答案 2 :(得分:28)

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

它适合我,享受!

答案 3 :(得分:5)

你总是可以在Click of the ToggleButton上使用泛型事件,它在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 :(得分:4)

你可以在其中放置带有radiobuttons的网格,并为raduiobuttons创建类似模板的按钮。而不仅仅是programmaticaly删除检查你是否不想切换按钮

答案 5 :(得分:3)

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

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

然后针对IsChecked属性编写代码以模仿radiobutton效果

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

答案 6 :(得分:3)

嘿,我实际上已经为此开发了一个解决方案。您可以覆盖单选按钮的控件模板,然后按下向下按钮。我在开源库中有一个实现的解决方案:

http://code.google.com/p/phoenix-control-library/

您可以获得开箱即用的工作解决方案或查看那里的源代码。

享受。

答案 7 :(得分:0)

我为RibbonToggleButtons做了这个,但是对于常规的ToggleButtons也许是这样。

我使用EnumToBooleanConverter从这里How to bind RadioButtons to an enum?将每个按钮的IsChecked绑定到“mode”枚举值(使用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; 
            }
        }
    }

答案 8 :(得分:0)

帮助像Julian和我这样的人(两分钟前......)。您可以从RadioButton这样派生出来。

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

然后,您可以像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>

此方法一次只允许一个ToggleButtonChecked,并且还允许取消检查。

答案 9 :(得分: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}}">

答案 10 :(得分:0)

一个简单的实现可能是您在代码中维护一个标志,例如:

ToggleButton _CurrentlyCheckedButton;

然后为所有上下文 ToggleButtons 分配一个 Checked 事件处理程序:

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

   _CurrentlyCheckedButton = (sender as ToggleButton);
}

还有一个 Unchecked 事件处理程序:

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

这样你就可以有你想要的“零或一”选择。