如何在不设置IsEnabled的情况下防止ToggleButton被切换

时间:2010-03-30 21:25:59

标签: wpf togglebutton

我有一个ToggleButtons列表,在ListBox中使用类似于this answer的ItemTemplate,使用Listbox的MultiSelect模式。但是我需要确保始终选择至少一个项目。

我可以从ListBox中获取正确的行为,只需在ListBox.SelectionChanged事件中将一个项目添加回ListBox的SelectedItems集合中,但我的ToggleButton仍然会移出其切换状态,所以我想我需要先在处理。

我想在没有在最后一个按钮上设置IsEnabled =“False”的情况下这样做,因为我更喜欢使用Enabled视觉样式,而不必重做我的按钮模板。有什么想法吗?

5 个答案:

答案 0 :(得分:32)

您可以通过不调用基本实现来覆盖OnToggle方法以防止切换状态:

public class LockableToggleButton : ToggleButton
{
    protected override void OnToggle()
    {
        if (!LockToggle)
        {
            base.OnToggle();
        }
    }

    public bool LockToggle
    {
        get { return (bool)GetValue(LockToggleProperty); }
        set { SetValue(LockToggleProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LockToggle.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LockToggleProperty =
        DependencyProperty.Register("LockToggle", typeof(bool), typeof(LockableToggleButton), new UIPropertyMetadata(false));
}

答案 1 :(得分:3)

您是否尝试过使用RadioButtons?如果不选择另一个,通常无法取消选择。它的样式也可以看起来像ToggleButton:

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

或者,如果您已经拥有Style,请将其设为BasedOn="{x:Type ToggleButton}"。请注意,Visual Studio编辑器在第一种情况下显示错误,但它编译并正常工作。

答案 2 :(得分:1)

这是hackey,但如果您不想要自定义代码,则可以始终使用属性“IsHitTestVisible”,当您不希望它们取消选中时,只需将IsHitTestVisible设置为false即可。但是,他们可以使用空格键切换到控件并进行切换。

答案 3 :(得分:1)

托马斯的回答很好,但你甚至不需要额外的依赖属性。如果您的类继承自ToggleButton,那么您的按钮将正确更新,因此您可以覆盖OnToggle方法,并更改ViewModel上的IsChecked绑定属性。

的Xaml:

<myControls:OneWayFromSourceToTargetToggle x:Name="MyCustomToggleButton"
                                           Command="{Binding Path=ToggleDoStuffCommand}"
                                           CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}"
                                           IsChecked="{Binding Path=ToggleIsCheckedConditionVar, 
                                                               Mode=OneWay}"
                                           />

添加了ToggleButton类:

public class OneWayFromSourceToTargetToggle : ToggleButton
{
   /// <summary>
   /// Overrides the OnToggle method, so it does not set the IsChecked Property automatically
   /// </summary>
   protected override void OnToggle()
   {
      // do nothing
   }
}

然后在ViewModel中将bool ToggleIsCheckedCondition设置为true或false。这是一个很好的方法,因为你遵循良好的MVVM实践。

视图模型:

public bool ToggleIsCheckedCondition
{
   get { return _toggleIsCheckedCondition; }
   set
   {
      if (_toggleIsCheckedCondition != value)
      {
         _toggleIsCheckedCondition = value;
         NotifyPropertyChanged("ToggleIsCheckedCondition");
      }
   }
}

public ICommand ToggleDoStuffCommand
{
    get {
         return _toggleDoStuffCommand ?? 
               (_toggleDoStuffCommand = new RelayCommand(ExecuteToggleDoStuffCommand));
        }
}

private void ExecuteToggleDoStuffCommand(object param)
{
   var btn = param as ToggleButton;
   if (btn?.IsChecked == null)
   {
      return;
   }
   // has not been updated yet at this point
   ToggleIsCheckedCondition = btn.IsChecked == false;

   // do stuff

   }
}

答案 4 :(得分:0)

在@Joachim-Mairböck的出色答案中添加了一些内容,以防您需要以编程方式执行相同操作:

new RadioButton {
    ...
    GroupName = "myButtonGroup"
    Style = Application.Current.TryFindResource(typeof(ToggleButton)) as Style
    ...
}