2

タッチ対応デバイス用の WPF を開発しています。私は奇妙な問題に直面しています。私のXAML構造は

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

  1. タッチでのスクロールを有効にするには、PannigModeHorizo ​​ntalOnly に設定する必要があります
  2. 操作イベントを受け取るには、PannigModeNoneに設定する必要があります

問題は、これら 2 つの機能を同時に持たなければならないことです。

スクロールビューアがタッチ時にスクロールされ、manipationcompletedイベントが発生するように回避策はありますか。

助けてください。

4

1 に答える 1

1

同じ問題がありました。少なくとも 2 つのオプションがあります

  • MS Surface ツールキットを使用する
  • ScrollViewerを修正

私は2番目のものを選びました。カスタム コントロールを作成し、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;
      }
   }
}
于 2013-09-04T09:20:57.407 に答える