ispiro
ispiro

Reputation: 27713

Allow vertical scrolling of outer ScrollViewer inside inner horizontal-scrolling ScrollViewer

When you have a ScrollViewer within a ScrollViewer, scrolling with the scroll wheel is limited to the inner one. That makes sense when they have the same "orientation". But when the outer allows only vertical scrolling, and the inner allows only horizontal scrolling, I'd expect scrolling with the mouse wheel inside the inner one to scroll vertically in the outer ScrollViewer. It doesn't. Is there a way to get it to do this?

In the following code, try using the scroll wheel while inside the red letter area:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
    <StackPanel>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>
        <TextBlock>aaaaaaaaaaaaaaaaaa</TextBlock>

        <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
            <StackPanel >
                <TextBlock Foreground="Red">aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc dddddddddddddddddddddd eeeeeeeeeeeeeeeeeeeee fffffffffffffffff ggggggggggggggggggggggg</TextBlock>
                <TextBlock Foreground="Red">aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc dddddddddddddddddddddd eeeeeeeeeeeeeeeeeeeee fffffffffffffffff ggggggggggggggggggggggg</TextBlock>
                <TextBlock Foreground="Red">aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc dddddddddddddddddddddd eeeeeeeeeeeeeeeeeeeee fffffffffffffffff ggggggggggggggggggggggg</TextBlock>
                <TextBlock Foreground="Red">aaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc dddddddddddddddddddddd eeeeeeeeeeeeeeeeeeeee fffffffffffffffff ggggggggggggggggggggggg</TextBlock>
            </StackPanel>
        </ScrollViewer>
    </StackPanel>
</ScrollViewer>

Upvotes: 0

Views: 806

Answers (1)

Mash
Mash

Reputation: 1536

If you are ok with using code-behind, you can create an event handler for the PreviewMouseWheel event of the "child" ScollViewer, and within the event handler, you can pass the MouseWheelEventArgs information to the "parent" ScrollViewer to raise its own MouseWheel event.

First, there will be a couple of minor changes to the XAML:

Give the "parent" ScrollViewer a name so it can be referenced from code-behind:

<ScrollViewer x:Name="parentScrollViewer"
              VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Disabled">

Create an event handler for the PreviewMouseWheel event of the "child" ScrollViewer:

<ScrollViewer VerticalScrollBarVisibility="Disabled"
              HorizontalScrollBarVisibility="Auto" 
              PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">

Finally, implement the code in the event handler to raise the "parent" MouseWheel event:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    var mouseWheelEventArgs = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
    mouseWheelEventArgs.RoutedEvent = ScrollViewer.MouseWheelEvent;
    mouseWheelEventArgs.Source = sender;
    this.parentScrollViewer.RaiseEvent(mouseWheelEventArgs);
}

Upvotes: 1

Related Questions