Событие манипуляции и режим панорамирования

Я разрабатываю WPF для сенсорного устройства. Я столкнулся со странной проблемой. Моя структура XAML

 <ScrollViewer>
     <StackPanel orientation="Horizontal">
         <!--  Control goes here -->
      </StackPanel>
  <ScrollViewer>

Теперь

  1. Чтобы включить прокрутку при касании, я должен установить для PannigMode значение HorizontalOnly.
  2. Чтобы получать события манипуляции, я должен установить для PannigMode значение None.

Проблема в том, что я должен иметь эти две функции одновременно.

Есть ли обходной путь, чтобы scrollviewer прокручивался при касании, а также срабатывало событие manipulationcompleted.

Пожалуйста помоги.


person Gulshan    schedule 19.02.2013    source источник
comment
Кто-нибудь, пожалуйста, ответьте.   -  person Gulshan    schedule 20.02.2013


Ответы (1)


Я была такая же проблема. У вас есть как минимум два варианта

  • использовать набор инструментов MS Surface
  • исправить ScrollViewer

Я выбрал второе. Просто создайте собственный элемент управления, наследуемый от ScrollViewer, в Generic.xaml вам нужно только поставить <ContentPresenter />, ничего больше. Настоящая работа заключается в коде позади, но это не так сложно. Мне нужно было проверить, коснулся ли пользователь кнопки или просто хотел прокрутить. Хитрость заключается в том, чтобы проверить, что находится на точках касания, и включить/выключить режим панорамирования.

А вот код:

namespace Demo.Controls
{
   public class ScrollViewerWithTouch : ScrollViewer
   {
    private PanningMode panningMode;


    private bool panningModeSet;

      static ScrollViewerWithTouch()
      {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollViewerWithTouch), new FrameworkPropertyMetadata(typeof(ScrollViewerWithTouch)));
      }

      protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)
      {
         base.OnManipulationCompleted(e);

         // set it back
         this.PanningMode = this.panningMode;
      }

      protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
      {
         // figure out what has the user touched
         var result = VisualTreeHelper.HitTest(this, e.ManipulationOrigin);
         if (result != null && result.VisualHit != null)
         {
            var hasButtonParent = this.HasButtonParent(result.VisualHit);

            // if user touched a button then turn off panning mode, let style bubble down, in other case let it scroll
            this.PanningMode = hasButtonParent ? PanningMode.None : this.panningMode;
         }
         base.OnManipulationStarted(e);
      }

      protected override void OnTouchDown(TouchEventArgs e)
      {
         // store panning mode or set it back to it's original state. OnManipulationCompleted does not do it every time, so we need to set it once more.
         if (this.panningModeSet == false)
         {
            this.panningMode = this.PanningMode;
            this.panningModeSet = true;
         }
         else
         {
            this.PanningMode = this.panningMode;
         }

         base.OnTouchDown(e);         
      }

      private bool HasButtonParent(DependencyObject obj)
      {
         var parent = VisualTreeHelper.GetParent(obj);

         if ((parent != null) && (parent is ButtonBase) == false)
         {
            return HasButtonParent(parent);
         }

         return parent != null;
      }
   }
}
person Andras Sebo    schedule 04.09.2013