惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
美团技术团队
博客园_首页
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CERT Recently Published Vulnerability Notes
Project Zero
Project Zero
有赞技术团队
有赞技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
博客园 - 聂微东
Forbes - Security
Forbes - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
T
Threatpost
月光博客
月光博客
人人都是产品经理
人人都是产品经理
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Security Archives - TechRepublic
Security Archives - TechRepublic
宝玉的分享
宝玉的分享
Know Your Adversary
Know Your Adversary
Spread Privacy
Spread Privacy
J
Java Code Geeks
Scott Helme
Scott Helme
S
SegmentFault 最新的问题
C
Cybersecurity and Infrastructure Security Agency CISA
H
Hacker News: Front Page
L
LINUX DO - 热门话题
Last Week in AI
Last Week in AI
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tor Project blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
量子位
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
博客园 - 叶小钗
C
Cisco Blogs
小众软件
小众软件
S
Securelist
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - Franky
V
Visual Studio Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
WordPress大学
WordPress大学
博客园 - 司徒正美

博客园 - Hey,Coder!

jaeger界面显示异常 .net opentelemetry collector jaeger c# opentelemetry 自定义export c# opentelemetry 自定义export c# 生成对象的初始化代码 Elasticsearch ILM 与 Data Stream 概念及实例说明文档 portainer httphelper封装 Ocelot + Consul + SignalR 粘性会话 正交软件架构 docker postgresql17 主从复制 rabbitmq总结与c#示例 docker rabbitmq quartz dashboard docker consul registrator 服务自动注册consul 微服务动态扩容 ubuntu24.04 安装docker RAG 检索增强生成 软考 - 架构设计师 知识点总结 c# MailKit3.4.3 发送邮件、附件 nginx 反向代理postgresql c# 信号量 elsa 3.5 中间件记录最后执行的节点数据 xp密钥 c# System.Text.Json 反序列化Dictionary<string,object>时未转换基础类型的处理方法 docker配置代理 openclaw 接入 LMStudio的模型服务 wpf canvas 移动 缩放 windows平台openclaw搭建 c# 动态切换sqlsugar连接字符串 c# Elastic.Clients.Elasticsearch 动态查询 c# es 封装Elastic.Clients.Elasticsearch c# scrollerview滚动到指定元素位置 WPF 重写Expander 基于elsa工作流封装一套变量、组件的体系 常用活动重写 DynamicExpresso 轻量级动态表达式库 c# elsa 3.5.2 程序化工作流常用功能及自定义中间件 leaflet docker 连接老版本的sqlserver ssl错误 c# quartz 动态创建任务 控制任务运行和停止 依赖注入 cefsharp 模拟点击 批量重置数据库的数据 docker 复制远程镜像本地并创建容器 c# newtonsoft dynamic
wpf scrollerview触摸滚动
Hey,Coder! · 2026-03-10 · via 博客园 - Hey,Coder!

RollAttachHelper

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;


    /// <summary>
    /// ScrollViewer触摸滚动
    /// 使用用例:
    /// 1、xmlns添加引用
    /// 2、ScrollViewer添加附加属性设置RollAttachHelper.IsEnabled="True" 
    /// </summary>
    public class RollAttachHelper : 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(RollAttachHelper), 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;
                target.ManipulationBoundaryFeedback += target_ManipulationBoundaryFeedback;
            }
            else
            {
                target_Unloaded(target, new RoutedEventArgs());
            }
        }

        static void target_Unloaded(object sender, RoutedEventArgs e)
        {
            //popup内部不需要移除
            return;
            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;
            target.ManipulationBoundaryFeedback -= target_ManipulationBoundaryFeedback;
        }
        /// <summary>
        /// 触摸屏滚动实现,禁止窗口弹跳
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void target_ManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
        {
            e.Handled = true;
        }

        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;
            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; }
        }
    }

使用

localHelper:RollAttachHelper.IsEnabled="True"