对需要支持滚动触摸滚动的控件添加以下代码即可
local:TouchScrolling.IsEnabled="True"
后端代码
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; }
}
}
页面代码
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!--定义所以button样式-->
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Times New Roman"/>
<Setter Property="FontSize" Value="80"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="Red"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content" Value="111111111111111111111111111111111111111111111111111"></Setter>
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
</Style>
</Window.Resources>
<WrapPanel Loaded="WrapPanel_Loaded" Name="Panel1">
<ScrollViewer local:TouchScrolling.IsEnabled="True" HorizontalScrollBarVisibility="Auto">
<StackPanel>
<Button Name="Button1" Click="Button1_OnClick" Content="{Binding Path=Btn1}"/>
<Button Name="Button2" Click="Button1_OnClick"/>
<Button Name="Button3" Click="Button1_OnClick"/>
<Button Name="Button4" Click="Button1_OnClick"/>
<Button Name="Button5" Click="Button1_OnClick"/>
<Button Name="Button6" Click="Button1_OnClick"/>
<Button Name="Button7" Click="Button1_OnClick"/>
<Button Name="Button8" Click="Button1_OnClick"/>
<Button Name="Button9" Click="Button1_OnClick"/>
</StackPanel>
</ScrollViewer>
</WrapPanel>
</Window>