12

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

我可以通过在 ListBox.SelectionChanged 事件上将一个项目重新添加到 ListBox 的 SelectedItems 集合中来从 ListBox 中获得正确的行为,但我的 ToggleButton 仍会脱离其切换状态,因此我认为我需要在此过程的早期停止它。

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

4

5 回答 5

34

您可以通过不调用基本实现来覆盖该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));
}
于 2010-03-30T21:33:16.567 回答
7

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

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

或者,如果你已经有了Style它,那就做吧BasedOn="{x:Type ToggleButton}"。请注意,Visual Studio 编辑器在第一种情况下显示错误,但它可以编译并正常工作。

于 2016-02-03T15:27:14.603 回答
2

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

于 2010-06-15T19:15:35.220 回答
2

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

xml:

<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

   }
}
于 2017-02-10T18:43:26.483 回答
0

如果您想以编程方式执行相同操作,请在@Joachim-Mairböck 的出色答案中添加一点:

new RadioButton {
    ...
    GroupName = "myButtonGroup"
    Style = Application.Current.TryFindResource(typeof(ToggleButton)) as Style
    ...
} 
于 2020-06-18T11:14:55.447 回答