Here's a little 5-minute glob of code I hacked together to handle dragging ScrollViewer content around with the mouse (or your finger).
It can also reverse the axes for "natural scrolling." There is also a Tolerance setting that is supposed to prevent it from scrolling if you only drag it a little bit. I did this because my crappy touchscreen driver has a lot of jitter.
I claim no responsibility if it explodes or otherwise has undesired effects. :)
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
namespace MouseExtensions
{
public class MouseDragBehavior
{
public static readonly DependencyProperty ToleranceProperty = DependencyProperty.RegisterAttached("Tolerance", typeof(double), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((double)10));
public static double GetTolerance(DependencyObject d)
{
return (double)d.GetValue(ToleranceProperty);
}
public static void SetTolerance(DependencyObject d, double value)
{
d.SetValue(ToleranceProperty, value);
}
public static readonly DependencyProperty ReverseAxisProperty = DependencyProperty.RegisterAttached("ReverseAxis", typeof(bool), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((bool)false));
public static bool GetReverseAxis(DependencyObject d)
{
return (bool)d.GetValue(ReverseAxisProperty);
}
public static void SetReverseAxis(DependencyObject d, bool value)
{
d.SetValue(ReverseAxisProperty, value);
}
private static readonly DependencyProperty DragStartPointProperty = DependencyProperty.RegisterAttached("DragStartPoint", typeof(Point), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((Point)new Point()));
private static Point GetDragStartPoint(DependencyObject d)
{
return (Point)d.GetValue(DragStartPointProperty);
}
private static void SetDragStartPoint(DependencyObject d, Point value)
{
d.SetValue(DragStartPointProperty, value);
}
private static readonly DependencyProperty DragLastPointProperty = DependencyProperty.RegisterAttached("DragLastPoint", typeof(Point), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((Point)new Point()));
private static Point GetDragLastPoint(DependencyObject d)
{
return (Point)d.GetValue(DragLastPointProperty);
}
private static void SetDragLastPoint(DependencyObject d, Point value)
{
d.SetValue(DragLastPointProperty, value);
}
public static readonly DependencyProperty HandleDragProperty = DependencyProperty.RegisterAttached("HandleDrag", typeof(bool), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((bool)false, new PropertyChangedCallback(OnHandleDragChanged)));
public static bool GetHandleDrag(DependencyObject d)
{
return (bool)d.GetValue(HandleDragProperty);
}
public static void SetHandleDrag(DependencyObject d, bool value)
{
d.SetValue(HandleDragProperty, value);
}
private static void OnHandleDragChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scrollViewer = d as ScrollViewer;
if ((bool)e.NewValue)
{
scrollViewer.PreviewMouseDown += new MouseButtonEventHandler(target_PreviewMouseDown);
scrollViewer.PreviewMouseMove += new MouseEventHandler(target_PreviewMouseMove);
scrollViewer.PreviewMouseUp += new MouseButtonEventHandler(target_PreviewMouseUp);
scrollViewer.MouseLeave += new MouseEventHandler(target_MouseLeave);
}
else
{
scrollViewer.PreviewMouseDown -= new MouseButtonEventHandler(target_PreviewMouseDown);
scrollViewer.PreviewMouseMove -= new MouseEventHandler(target_PreviewMouseMove);
scrollViewer.PreviewMouseUp -= new MouseButtonEventHandler(target_PreviewMouseUp);
scrollViewer.MouseLeave -= new MouseEventHandler(target_MouseLeave);
}
}
private static bool IsDragging(ScrollViewer scrollViewer)
{
Point posNow = Mouse.GetPosition(scrollViewer);
return ((Math.Abs(GetDragStartPoint(scrollViewer).X - posNow.X) > GetTolerance(scrollViewer)) || (Math.Abs(GetDragStartPoint(scrollViewer).Y - posNow.Y) > GetTolerance(scrollViewer)));
}
private static void target_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
var mousePos = e.GetPosition(scrollViewer);
scrollViewer.CaptureMouse();
if (GetDragLastPoint(scrollViewer) == new Point())
{
SetDragStartPoint(scrollViewer, mousePos);
SetDragLastPoint(scrollViewer, mousePos);
}
if (IsDragging(scrollViewer))
{
e.Handled = true;
return;
}
else
scrollViewer.ReleaseMouseCapture();
}
private static void target_PreviewMouseMove(object sender, MouseEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
if (GetDragLastPoint(scrollViewer) != new Point())
{
Point posNow = e.GetPosition(scrollViewer);
double dX = posNow.X - GetDragLastPoint(scrollViewer).X;
double dY = posNow.Y - GetDragLastPoint(scrollViewer).Y;
SetDragLastPoint(scrollViewer, posNow);
if (!IsDragging(scrollViewer))
return;
if (GetReverseAxis(scrollViewer))
{
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + dX);
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + dY);
}
else
{
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - dX);
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - dY);
}
}
e.Handled = true;
}
private static void target_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
if (GetDragLastPoint(scrollViewer) != new Point() && IsDragging(scrollViewer))
{
e.Handled = true;
scrollViewer.ReleaseMouseCapture();
}
Reset(scrollViewer);
}
private static void target_MouseLeave(object sender, MouseEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
Reset(scrollViewer);
}
private static void Reset(ScrollViewer scrollViewer)
{
SetDragLastPoint(scrollViewer, new Point());
SetDragStartPoint(scrollViewer, new Point());
}
}
}
To use it simply reference the namespace and set MouseDragBehavior.HandleDrag to true in your
A study by physicist Henry Tye of Cornell University suggests that the universe may not expand forever. Instead, it could eventually stop expanding, begin contracting and end in a "Big Crunch" roughly 20 billion years from now.
Maybe not as we now know that time can flow backwards.
It is clear from this aricle that "Time Is On My Side" no matter which direction it is flowing.,
https://noai.duckduckgo.com/?i...m%2Fwatch%3Fv%3DsEj8lUx0gwY
Matt Dinniman
I’m happy to announce that our friends at Peacock have officially greenlit the Dungeon Crawler Carl television series! Me, Chris Yost and Seth MacFarlane and his team at Fuzzy Door are all really excited to get to work. In the coming weeks I'll have more details, and if you're going to SDCC be sure to catch me and Chris on our DCC panel, but in the meantime I wanted to thank you, the fans, for helping make this happen.
— with Peacock TV and Seth MacFarlane.
Question
Eric Veteran
Here's a little 5-minute glob of code I hacked together to handle dragging ScrollViewer content around with the mouse (or your finger).
It can also reverse the axes for "natural scrolling." There is also a Tolerance setting that is supposed to prevent it from scrolling if you only drag it a little bit. I did this because my crappy touchscreen driver has a lot of jitter.
I claim no responsibility if it explodes or otherwise has undesired effects. :)
using System; using System.Windows; using System.Windows.Input; using System.Windows.Controls; namespace MouseExtensions { public class MouseDragBehavior { public static readonly DependencyProperty ToleranceProperty = DependencyProperty.RegisterAttached("Tolerance", typeof(double), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((double)10)); public static double GetTolerance(DependencyObject d) { return (double)d.GetValue(ToleranceProperty); } public static void SetTolerance(DependencyObject d, double value) { d.SetValue(ToleranceProperty, value); } public static readonly DependencyProperty ReverseAxisProperty = DependencyProperty.RegisterAttached("ReverseAxis", typeof(bool), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((bool)false)); public static bool GetReverseAxis(DependencyObject d) { return (bool)d.GetValue(ReverseAxisProperty); } public static void SetReverseAxis(DependencyObject d, bool value) { d.SetValue(ReverseAxisProperty, value); } private static readonly DependencyProperty DragStartPointProperty = DependencyProperty.RegisterAttached("DragStartPoint", typeof(Point), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((Point)new Point())); private static Point GetDragStartPoint(DependencyObject d) { return (Point)d.GetValue(DragStartPointProperty); } private static void SetDragStartPoint(DependencyObject d, Point value) { d.SetValue(DragStartPointProperty, value); } private static readonly DependencyProperty DragLastPointProperty = DependencyProperty.RegisterAttached("DragLastPoint", typeof(Point), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((Point)new Point())); private static Point GetDragLastPoint(DependencyObject d) { return (Point)d.GetValue(DragLastPointProperty); } private static void SetDragLastPoint(DependencyObject d, Point value) { d.SetValue(DragLastPointProperty, value); } public static readonly DependencyProperty HandleDragProperty = DependencyProperty.RegisterAttached("HandleDrag", typeof(bool), typeof(MouseDragBehavior), new FrameworkPropertyMetadata((bool)false, new PropertyChangedCallback(OnHandleDragChanged))); public static bool GetHandleDrag(DependencyObject d) { return (bool)d.GetValue(HandleDragProperty); } public static void SetHandleDrag(DependencyObject d, bool value) { d.SetValue(HandleDragProperty, value); } private static void OnHandleDragChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ScrollViewer scrollViewer = d as ScrollViewer; if ((bool)e.NewValue) { scrollViewer.PreviewMouseDown += new MouseButtonEventHandler(target_PreviewMouseDown); scrollViewer.PreviewMouseMove += new MouseEventHandler(target_PreviewMouseMove); scrollViewer.PreviewMouseUp += new MouseButtonEventHandler(target_PreviewMouseUp); scrollViewer.MouseLeave += new MouseEventHandler(target_MouseLeave); } else { scrollViewer.PreviewMouseDown -= new MouseButtonEventHandler(target_PreviewMouseDown); scrollViewer.PreviewMouseMove -= new MouseEventHandler(target_PreviewMouseMove); scrollViewer.PreviewMouseUp -= new MouseButtonEventHandler(target_PreviewMouseUp); scrollViewer.MouseLeave -= new MouseEventHandler(target_MouseLeave); } } private static bool IsDragging(ScrollViewer scrollViewer) { Point posNow = Mouse.GetPosition(scrollViewer); return ((Math.Abs(GetDragStartPoint(scrollViewer).X - posNow.X) > GetTolerance(scrollViewer)) || (Math.Abs(GetDragStartPoint(scrollViewer).Y - posNow.Y) > GetTolerance(scrollViewer))); } private static void target_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var scrollViewer = (ScrollViewer)sender; var mousePos = e.GetPosition(scrollViewer); scrollViewer.CaptureMouse(); if (GetDragLastPoint(scrollViewer) == new Point()) { SetDragStartPoint(scrollViewer, mousePos); SetDragLastPoint(scrollViewer, mousePos); } if (IsDragging(scrollViewer)) { e.Handled = true; return; } else scrollViewer.ReleaseMouseCapture(); } private static void target_PreviewMouseMove(object sender, MouseEventArgs e) { var scrollViewer = (ScrollViewer)sender; if (GetDragLastPoint(scrollViewer) != new Point()) { Point posNow = e.GetPosition(scrollViewer); double dX = posNow.X - GetDragLastPoint(scrollViewer).X; double dY = posNow.Y - GetDragLastPoint(scrollViewer).Y; SetDragLastPoint(scrollViewer, posNow); if (!IsDragging(scrollViewer)) return; if (GetReverseAxis(scrollViewer)) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + dX); scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + dY); } else { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - dX); scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - dY); } } e.Handled = true; } private static void target_PreviewMouseUp(object sender, MouseButtonEventArgs e) { var scrollViewer = (ScrollViewer)sender; if (GetDragLastPoint(scrollViewer) != new Point() && IsDragging(scrollViewer)) { e.Handled = true; scrollViewer.ReleaseMouseCapture(); } Reset(scrollViewer); } private static void target_MouseLeave(object sender, MouseEventArgs e) { var scrollViewer = (ScrollViewer)sender; Reset(scrollViewer); } private static void Reset(ScrollViewer scrollViewer) { SetDragLastPoint(scrollViewer, new Point()); SetDragStartPoint(scrollViewer, new Point()); } } }To use it simply reference the namespace and set MouseDragBehavior.HandleDrag to true in your
ScrollViewer declaration:
<ScrollViewer xmlns:my="clr-namespace:MouseExtensions" my:MouseDragBehavior.HandleDrag="True" my:MouseDragBehavior.ReverseAxis="True" />Link to comment
https://www.neowin.net/forum/topic/1022710-cwpf-mouse-drag-behavior/Share on other sites
3 answers to this question
Recommended Posts