2

私はこのWPFの世界にちょっと慣れていません。そして、スクロールビューがタッチイベントを消費している理由についてちょっと混乱しています。

私の現在の状況は次のとおりです。

この ScrollViewer には ItemsControl があります。この ItemsControl では、Wrappanel を使用して多数の Rectangle を表示しています。私の ScrollViewer は、垂直方向にスクロールして、下にラップされた Rectangles を表示できるようにする必要があります。これらの各 Rectangles で、あらゆる種類のハンドラーを使用して CustomBehaviour を作成しました。これらのハンドラーの 1 つは、LongPressGestures を処理するために「創造的に」作られた方法です。

問題は次のとおりです。長押しが動作によって検出される前に、ScrollViewer が PreviewTouchMove ハンドラーで TouchDevice をキャプチャしています。

ScrollViewer が TouchDevice を早期にキャプチャしないようにするにはどうすればよいですか? ScrollViewer をスクロールして、LongPress、DoubleClick (これは引き続き機能します)、SingleClick (これも同様に機能します)、およびこのカスタム動作に追加する可能性のあるその他のジェスチャを実行できるようにするにはどうすればよいですか?

stackoverflow と google で同様の質問を見つけましたが、特定のケースではわかりません。

CustomThumb を使用したもの<-- このリンクは、CustomThumb を作成することで問題を解決します。これをどうにかして自分の行動に再利用できますか?動作ハンドラの早い段階で TouchDevice をキャプチャすることによって?

すべてが失敗した場合。この ScrollViewer と CustomBehaviour の組み合わせに代わるものはありますか?


編集:

その間。CustomThumb メソッドを再試行しました。UIElements (その動作を伴う) が ScrollViewer に配置されている間に、CustomBehaviour から長押しが機能するようになりました。ただし、ScrollViewer のスクロール機能はまだ機能しません。私が追加した報奨金は、それを再び適切に機能させるのを手伝ってくれた人にも授与されます (答えはこの CustomThumb ソリューションと同じ方向にあるはずなので)。

4

1 に答える 1

4

以前にも同様の問題がありました。スクロール、タッチ、スタイルを同時に使用できませんでした。最後に、カスタム ScrollViewer を開発しました。いくつかの基本的なメソッドを監視/変更するだけでよいので、思ったより簡単です。

あなたの場合、ユーザーが空の表面またはリスト項目を押したかどうかを確認できます。リストアイテムの場合は、短押し(タッチダウン後にタッチアップも発生)か長押しかを確認する必要があります。

スクロールは、PanningMode で構成できます。ユーザーコントロール全体を指でスクロールできます。

これが私のバージョンのスクロールビューアです。ユーザーがボタンを押してからオンにすると、スクロールモードがオフになります。

public class ScrollViewerWithTouch : ScrollViewer   
{
      /// <summary>
      /// Original panning mode.
      /// </summary>
      private PanningMode panningMode;

  /// <summary>
  /// Set panning mode only once.
  /// </summary>
  private bool panningModeSet;

  /// <summary>
  /// Initializes static members of the <see cref="ScrollViewerWithTouch"/> class.
  /// </summary>
  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-11-11T15:12:38.687 に答える