2010-03-02 141 views
100

我有一组按钮应该像切换按钮,但也可以作为单选按钮,当前只能选择/按下一个按钮。它还需要有一个状态,其中没有按钮被选中/按下。如何让一组切换按钮像WPF中的单选按钮一样工作?

该行为将有点像Photoshop工具栏,其中零或一个工具随时选择!

任何想法如何可以在WPF中实现?

回答

33

最简单的方法是设置一个ListBox来为其ItemTemplate使用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。

+0

感谢您分享!我想知道这是否是好的做法......但它似乎是好的.. – GorillaApe 2011-10-02 17:46:46

+1

@LouLouviere:你会不会详细说明为什么不呢?这不是如何使用项目模板的主要例子吗? – 2013-10-31 13:30:15

+2

这是一个不好的例子,因为你混淆了显示和行为。您可以通过datatemplate更改显示,但您仍然具有列表框的行为,而不是*一组收音机/切换按钮的行为。键盘互动很奇怪。一个更好的解决方案是带有RadioButtons的ItemsControl,它被称为ToggleButtons(请参阅其他最高票数的答案)。 – Zarat 2015-04-15 10:36:39

4

你可以把网格与单选按钮放在它里面,并为raduibuttons创建类似模板的按钮。不仅仅是programmaticaly删除检查,如果你不想按键进行切换

+0

但是,通过使用单选按钮是有办法取消选择所有按钮?一旦选定,我看不到一个简单的方法来取消选择它! – 2010-03-02 11:54:17

+0

RadioButton有一个IsChecked属性,当你需要时可以在代码中将它设置为false – 2010-03-02 12:10:34

+0

谢谢!将尝试出来 – 2010-03-02 12:22:16

3

您也可以尝试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; 
} 
+0

这不是非常通用和可重用的...例如,它在ListBoxItem中不可用。 – ANeves 2015-05-14 16:47:01

5

您可以随时在ClickButtonButton上使用一个通用事件,它可以在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; 
    } 
3

嘿,我实际上已经开发了一个解决方案。您可以覆盖单选按钮的控件模板并放置按下按钮。我有一个开源库,这里的实施的解决方案:

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

你可以得到外的箱子用工作溶液或看看源代码存在。

享受。

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

工作对我来说,享受!

+0

我知道这不是问题。但是,如果按钮的行为类似于必须始终选择按钮的单选按钮,该怎么办? – Karsten 2011-06-28 12:46:05

+0

回答我自己的问题:阅读Uday Kiran的答案:-) – Karsten 2011-06-28 12:49:44

+0

不错,这个行为与切换按钮相同。点击检查并点击相同的按钮取消选中。一旦我把所有的RadioButton放在同一个组中,它就像单选按钮一样。谢谢你RoKK! – mili 2014-05-29 11:21:09

248

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

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

享受! - Pricksaw

+27

这一个应该选择回答。 给你一个单选按钮的所有好处,没有绑定到某些控制器的缺点。我首先尝试绑定到单独的不可见的单选按钮集,但是这样做有不必要的开销,最后导致一个错误,其中点击的所有按钮看起来突出显示,但不一定检查。 – 2012-04-11 17:48:20

+15

或者,如果需要将此应用到所有单选按钮的元件内(例如一个'Grid'),使用'<形式的TargetType = “单选按钮” 支持算法FMP = “{StaticResource的{X:类型切换按钮}}” />'。 – 2012-12-06 18:53:47

+12

这种方法的一个缺点是你不能通过点击选中的按钮来取消单选按钮。 – Julien 2014-02-25 17:25:42

0

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

我结合的供器isChecked每个按钮使用EnumToBooleanConverter从这里How to bind RadioButtons to an enum?一个“模式”枚举值(指定用于使用所述ConverterParameter这个按钮的枚举值。你应该为每个按钮一个枚举值)

随后阻止取消选中这已经查了按钮,把这个在后面的代码为Click事件为每个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; 
      } 
     } 
    } 
0

为了帮助人们像朱利安和我(两分钟前...)。你可以像这样从RadioButton派生。

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

然后,您可以使用它像乌代·柯伦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的时间,而这也让取消选中。

相关问题