借鉴地址:http://matthamilton.net/touchscrolling-for-scrollviewer
改造后支持上下和左右鼠标拖动滚动:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input; namespace TestTouchScroll
{
public class TouchScrolling : DependencyObject
{
public static bool GetIsEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsEnabledProperty);
} public static void SetIsEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsEnabledProperty, value);
} public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
} public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TouchScrolling), new UIPropertyMetadata(false, IsEnabledChanged)); static Dictionary<object, MouseCapture> _captures = new Dictionary<object, MouseCapture>(); static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as ScrollViewer;
if (target == null) return; if ((bool)e.NewValue)
{
target.Loaded += target_Loaded;
}
else
{
target_Unloaded(target, new RoutedEventArgs());
}
} static void target_Unloaded(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Target Unloaded"); var target = sender as ScrollViewer;
if (target == null) return; _captures.Remove(sender); target.Loaded -= target_Loaded;
target.Unloaded -= target_Unloaded;
target.PreviewMouseLeftButtonDown -= target_PreviewMouseLeftButtonDown;
target.PreviewMouseMove -= target_PreviewMouseMove; target.PreviewMouseLeftButtonUp -= target_PreviewMouseLeftButtonUp;
} static void target_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return; _captures[sender] = new MouseCapture
{
VerticalOffset = target.VerticalOffset,
HorticalOffset = target.HorizontalOffset,
Point = e.GetPosition(target),
};
} static void target_Loaded(object sender, RoutedEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return; System.Diagnostics.Debug.WriteLine("Target Loaded"); target.Unloaded += target_Unloaded;
target.PreviewMouseLeftButtonDown += target_PreviewMouseLeftButtonDown;
target.PreviewMouseMove += target_PreviewMouseMove; target.PreviewMouseLeftButtonUp += target_PreviewMouseLeftButtonUp;
} static void target_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var target = sender as ScrollViewer;
if (target == null) return; target.ReleaseMouseCapture();
} static void target_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!_captures.ContainsKey(sender)) return; if (e.LeftButton != MouseButtonState.Pressed)
{
_captures.Remove(sender);
return;
} var target = sender as ScrollViewer;
if (target == null) return; var capture = _captures[sender]; var point = e.GetPosition(target); var dy = point.Y - capture.Point.Y;
var dx = point.X - capture.Point.X; if (Math.Abs(dy) > 5)
{
target.CaptureMouse();
}
if (Math.Abs(dx) > 5)
{
target.CaptureMouse();
} target.ScrollToVerticalOffset(capture.VerticalOffset - dy);
target.ScrollToHorizontalOffset(capture.HorticalOffset - dx); } internal class MouseCapture
{
public Double VerticalOffset { get; set; }
public Double HorticalOffset { get; set; } public Point Point { get; set; }
}
}
}
UI:
<Window x:Class="TestTouchScroll.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:TestTouchScroll"
Title="MainWindow" Height="410" Width="888">
<Grid>
<ScrollViewer my:TouchScrolling.IsEnabled="True" HorizontalAlignment="Right" Width="351">
<StackPanel> <Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="120" Margin="12" Click="Button_Click">hello wgscd</Button>
</StackPanel> </ScrollViewer> <ScrollViewer my:TouchScrolling.IsEnabled="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Left" Width="458" Background="#FFEBEBEB">
<StackPanel Orientation="Horizontal" > <Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
<Button Height="328" Width="182" Margin="12" Click="Button_Click">hello wgscd</Button>
</StackPanel> </ScrollViewer> </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace TestTouchScroll
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("hello");
}
}
}