C# wpf scrollviewer not working like windows store

2019-05-04 21:40发布

问题:

I'm currently working on an application using WPF. And I can't but help to notice the difference in ScrollViewer functionality compared to the Windows Store App variant.

When I'm at the edge of the screen and the edge of a ScrollViewer and I want to slide so that I'd move away from the edge. I see the windows desktop or menubar (when at the bottom of the screen). Is there a solution to prevent this scroll behaviour from happening? It is rather annoying (and ugly!) when your scrolling till the edge of the screen and then get bumped back and see a bit of the windows platform underneath. This behaviour is fixed in the Windows Store App ScrollViewer..

I tried overwriting the ScrollChanged and checking if f.e. horizontalOffset == 0 && horizontalChange < 0 and return if this is the case. But this check doesn't seem to work (since then it's probably already too late). And I can't seem to find the way Windows Store Apps have fixed this.

Perhaps you guys have an idea?


EDIT: Reproduction for WPF projects in .NET 4.5.1

This piece of XAML re-creates my problem in WPF. However in Windows Store App the problem doesn't seem to exist.

How can I prevent this behaviour when scrolling to and/or over the edges of my application?

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" ResizeMode="NoResize" WindowState="Maximized" WindowStyle="None">
    <Grid>
        <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" PanningMode="Both">
            <Rectangle Height="2500" Stroke="Black" Width="3500" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0,0.5">
                        <GradientStop Color="#FF00FF68" Offset="0"/>
                        <GradientStop Color="Red" Offset="1"/>
                        <GradientStop Color="#FF95FF00" Offset="0.506"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>
        </ScrollViewer>

    </Grid>
</Window>

回答1:

This is the default Windows 8 behavior related to scrolling. Your entire app will "bounce" when hitting the edge of a scroll-able view. This happens in every single cases and is part of the system animations. You can see it, for instance, in the Windows Explorer when in a long list of folders. This only happens when scrolling through touch and, if I remember correctly, on non full-screen applications. I do not currently have access to a Windows 8 machine to test this claim and there might very well be no way to disable this behavior.

The Modern environment is a completely separate application environment and does not handle touch gestures in the same way at all. This is why this behavior does not exists in a WinRT application.

EDIT : This effect is called the Manipulation Boundary Feedback. It triggers when a manipulation event goes beyond the limits of its container. You can disable it overriding the OnManipulationBoundaryFeedback(ManipulationBoundaryFeedbackEventArgs) method on the affected UIElement like so:

class NoTouchFeedbackWindow : Window
{
    protected override void OnManipulationBoundaryFeedback(ManipulationBoundaryFeedbackEventArgs e)
    {
        e.Handled = true;
    }
}

This could also be done directly on your ScrollViewer or any control up the chain.

You can find more information about this behavior on:

  • http://msdn.microsoft.com/en-us/library/dd988680(v=vs.110).aspx
  • http://msdn.microsoft.com/en-us/library/system.windows.uielement.onmanipulationboundaryfeedback(v=vs.110).aspx

Hopefully, this should solve your issue.