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 ...
随机推荐
- JS_进阶-遍历对象属性、数组输出、Math、正则表达式匹配
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- 论文解读(IGSD)《Iterative Graph Self-Distillation》
论文信息 论文标题:Iterative Graph Self-Distillation论文作者:Hanlin Zhang, Shuai Lin, Weiyang Liu, Pan Zhou, Jian ...
- c++:-2
上节介绍C++的函数介绍:c++:-1,本节学习类与对象 类与对象 定义 类定义 class 类名称 { public: 公有成员(外部接口) private: 私有成员 protected: 保护型 ...
- Citus 11(分布式 PostgreSQL) 文档贡献与本地运行
Citus 可以使用分片跨多台计算机来水平缩放查询. 其查询引擎会将这些服务器的传入 SQL 查询并行化,加快大型数据集上的响应. 它为需要比其他部署选项更大规模和更高性能的应用程序提供服务:通常,工 ...
- 什么是边缘CDN和虚拟CDN (vCDN)?
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 如今CDN有哪些局限性? 现如今,内容和游戏提供商正面临着越来越大的压力,它们需要向最终用户提 ...
- viewport布局
1.viewport实例 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <h ...
- AQS源码三视-JUC系列
AQS源码三视-JUC系列 前两篇文章介绍了AQS的核心同步机制,使用CHL同步队列实现线程等待和唤醒,一个int值记录资源量.为上层各式各样的同步器实现画好了模版,像已经介绍到的ReentrantL ...
- Spring Boot+微信小程序_保存微信登录者的个人信息
1. 前言 微信小程序开发平台,提供有一类 API,可以让开发者获取到微信登录用户的个人数据.这类 API 统称为开放接口. Tip:微信小程序开发平台,会把微信登录用户的个人信息分为明文数据和敏感数 ...
- WSL2+Docker+IDEA一站式开发调试
WSL2+Docker+IDEA一站式开发调试 前言 我们知道,Docker是一个容器引擎:对于开发者来说,使用Dokcer容器部署各种开发需要的中间件(比如myql.redis)会非常简单方便: ...
- 透过实例demo带你认识gRPC
摘要:gRPC是基于定义一个服务,指定一个可以远程调用的带有参数和返回类型的的方法.在服务端,服务实现这个接口并且运行gRPC服务处理客户端调用. 本文分享自华为云社区<gRPC介绍以及spri ...