Как я могу предотвратить переключение ToggleButton без установки IsEnabled - PullRequest
9 голосов
/ 31 марта 2010

У меня есть список ToggleButtons, используемых в качестве ItemTemplate в ListBox, аналогично этому ответу с использованием режима MultiSelect в Listbox. Однако мне нужно убедиться, что хотя бы один элемент всегда выбран.

Я могу получить правильное поведение из ListBox, просто добавив элемент обратно в коллекцию SelectedItems ListBox в событии ListBox.SelectionChanged, но мой ToggleButton все еще выходит из переключенного состояния, поэтому я думаю, что мне нужно остановить его раньше в процесс.

Я хотел бы сделать это, не устанавливая IsEnabled = "False" на последней выбранной кнопке, потому что я предпочел бы использовать визуальный стиль Enabled без необходимости повторять шаблоны кнопок. Есть идеи?

Ответы [ 4 ]

32 голосов
/ 31 марта 2010

Вы можете переопределить метод 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));
}
3 голосов
/ 03 февраля 2016

Вы пробовали вместо этого использовать RadioButtons? Обычно он не может быть отменен без выбора другого. Он также может быть оформлен в виде кнопки ToggleButton:

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

Или, если у вас уже есть Style, просто сделайте его BasedOn="{x:Type ToggleButton}". Обратите внимание, что редактор Visual Studio показывает ошибку в первом случае, но он компилируется и работает нормально.

1 голос
/ 10 февраля 2017

Ответ Томаса работает нормально, но вам даже не нужно дополнительное свойство зависимости. Ваша кнопка будет обновляться правильно, если у вас есть класс, унаследованный от ToggleButton, поэтому вы можете переопределить метод OnToggle и изменить свойство привязки IsChecked в ViewModel.

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.

ViewModel:

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

   }
}
1 голос
/ 15 июня 2010

Это хаккей, но если вам не нужен пользовательский код, вы всегда можете использовать свойство "IsHitTestVisible", если вы не хотите, чтобы они снимали его, просто установите IsHitTestVisible равным false. Тем не менее, они могут быть в состоянии перейти к элементу управления и переключать его с помощью пробела.

...