0

このことを考慮:

<ScrollViewer>
  <!-- Several Controls /-->

  <MyControl MouseMove="myMouseMoveHandler" />

  <!-- Several Controls /-->
</ScrollViewer>

MyControl は、回転可能な円にカラー スペクトルを、三角形に選択した色相のニュアンスを示す HSV カラー選択コントロールです。それはすばらしく見えますが、残念ながらまだ写真を投稿できません (担当者)。表面上のすべての方向でマウスの動きを処理できる必要があります。

MyControl でマウスを動かすと (そして、動きを正しく処理します)、ScrollViewer はまだスクロールします!

これは、ScrollViewer 内の唯一のコントロールであり、コントロール内で動きが開始および終了する場合、および/または MouseLeftButtonDown / -Up イベントの両方で e.Handled = true を設定した場合でも発生します。..Down で CaptureMouse() を使用し、..Up で ReleaseMouseCapture() を使用しても役に立ちません。

ScrollViewer の実装を変更できない (または変更できる?) ことに同意するでしょう。また、コントロールが ScrollViewer 内でホストされていないことを保証することはできません (たとえば、公開したいため)。

ScrollViewer が MouseMove を取得できないようにすることが可能でなければなりません。証明: MyControl を、Height に収まるよりも多くのアイテムを含む ListBox に置き換えるだけで、ScrollViewer が反応せずに ListBox アイテムをスワイプできます。

しかし、どのように?それはListBox内のScrollViewerでもありますか?それがそこで機能する理由ですか?それとも私のコントロールでも実行できますか?

4

1 に答える 1

1

さて、私はうまく機能する解決策を見つけました。

私の考えは、e.Handled (MouseMove では使用できません)、IsHitTestVisible (タッチ イベントからもすべての子を非表示にします) などに固定されていたため、明らかなことはわかりませんでした。

誰かが同じ質問をした場合のコードは次のとおりです。

struct ScrollVisibilities
{
    public ScrollBarVisibility Horizontal;
    public ScrollBarVisibility Vertical;
}

Dictionary<ScrollViewer, ScrollVisibilities> scrollersStates = new Dictionary<ScrollViewer, ScrollVisibilities>();

bool scrollersDisabled;

void disableScrollViewers(bool disable)
{
    if (scrollersDisabled == disable)   // can't disable if disabled or enable if enabled
        return;
    scrollersDisabled = disable;

    if (disable)
    {
        DependencyObject dpo = Parent;
        while (dpo is FrameworkElement)
        {
            if (dpo is ScrollViewer)
            {
                ScrollViewer s = dpo as ScrollViewer;
                ScrollVisibilities v = new ScrollVisibilities()
                {
                    Horizontal = s.HorizontalScrollBarVisibility,
                    Vertical = s.VerticalScrollBarVisibility
                };
                scrollersStates.Add(s, v);
                s.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
                s.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
            }
            dpo = ((FrameworkElement)dpo).Parent;
        }
    }
    else // restore
    {
        foreach (ScrollViewer s in scrollersStates.Keys)
        {
            s.HorizontalScrollBarVisibility = scrollersStates[s].Horizontal;
            s.VerticalScrollBarVisibility = scrollersStates[s].Vertical;
        }
        scrollersStates.Clear();
    }
}

MouseLeftButtonDown で、ScrollViewers(true) を無効にし、Touch.FrameReported にフックします。Touch_FrameReported では、すべてのタッチ ポイントに Action == Up がある場合に、ScrollViewers(false) を無効にします。そうすれば、MyControl の外で発生した場合でも Up イベントを取得できます。

ScrollViewers を無効にすると、ScrollViewers (およびその子) がスクロールされていない状態にジャンプするため、このアプローチには制限があります。そこで、MyControl を一番上に置き、それに応じてすべての配置を設定しました。

于 2013-02-21T10:27:29.463 に答える