WPF создает список элементов управления, которые можно прокручивать с помощью мыши, но при этом оставаться функциональными - PullRequest
4 голосов
/ 11 марта 2010

У меня есть список элементов управления, которые я отображаю через WrapPanel, и он расположен горизонтально.

Я реализовал технику прокрутки «Нажми и перетаскивай», чтобы пользователь прокручивал мышью, щелкая и перетаскивая.

Вот так:

<Canvas x:Name="ParentCanvas" PreviewMouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove">
  <WrapPanel>
    <WrapPanel.RenderTransform>
      <TranslateTransform />
    </WrapPanel.RenderTransform> 

    <!-- controls are all in here ... -->
  </WrapPanel>
</Canvas>

Тогда в коде позади:

    private Point _mousePosition;
    private Point _lastMousePosition;

    private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        _lastMousePosition = e.GetPosition(ParentCanvas);
        e.Handled = true;
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        _mousePosition = e.GetPosition(ParentCanvas);
        var delta = _mousePosition - _lastMousePosition;

        if(e.LeftButton == MouseButtonState.Pressed && delta.X != 0)
        {
            var transform = ((TranslateTransform)_wrapPanel.RenderTransform).Clone();
            transform.X += delta.X;
            _wrapPanel.RenderTransform = transform;
            _lastMousePosition = _mousePosition;
        }
    }

Это все отлично работает

Но я хочу сделать так, чтобы, когда пользователь щелкает мышью для перетаскивания, элементы внутри WrapPanel не отвечали (т.е. пользователь только просматривал), но когда пользователь нажимает (как в полный щелчок), а затем они отвечают на щелчок.

Точно так же, как работает iphone, когда вы нажимаете и перетаскиваете приложение, оно не открывается, а прокручивает экран, но когда вы нажимаете на приложение, оно запускается ...

Надеюсь, это имеет смысл.

Cheers, Mark

Ответы [ 2 ]

3 голосов
/ 11 марта 2010

Полагаю, вам нужно поймать мышь. Проблема в том, что вы будете бороться с элементами управления (такими как Button), которые также будут пытаться захватить мышь.

В вашем событии MouseDown (вероятно, на самом деле PreviewMouseDown) вы можете использовать e.MouseDevice.Capture (_wrapPanel, CaptureMode.Element). Это должно направлять весь ввод мыши в _wrapPanel, а не любые элементы поддерева.

В вашем событии MouseUp вам нужно освободить перехват, вызвав e.Mousedevice.Capture (null). Если прокрутки не было, вы захотите отправить «щелчок» элементу управления, который обычно получил бы щелчок, в котором я не совсем уверен. Возможно, вы можете использовать классы Automation Peer для этого?

Хитрость заключается в том, что некоторые элементы управления не будут работать должным образом, если вы удерживаете от них события мыши. Для примера рассмотрим слайдер. Как этот слайдер можно будет использовать внутри панели, которая работает следующим образом?

0 голосов
/ 11 марта 2010

Другое, и, на мой взгляд, лучшее решение:

  1. Добавьте обработчик PreviewMouseDown, в котором вы установили Handled = true, и запишите параметры, включая позицию, и установите флаг MaybeClick (если не установлен ваш флаг "рекурсия") и установите таймер.

  2. Добавить обработчик MouseMove, который очищает флаг «MaybeClick», если мышь перемещается на расстояние больше эпсилона от позиции, записанной для PreviewMouseDown.

  3. Добавить обработчик PreviewMouseUp, который проверяет флаг «MaybeClick» - если true, он устанавливает флаг «рекурсия», делает InputManager.ProcessInput, чтобы повторно поднять исходный PreviewMouseDown, а затем очищает флаг "рекурсия".

  4. В таймере сделайте то же самое, что и для PreviewMouseUp, чтобы щелчок задерживался только на мгновение.

Чистым эффектом является задержка события PreviewMouseDown до тех пор, пока у вас не будет времени проверить, двигалась ли мышь или нет.

Некоторые замечания об этом решении:

  • Установка Handled=true на PreviewMouseDownEvent также останавливает MouseDownEvent.
  • Рекурсивный вызов игнорируется в обработчике PreviewMouseDown, так как установлен флаг рекурсии
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...