在 WPF 中。如何像 iPhone 一样通过鼠标拖动滚动 ScrollViewer 中的对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20680162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
in WPF. How to scroll Objects in ScrollViewer by mouse-dragging, like as iPhone?
提问by user110777
it's done well to scroll by mouse-wheel or scrollbar seed-dragging. but scrolling by mouse-dragging contents on scroll view is not done. How can i implement this action?
通过鼠标滚轮或滚动条种子拖动滚动效果很好。但是在滚动视图上通过鼠标拖动内容滚动没有完成。我该如何实施此操作?
<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>
回答by user110777
I found a way of resolving this. It's following...
我找到了解决这个问题的方法。它在跟...
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);
}
thanks!
谢谢!
回答by TheBigSot
I did this class to scroll while keeping the scrollviewer buttons. From the code from user110777, but this works with vertical instead of horizontally, and works well with the viewer (Since I'm now only capturing the content). Plus I'm using MouseLeftButtonDown instead of the preview in order to allow the user to click things like the combobox without causing a drag. (If you want label or Textblock to drag set their IsHitTestVisible=false)
我做了这个类来滚动,同时保持滚动查看器按钮。来自 user110777 的代码,但这适用于垂直而不是水平,并且适用于查看器(因为我现在只捕获内容)。另外,我使用 MouseLeftButtonDown 而不是预览,以允许用户单击组合框之类的内容而不会引起拖动。(如果你想要标签或文本块拖动设置它们的 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();
}
}
回答by John Laszlo
This is how I did it, XAML:
我就是这样做的,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#:
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;
}
}
where Point oldMousePosition;is a member of the window.
Point oldMousePosition;窗口的成员在哪里。
回答by MadMaxIV
UWP variation:
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);
}
}
I know that question was for WPF, but this was best result I found searching for UWP solution.
我知道这个问题是针对 WPF 的,但这是我在搜索 UWP 解决方案时发现的最佳结果。
回答by naseer mohammad
You can do this in C# WPFlike this.
note that there are two type of Point classes.From them you should use System.Windows.Pointto get this work.These are mouse related events for your ScrollViewer.The code below will scroll your object to both horizontal and vertical inside the ScrollViewer.
您可以像这样在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);
}
回答by Rajeev Ranjan
use this
用这个
for horizontal scrolling
用于水平滚动
private void ScrollViewer_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ScrollViewer scv = (ScrollViewer)sender;
scv.ScrollToHorizontalOffset(scv.HorizontalOffset - e.Delta);
e.Handled = true;
}
回答by PhuocLuong
My experience: follow user110777Changed below code
我的经验:按照user110777更改以下代码
private void scrollViewer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
scrollMousePoint = e.GetPosition(scrollViewer);
hOff = scrollViewer.HorizontalOffset;
scrollViewer.CaptureMouse();
}

