ScrollViewer - 可用鼠标拖动滚动的列表框
ScrollViewer添加附加属性:
using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace TouchScrollViewer { 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 System.Windows.DependencyProperty IsEnabledProperty = System.Windows.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_Unloaded; } } 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_Loaded(object sender, RoutedEventArgs e) { var target = sender as ScrollViewer; if (target == null) return; System.Diagnostics.Debug.WriteLine("Target Loaded"); 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_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 / 50); target.ScrollToHorizontalOffset(capture.HorticalOffset - dx); } internal class MouseCapture { public Double VerticalOffset { get; set; } public Double HorticalOffset { get; set; } public Point Point { get; set; } } } }
设置水平方向滚动条不显示:HorizontalScrollBarVisibility="Disabled"
设置垂直方向滚动条不显示:VerticalScrollBarVisibility="Disabled"
设置响应触摸操作的方式只有垂直有效:PanningMode="VerticalOnly"
UI界面:
<Window x:Class="TouchScrollViewer.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:local="clr-namespace:TouchScrollViewer" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="可触摸滚动的ScrollViewer" Width="800" Height="450" mc:Ignorable="d"> <Grid> <Grid.Resources> <Style TargetType="ItemsControl"> <Style.Setters> <Setter Property="Background" Value="Transparent" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="FontSize" Value="18" /> <Setter Property="FontFamily" Value="新宋体" /> <Setter Property="Stylus.IsFlicksEnabled" Value="False" /> <Setter Property="BorderThickness" Value="0,0,0,1" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ItemsControl"> <ScrollViewer local:TouchScrolling.IsEnabled="True" CanContentScroll="True" HorizontalScrollBarVisibility="Disabled" PanningMode="VerticalOnly" VerticalScrollBarVisibility="Disabled"> <ItemsPresenter /> </ScrollViewer> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Vertical" /> </ItemsPanelTemplate> </Setter.Value> </Setter> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate DataType="local:Data"> <RadioButton Width="1000" Height="50"> <RadioButton.Template> <ControlTemplate TargetType="RadioButton"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <TextBlock VerticalAlignment="Center" FontSize="30" Text="{Binding TestData}" /> </Grid> </Border> </ControlTemplate> </RadioButton.Template> </RadioButton> </DataTemplate> </Setter.Value> </Setter> </Style.Setters> </Style> </Grid.Resources> <ItemsControl x:Name="ItemsControl" /> </Grid> </Window>
using System.Collections.Generic; using System.Windows; namespace TouchScrollViewer { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); ShowList = new List<Data>(); for (int i = 0; i < 50; ++i) { ShowList.Add(new Data() {TestData = "测试文本" + i }); } ItemsControl.ItemsSource = ShowList; } public List<Data> ShowList { get; set; } } public class Data { public string TestData { get; set; } } }
效果展示:
文章参考:http://matthamilton.net/touchscrolling-for-scrollviewer
完整Demo下载地址:https://files.cnblogs.com/files/ly940120/TouchScrollViewerDemo.rar