WPF双滑块控件以及强制捕获鼠标事件焦点
效果
概述
最近有个小需求要用双滑块表示一个取值范围,于是就简单做了个用户控件,在此记录下.
使用矩形Rectangle表示范围,椭圆Ellipse表示滑块,使用Canvas控制滑块的左右移动.
椭圆的鼠标按下事件里强制获取鼠标事件焦点,避免移动过快或移出控件范围时,滑块就不跟着跑了.椭圆的鼠标抬起事件释放强制获取鼠标事件焦点
代码部分
需求比较简单,只定义了4个依赖属性,范围的最大值和最小值,取值的最大值和最小值.
接下来就是计算滑块和高亮矩形的位置,计算时注意减去椭圆Ellipse控件(圆)的半径,使圆心对准值,而不是左侧对准值.
鼠标移动的时候,计算当前位置对应的值,去改变依赖属性的值:
- 1 private void ell_MouseMove(object sender, MouseEventArgs e)
- 2 {
- 3 if (e.LeftButton == MouseButtonState.Pressed)
- 4 {
- 5 double percentage = e.GetPosition(rect).X / rect.ActualWidth;
- 6 double value = (Maximum - Minimum) * percentage + Minimum;
- 7 if (_ellFromPressed)
- 8 {
- 9 MinValue = (int)value;
- 10
- 11 }
- 12 if (_ellToPressed)
- 13 {
- 14 MaxValue = (int)value;
- 15 }
- 16 }
- 17 }
依赖属性的值变化,引起滑块的位置变化和高亮滑块宽度和位置的变化:
- 1 //最小值变化
- 2 private void MinValuePropertyChanged()
- 3 {
- 4 if (MinValue < Minimum)
- 5 {
- 6 MinValue = Minimum;
- 7 return;
- 8 }
- 9 if (MinValue > MaxValue)
- 10 {
- 11 MaxValue = MinValue;
- 12 }
- 13 //滑块位置变化
- 14 _offsetFrom = (MinValue - Minimum) * rect.ActualWidth / (Maximum - Minimum) - 8;
- 15 Canvas.SetLeft(ellFrom, _offsetFrom);
- 16 //高亮矩形长度和位置的变化
- 17 if (_offsetTo != -1)
- 18 {
- 19 double diff = _offsetTo - _offsetFrom;
- 20 if (diff >= 0)
- 21 {
- 22 rectHighLight.Width = diff;
- 23 Canvas.SetLeft(rectHighLight, _offsetFrom);
- 24 }
- 25 }
- 26 }
- 27
- 28 //最大值变化
- 29 private void MaxValuePropertyChanged()
- 30 {
- 31 if (MaxValue > Maximum)
- 32 {
- 33 MaxValue = Maximum;
- 34 return;
- 35 }
- 36 if (MaxValue < MinValue)
- 37 {
- 38 MinValue = MaxValue;
- 39 }
- 40 //滑块位置变化
- 41 _offsetTo = (MaxValue - Minimum) * rect.ActualWidth / (Maximum - Minimum) - 8;
- 42 Canvas.SetLeft(ellTo, _offsetTo);
- 43 //高亮矩形长度和位置的变化
- 44 if (_offsetFrom != -1)
- 45 {
- 46 double diff = _offsetTo - _offsetFrom;
- 47 if (diff >= 0)
- 48 {
- 49 rectHighLight.Width = diff;
- 50 Canvas.SetLeft(rectHighLight, _offsetFrom);
- 51 }
- 52 }
- 53 }
取值的TextBox没有封装在用户控件里,是单独的两个TextBox跟依赖属性双向绑定的.注意绑定的时候触发方式最好不要用PropertyChanged,没有防抖效果,不然体验不是很好.回车触发就可以了.
前台双向绑定:
- 1 <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
- 2 <local:DoubleThumbSlider x:Name="dts" Width="500" Minimum="100" Maximum="200"></local:DoubleThumbSlider>
- 3 <TextBox Name="tMin" Width="48" Text="{Binding ElementName=dts,Path=MinValue,UpdateSourceTrigger=Explicit,Mode=TwoWay}" PreviewKeyUp="tbox_PreviewKeyUp"></TextBox>
- 4 <TextBlock Margin="5,0" Text="-"></TextBlock>
- 5 <TextBox Name="tMax" Width="48" Text="{Binding ElementName=dts,Path=MaxValue,UpdateSourceTrigger=Explicit,Mode=TwoWay}" PreviewKeyUp="tbox_PreviewKeyUp"></TextBox>
- 6 </StackPanel>
后台回车触发:
- 1 private void tbox_PreviewKeyUp(object sender, KeyEventArgs e)
- 2 {
- 3 if (e.Key == Key.Enter)
- 4 {
- 5 TextBox tbox = (TextBox)sender;
- 6 var binding = tbox.GetBindingExpression(TextBox.TextProperty);
- 7 binding.UpdateSource();
- 8 }
- 9 }
参考连接:
1.https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.uielement.capturemouse?view=windowsdesktop-6.0
WPF双滑块控件以及强制捕获鼠标事件焦点的更多相关文章
- 【WPF】监听WPF的WebBrowser控件弹出新窗口的事件
原文:[WPF]监听WPF的WebBrowser控件弹出新窗口的事件 WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗 ...
- WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件
在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件.例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开.在这个过程中,控 ...
- WPF滑块控件(Slider)的自定义样式
前言 每次开发滑块控件的样式都要花很久去读样式代码,感觉有点记不牢,所以特此备忘. 自定义滑块样式 首先创建项目,添加Slider控件. 然后获取Slider的Window样式,如下图操作. 然后弹出 ...
- 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步
深入理解MVC MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...
- 抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单
原文:抛砖引玉 [镜像控件] WPF实现毛玻璃控件不要太简单 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Vblegend_2013/articl ...
- WPF范围选择控件(RangeSelector)
原文:WPF范围选择控件(RangeSelector) 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/art ...
- WPF中Ribbon控件的使用
这篇博客将分享如何在WPF程序中使用Ribbon控件.Ribbon可以很大的提高软件的便捷性. 上面截图使Outlook 2010的界面,在Home标签页中,将所属的Menu都平铺的布局,非常容易的可 ...
- WPF 调用WinForm控件
WPF可以使用WindowsFormsHost控件做为容器去显示WinForm控件,类似的用法网上到处都是,就是拖一个WindowsFormsHost控件winHost1到WPF页面上,让后设置win ...
- InteropBitmap指定内存,绑定WPF的Imag控件时刷新问题。
1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性 创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32, 如果不是的话在绑定到I ...
随机推荐
- docker进阶_dockerswarm
DockerSwarm Docker Swarm简介 Docker Swarm的功能 Docker Swarm包含两个方面:docker安全集群,以及一个微服务应用引擎 集群方面,swarm将 ...
- 机器学习实战:用SVD压缩图像
前文我们了解了奇异值分解(SVD)的原理,今天就实战一下,用矩阵的奇异值分解对图片进行压缩. Learn by doing 我做了一个在线的图像压缩应用,大家可以感受一下. https://huggi ...
- python基础练习题(题目 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身)
day8 --------------------------------------------------------------- 实例013:所有水仙花数 题目 打印出所有的"水仙花 ...
- 手撸一个虚拟DOM,不错
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- 前台主页搭建、后台主页轮播图接口设计、跨域问题详解、前后端互通、后端自定义配置、git软件的初步介绍
今日内容概要 前台主页 后台主页轮播图接口 跨域问题详解 前后端打通 后端自定义配置 git介绍和安装 内容详细 1.前台主页 Homeviwe.vue <template> <di ...
- 【第六课】SHELL和计划任务(学习笔记)
4月15日学习笔记
- 【面试普通人VS高手系列】volatile关键字有什么用?它的实现原理是什么?
一个工作了6年的Java程序员,在阿里二面,被问到"volatile"关键字. 然后,就没有然后了- 同样,另外一个去美团面试的工作4年的小伙伴,也被"volatile关 ...
- Python 函数进阶-递归函数
递归函数 什么是递归函数 如果一个函数,可以自己调用自己,那么这个函数就是一个递归函数. 递归,递就是去,归就是回,递归就是一去一回的过程. 递归函数的条件 一般来说,递归需要边界条件,整个递归的结构 ...
- 新鲜出炉:appium2.0+ 单点触控和多点触控新的解决方案
在 appium2.0 之前,在移动端设备上的触屏操作,单手指触屏和多手指触屏分别是由 TouchAction 类,Multiaction 类实现的. 在 appium2.0 之后,这 2 个方法将会 ...
- 海量数据存储ClickHouse
ClickHouse介绍 ClickHouse的由来和应用场景 俄罗斯Yandex在2016年开源,使用C++编写的列式存储数据库,近几年在OLAP领域大范围应用 官网:https://clickho ...