WPF touch Scroll -触摸滚动

博客介绍了借鉴特定地址内容,对UI进行改造,使其支持上下和左右鼠标拖动滚动,还给出了转载来源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

借鉴地址: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

<think>好的,用户的问题是关于在WPF应用程序中,使用触摸滚动时希望整个页面滚动,而不仅仅是滚动条部分。我需要结合提供的引用资料来找到解决方案。 首先,根据引用[1],WPF触摸屏下默认有触底反馈导致抖动,这可能与滚动行为有关。引用[3]提到通过处理ManipulationBoundaryFeedback事件来阻止窗口移动。用户的问题可能涉及到如何扩展滚动的区域,而不仅仅是滚动条。 用户希望整个页面都能响应触摸滚动,而不是仅限于滚动条区域。通常,WPFScrollViewer的触摸滚动需要用户直接在滚动条上操作,但用户可能希望像触摸设备那样,任何区域的滑动都能触发滚动。 查看引用[3]中的解决方案,设置PanningMode为Both,这允许水平和垂直方向的平移滚动。这样用户在任何区域滑动都可以滚动内容,而不仅限于滚动条。同时,处理ManipulationBoundaryFeedback事件可以避免触底时的抖动问题。 另外,引用[2]提到触摸键盘的显示可能会干扰滚动,但这里的问题更关注滚动区域。引用[4]展示了使用WindowsFormsHost来处理滚动,但可能复杂,不如原生的ScrollViewer调整方便。 综合这些信息,解决方案应围绕ScrollViewer的PanningMode属性和事件处理。设置PanningMode="Both"启用整个区域的触摸滚动,并处理ManipulationBoundaryFeedback来防止抖动。这样用户在任何地方滑动都能滚动整个页面,而不只是操作滚动条。</think>### WPF触摸屏全页面滚动解决方案 在WPF中实现全页面触摸滚动(而不仅限于操作滚动条),可通过以下三种方案实现: **方案一:启用ScrollViewer平移模式** ```xml <ScrollViewer PanningMode="Both" VerticalScrollBarVisibility="Auto" ManipulationBoundaryFeedback="ScrollViewer_ManipulationBoundaryFeedback"> <!-- 页面内容 --> </ScrollViewer> ``` 通过设置: 1. `PanningMode="Both"` 允许水平和垂直方向的触摸平移[^3] 2. 事件处理防止触底抖动: ```csharp private void ScrollViewer_ManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e) { e.Handled = true; // 阻止默认触底反馈 } ``` **方案二:自定义触摸行为** ```xml <Grid TouchDown="Grid_TouchDown"> <ScrollViewer x:Name="mainScroller"> <!-- 页面内容 --> </ScrollViewer> </Grid> ``` 通过全局触摸事件处理: ```csharp private Point scrollStartPoint; private void Grid_TouchDown(object sender, TouchEventArgs e) { scrollStartPoint = e.GetTouchPoint(this).Position; e.Device.Capture((IInputElement)sender); } private void Grid_TouchMove(object sender, TouchEventArgs e) { var currentPoint = e.GetTouchPoint(this).Position; mainScroller.ScrollToVerticalOffset(mainScroller.VerticalOffset + (scrollStartPoint.Y - currentPoint.Y)); } ``` **方案三:Windows交互操作库** ```powershell Install-Package System.Windows.Interactivity ``` ```xml <ScrollViewer> <i:Interaction.Behaviors> <behaviors:ScrollViewerPanBehavior/> </i:Interaction.Behaviors> <!-- 页面内容 --> </ScrollViewer> ``` 该方案通过附加行为实现更精细的触摸控制,建议用于复杂交互场景[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值