LoginSignup
7
6

More than 5 years have passed since last update.

[WPF]ScrollViewerが入れ子のときマウススクロールが効かない問題への対処法

Last updated at Posted at 2016-03-12

問題

ScrollViewerの中にScrollViewer(またはScrollViewerを内包するListViewやDataGrid)があるとき、マウススクロールが意図した通りに行われません。

原因

入れ子になったScrollViewerの下位ScrollViewerにMouseWheelEventが常にHandleされているため、上位ScrollViewerにスクロールイベントが到達しないことが原因です。

対処法

その1:TemplateからScrollViewerを除外する

下位にあるScrollViewerを使った要素からScrollViewerを取り除くことで対処する方法です。

xaml
<ListView>
    <ListView.Template>
        <ControlTemplate>
            <ItemsPresenter/>
        </ControlTemplate>
    </ListView.Template>
    ...
</ListView>

その2:MouseWheelEventを強制的に発生させる

上位ScrollViewer(またはMouseWheelEventを扱う要素)がMouseWheelEventを捕捉できるように下位のScrollViewerより先にMouseWheelEventを捕捉し、改めてイベントを送出します。

Behavior

public sealed class BubbleScrollEvent : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
        base.OnDetaching();
    }

    void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;
        var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        e2.RoutedEvent = UIElement.MouseWheelEvent;
        AssociatedObject.RaiseEvent(e2);
    }
}
xaml
<SomePanel>
            <i:Interaction.Behaviors>
                <viewsCommon:BubbleScrollEvent />
            </i:Interaction.Behaviors>
</SomePanel>

注意点

DataGridの場合はTemplateを書き換えるとRowHeaderがなくなってしまい表示が崩れます。
これは対処法その2を使うことで回避可能です。

参考

ここに掲載したコードは下記リンクのページから引用しています。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6