WPF touch Scroll -触摸滚动

借鉴地址: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");
        }
    }
}

  

原文地址:https://www.cnblogs.com/wgscd/p/10558132.html