在WPF中。如何通过鼠标拖动滚动ScrollViewer中的对象,就像iPhone一样?

时间:2013-12-19 11:10:48

标签: c# wpf xaml

通过鼠标滚轮或滚动条种子拖动滚动效果很好。 但滚动视图上的鼠标拖动内容滚动没有完成。 我该如何实施这一行动?

        <ScrollViewer x:Name="scrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
            <Grid x:Name="galleryGrid" ShowGridLines="True">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="500"></ColumnDefinition>
                    <ColumnDefinition Width="500"></ColumnDefinition>
                    <ColumnDefinition Width="500"></ColumnDefinition>
                    <ColumnDefinition Width="500"></ColumnDefinition>
                    <ColumnDefinition Width="500"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Button Grid.Column="0" Magin="10,10,10,10">Test</Button>
                <Button Grid.Column="1" Magin="10,10,10,10">Test</Button>
                <Button Grid.Column="2" Magin="10,10,10,10">Test</Button>
                <Button Grid.Column="3" Magin="10,10,10,10">Test</Button>
                <Button Grid.Column="4" Magin="10,10,10,10">Test</Button>
            </Grid>
        </ScrollViewer>

7 个答案:

答案 0 :(得分:15)

我找到了解决这个问题的方法。 它跟随......

    Point scrollMousePoint = new Point();
    double hOff = 1;
    private void scrollViewer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        scrollMousePoint = e.GetPosition(scrollViewer);
        hOff = scrollViewer.HorizontalOffset;
        scrollViewer.CaptureMouse();
    }

    private void scrollViewer_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if(scrollViewer.IsMouseCaptured)
        {
            scrollViewer.ScrollToHorizontalOffset(hOff + (scrollMousePoint.X - e.GetPosition(scrollViewer).X));
        }
    }

    private void scrollViewer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        scrollViewer.ReleaseMouseCapture();
    }

    private void scrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + e.Delta);
    }

谢谢!

答案 1 :(得分:3)

我在保持滚动查看器按钮的同时滚动了这个类。来自user110777的代码,但这适用于垂直而不是水平,并且与查看器配合得很好(因为我现在只捕获内容)。另外我使用MouseLeftButtonDown而不是预览,以允许用户点击组合框之类的东西而不会造成阻力。 (如果您希望标签或Textblock拖动设置其IsHitTestVisible = false)

public class ScrollDragger
{
    private readonly ScrollViewer _scrollViewer;
    private readonly UIElement _content;
    private Point _scrollMousePoint;
    private double _hOff = 1;

    public ScrollDragger(UIElement content, ScrollViewer scrollViewer)
    {
        _scrollViewer = scrollViewer;
        _content = content;
        content.MouseLeftButtonDown += scrollViewer_MouseLeftButtonDown;
        content.PreviewMouseMove += scrollViewer_PreviewMouseMove;
        content.PreviewMouseLeftButtonUp += scrollViewer_PreviewMouseLeftButtonUp;
    }

    private void scrollViewer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _content.CaptureMouse();
        _scrollMousePoint = e.GetPosition(_scrollViewer);
        _hOff = _scrollViewer.VerticalOffset;
    }

    private void scrollViewer_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (_content.IsMouseCaptured)
        {
            var newOffset = _hOff + (_scrollMousePoint.Y - e.GetPosition(_scrollViewer).Y);
            _scrollViewer.ScrollToVerticalOffset(newOffset);
        }
    }

    private void scrollViewer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _content.ReleaseMouseCapture();
    } 
}

答案 2 :(得分:1)

我就是这样做的,XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="20px"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Text="this is not in the scrollviewer" Name="tb"/>
    <ScrollViewer Name="sv" 
                  HorizontalScrollBarVisibility="Auto" 
                  Grid.Row="1">
        <StackPanel Name="sp" Width="500" Height="500"
                    MouseMove="sp_MouseMove" 
                    Background="Transparent">
            <Ellipse Height="50" Width="50" Fill="Green"/>
        </StackPanel>

    </ScrollViewer>
</Grid>

C#:

