简体   繁体   中英

How do I prevent DataGrid RowDetails from stoping scrolling?

I have a simple DataGrid with RowDetails. The RowDetails contain another DataGrid. When the RowDetails are collapsed scrolling works normally as you would expect it. But when the RowDetails are visible the scrolling stops as soon as the RowDetails get scrolled below the cursor. I guess what's happening is that it is trying to scroll the DataGrid in the details but it doesn't even have a scrollbar. The only way to scroll is to move the cursor away from the RowDetails. But in a DataGrid with multiple RowDetails all having a DataGrid with the width of the parent DataGrid this is really annoying.

Also it seems like a simple thing to fix but I can't find anything about this. So how do I prevent the RowDetails from messing up my scrolling?

I found a solution to this. The problem is the DateGrid not the RowDetails, so this also applies to all DataGrids in ScrollViewers.

First way of doing this would be setting IsHitTestVisible to false . Then the DataGrid will be ignored by the cursor and won't block the scrolling. The downside to this is that it will be completely ignored by the cursor so you can't even click on things in the DataGrid anymore. Since this is usually necessary and also is for my case this is not a great solution.

So the second and better way is to catch the scrolling event on the inner DataGrid and pass it on to the outer DataGrid or whatever is supposed to scroll. We can do this with the PreviewMouseWheel Event of the DataGrid. Then we can scroll the outer ScrollViewer like this:

ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ContentVerticalOffset - e.Delta);

Found here: DataGrids over ScrollViewer prevent it to scroll

If the outer Control is a DataGrid we first have to get its ScrollViewer like this:

private static ScrollViewer GetScrollbar(DependencyObject dep)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dep); i++)
    {
        var child = VisualTreeHelper.GetChild(dep, i);
        if (child != null && child is ScrollViewer)
            return child as ScrollViewer;
        else
        {
            ScrollViewer sub = GetScrollbar(child);
            if (sub != null)
                return sub;
        }
    }
    return null;
}

ScrollViewer scrollView = GetScrollbar(myDataGrid);

Code from: http://blog.kervinramen.com/2010/10/wpf-datagrid-controlling-scrollbar.html

If the inner DataGrid has a content that can scroll we need to add a condition to passing on the scrolling, like this:

if (e.Delta > 0 && sv.VerticalOffset == 0 || e.Delta < 0 && 
    ScrollViewer.VerticalOffset == ScrollViewer.ScrollableHeight)

After this the DataGrid will behave like a TextBox would. If the cursor gets above it it will scroll itself until it hits the bottom. Then it will pass the scrolling to the outer control and let it scroll. Same for scrolling up.

Also e.Delta will always be 120 or -120. Test how this applies to your application. I had to divide it by 2.5 to get the same scrolling as the outer DataGrid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM