Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF scrolling parent container through child container

I'm having some issues trying to figure out how to scroll the content of a grid which is contained inside of a scroll viewer. When trying to scroll with the mouse wheel or pan (with a touch screen), the grid scrolls fine if the mouse/touch point is over an empty area, but if it is above certain controls (ex. a group box) it won't scroll. Is there some property I'm missing to allow the child panels to allow them to scroll their parent containers?

EDIT: I incorrectly stated my original layout. Here's a simplified version of my senario:

<Grid>
    <ScrollViewer Name="MainScrollViewer">
        <StackPanel>
            <ListBox />    <--Doesn't Scroll-->
            <Button />     <--Scrolls Fine-->
            <TextBlock />  <--Scrolls Fine-->
            <TextBox />    <--Scrolls Fine-->
            <DataGrid />   <--Doesn't Scroll-->
        </StackPanel>
    </ScrollViewer>
</Grid>

A coworker pointed out that my issue is due to the fact the controls such as a ListBoxes and DataGrids contain ScrollViewers themselves, this makes sense. His suggestion (which would work but we both agree seems more complex than it should be) is to catch and rethrow the the scroll event in the code behind (and likely have to deal with calculating the smount of offset to scroll) so that it can bubble up to "MainScrollViewer".

EDIT 2: It seems like the only way to achieve this is to use code behind to handle the PreviewMouseWheel event in the parent. That works, but how do I go about implementing the same thing for panning (scrolling by finger on a touch screen)?

like image 602
AXG1010 Avatar asked Dec 12 '22 03:12

AXG1010


1 Answers

Create a bubbling scrollbehavior for your scrollview:

using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;

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)
    {
        if (!e.Handled)
        {
            e.Handled = true;
            var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = UIElement.MouseWheelEvent };
            AssociatedObject.RaiseEvent(e2);
        }
    }
}

Add this behavior to your scrollviewer:

 <ScrollViewer x:Name="Scroller">
                    <i:Interaction.Behaviors>
                        <ViewAddons:BubbleScrollEvent />
                    </i:Interaction.Behaviors>
like image 110
Illedan Avatar answered Jan 18 '23 10:01

Illedan