private void sp_MouseMove(object sender, MouseEventArgs e)
    {
        Point newMousePosition = Mouse.GetPosition((StackPanel)sender);
        tb.Text = newMousePosition.X + " | " + newMousePosition.Y;

        if (Mouse.LeftButton == MouseButtonState.Pressed)
        {
            if (newMousePosition.Y < oldMousePosition.Y)
                sv.ScrollToVerticalOffset(sv.VerticalOffset + 1);
            if (newMousePosition.Y > oldMousePosition.Y)
                sv.ScrollToVerticalOffset(sv.VerticalOffset - 1);

            if (newMousePosition.X < oldMousePosition.X)
                sv.ScrollToHorizontalOffset(sv.HorizontalOffset + 1);
            if (newMousePosition.X > oldMousePosition.X)
                sv.ScrollToHorizontalOffset(sv.HorizontalOffset - 1);
        }
        else
        {
            oldMousePosition = newMousePosition;
        }
    }

其中Point oldMousePosition;是窗口的成员。

答案 3 :(得分:0)

我的经验:关注user110777 更改了以下代码

private void scrollViewer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
       scrollMousePoint = e.GetPosition(scrollViewer);
        hOff = scrollViewer.HorizontalOffset;
        scrollViewer.CaptureMouse();
    }

答案 4 :(得分:0)

UWP版本:

    Pointer pointer;
    PointerPoint scrollMousePoint ;
    double hOff = 1;

    private void MainScrollviewer_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        pointer = e.Pointer;
        scrollMousePoint = e.GetCurrentPoint(scrollviewer);
        hOff = scrollviewer.HorizontalOffset;
        scrollviewer.CapturePointer(pointer);
    }

    private void MainScrollviewer_PointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        scrollviewer.ReleasePointerCaptures();
    }

    private void MainScrollviewer_PointerMoved(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        if (scrollviewer.PointerCaptures!= null&& scrollviewer.PointerCaptures.Count>0)
        {
          scrollviewer.ChangeView(hOff + (scrollMousePoint.Position.X - e.GetCurrentPoint(scrollviewer).Position.X),null,null);
        }
    }

我知道这个问题是关于WPF的,但这是我寻找UWP解决方案的最好结果。

答案 5 :(得分:0)

您可以像这样在 C#WPF 中执行此操作。 请注意,有两种类型的Point类。您应该使用System.Windows.Point来完成这项工作。这些是ScrollViewer的鼠标相关事件。下面的代码将在ScrollViewer中将对象滚动到水平和垂直方向。

   System.Windows.Point ScrollMousePoint1 = new System.Windows.Point();
   double HorizontalOff1 = 1; double VerticalOff1 = 1;
   private void ScrollViewer1_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ScrollMousePoint1 = e.GetPosition(ScrollViewer1);
            HorizontalOff1 = ScrollViewer1.HorizontalOffset;
            VerticalOff1 = ScrollViewer1.VerticalOffset;
            ScrollViewer1.CaptureMouse();
        }

        private void ScrollViewer1_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (ScrollViewer1.IsMouseCaptured)
            {
                ScrollViewer1.ScrollToHorizontalOffset(HorizontalOff1 + (ScrollMousePoint1.X - e.GetPosition(ScrollViewer1).X));
                ScrollViewer1.ScrollToVerticalOffset(VerticalOff1 + (ScrollMousePoint1.Y - e.GetPosition(ScrollViewer1).Y));
            }
        }

        private void ScrollViewer1_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ScrollViewer1.ReleaseMouseCapture();
        }

        private void ScrollViewer1_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
        {
            ScrollViewer1.ScrollToHorizontalOffset(ScrollViewer1.HorizontalOffset + e.Delta);
            ScrollViewer1.ScrollToVerticalOffset(ScrollViewer1.VerticalOffset + e.Delta);
        }

答案 6 :(得分:-1)

使用此

用于水平滚动

private void ScrollViewer_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)     
{             
    ScrollViewer scv = (ScrollViewer)sender;               
    scv.ScrollToHorizontalOffset(scv.HorizontalOffset - e.Delta);
    e.Handled = true;    
}