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?
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)
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();
}
}
You can do this in C# WPF like this.
note that there are two type of Point classes.From them you should use System.Windows.Point
to 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.
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);
}
This is how I did it, 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;
}
}
where Point oldMousePosition;
is a member of the window.
My experience: follow user110777 Changed below code
private void scrollViewer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
scrollMousePoint = e.GetPosition(scrollViewer);
hOff = scrollViewer.HorizontalOffset;
scrollViewer.CaptureMouse();
}
UWP variation:
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.
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;
}