【问题标题】:How can I prevent a ToggleButton from being Toggled without setting IsEnabled如何在不设置 IsEnabled 的情况下防止 ToggleButton 被切换
【发布时间】:2011-02-02 16:20:09
【问题描述】:

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

我可以通过在 ListBox.SelectionChanged 事件上将一个项目重新添加到 ListBox 的 SelectedItems 集合中来从 ListBox 中获得正确的行为,但是我的 ToggleButton 仍然移出其切换状态,所以我认为我需要在过程。

我不想在最后一个按钮 Selected 上设置 IsEnabled="False",因为我更喜欢保持 Enabled 视觉样式,而不必重做我的按钮模板。有什么想法吗?

【问题讨论】:

    标签: wpf togglebutton


    【解决方案1】:

    您可以通过不调用基本实现来覆盖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));
    }
    

    【讨论】:

    • 正常工作:-)
    【解决方案2】:

    您是否尝试过使用 RadioButtons 代替?如果不选择另一个,通常无法取消选择它。它也可以被设计成一个 ToggleButton:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 此外,当用户在锁定时尝试切换它时,可能需要发出可听见的 ding 声音。使用 IsHitTestVisible 无法实现这一目标。
      • 您也可以使用IsTabStop="False" 来阻止用户点击按钮。我更喜欢这个解决方案而不是接受的答案,因为它可以在 XAML 中完成,对 MVVM 友好,并且不需要任何自定义代码。如果您需要在多个地方应用一个样式,可以使用它。
      【解决方案4】:

      Thomas 的回答很好用,但您甚至不需要额外的依赖属性。如果您有从 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}"
                                                 />
      

      添加了切换按钮类:

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

      【讨论】:

        【解决方案5】:

        为@Joachim-Mairböck 的出色答案添加一点内容,以防您想以编程方式执行相同操作:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多