Ползунок не перетаскивает в сочетании с поведением IsMoveToPointEnabled

У меня есть IsMoveToPointEnabled на для моего Ползунка, поэтому когда я нажимаю где угодно на компонент, селектор перемещается в мою мышь. Проблема состоит в том, если я имею эту опцию на и нажимаю и удерживаю мышь для перетаскивания селектора, селектор не перемещается. Кто-либо знает, как зафиксировать это?

12
задан Tim Pohlmann 14 September 2015 в 14:47
поделиться

1 ответ

Самый простой способ - создать подкласс Slider:

public class CustomSlider : Slider
{
  public override void OnPreviewMouseMove(MouseEventArgs e)
  {
    if(e.LeftButton == MouseButtonState.Pressed)
      OnPreviewMouseLeftButtonDown(e);
  }
}

В этом случае ваш XAML будет выглядеть следующим образом:

<my:CustomSlider IsMoveToPointEnabled="True" />

Для более универсального решения, которое не подклассирует Slider, вы можете сделать это с прикрепленным property:

public class SliderTools : DependencyObject
{
  public static bool GetMoveToPointOnDrag(DependencyObject obj) { return (bool)obj.GetValue(MoveToPointOnDragProperty); }
  public static void SetMoveToPointOnDrag(DependencyObject obj, bool value) { obj.SetValue(MoveToPointOnDragProperty, value); }
  public static readonly DependencyProperty MoveToPointOnDragProperty = DependencyProperty.RegisterAttached("MoveToPointOnDrag", typeof(bool), typeof(SliderTools), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, changeEvent) =>
    {
      var slider = (Slider)obj;
      if((bool)changeEvent.NewValue)
        slider.MouseMove += (obj2, mouseEvent) =>
        {
          if(mouseEvent.LeftButton == MouseButtonState.Pressed)
            slider.RaiseEvent(new MouseButtonEventArgs(mouseEvent.MouseDevice, mouseEvent.Timestamp, MouseButton.Left)
            {
              RoutedEvent = UIElement.PreviewMouseLeftButtonDownEvent,
              Source = mouseEvent.Source,
            });
        };
    }
  });
}

Вы можете использовать это присоединенное свойство в Slider вместе со свойством IsMoveToPointEnabled:

<Slider IsMoveToPointEnabled="True" my:SliderTools.MoveToPointOnDrag="True" ... />

Оба этих решения работают путем преобразования событий PreviewMouseMove в эквивалентные события PreviewMouseLeftButtonDown всякий раз, когда левая кнопка нажата.

Обратите внимание, что присоединенное свойство не удаляет обработчик событий, если для свойства установлено значение false. Я написал это для простоты, так как вам почти никогда не придется удалять такой обработчик. Я рекомендую вам придерживаться этого простого решения, но если вы хотите, вы можете изменить PropertyChangedCallback, чтобы удалить обработчик, когда NewValue имеет значение false.

18
ответ дан 2 December 2019 в 05:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: