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 ...
随机推荐
- 如何实现 antd table 自动调整可视高度(纵向滚动条,scrollY)
一.事情的起因 最近在做的项目中有大量的表格,正常的表格高度是没有限制的,数据量很大的时候会出现表格内容以及分页信息超出可视窗口, 为了查看超出的部分就需要滚动页面但是这样就会把查询条件等信息滚出可视 ...
- Djang内置分页和自定义分页
内置分页 views from django.core.paginator import Paginator,Page,PageNotAnInteger def DJs_pages(request): ...
- 《Streaming Systems》第一章: Streaming 101
数据的价值在其产生之后,将随着时间的流逝逐渐降低.因此,为了获得最大化的数据价值,尽可能实时.快速地处理新产生的数据就显得尤为重要.实时数据处理将在越来越多的场景中体现出更大的价值所在 -- 实时即未 ...
- Golang 高阶函数
定义 高阶函数是接收函数作为参数或返回函数作为输出的函数. 高阶函数是对其他函数进行操作的函数,要么将它们作为参数,要么返回它们. 举例 函数作为参数 package main import &quo ...
- 2003031121-浦娟-python数据分析五一假期作业
项目 内容 课程班级博客链接 20级数据班(本) 这个作业要求链接 Python作业 博客名称 2003031121-浦娟-python数据分析五一假期作业 要求 每道题要有题目,代码(使用插入代码, ...
- 手脱NsPacK壳
1.查壳 使用PEiD未能检测到壳信息,这时,我们更换其他工具 从图中可以看到壳的信息为[NsPacK(3.x)[-]] 2.百度壳信息 北斗程序压缩(Nspack)是一款压缩壳.主要的选项是:压缩资 ...
- Base64隐写
0x00: 前言 Base64编码的作用: 将一些特殊的字符转换成常见的字符.特殊的字符可能是不可见字符或者是大于ascii码127的,将其变成常见的字符(在base64中为a~z A~Z 0~9 + ...
- Sharding JDBC案例实战
基础分库 以下实例基于shardingsphere 4.1.0 + SpringBoot 2.2.5.RELEASE版本 依赖导入: <properties> <project.bu ...
- 6.Docker网络
什么是 Docker网络 docker 不启动,默认网络情况 ens33 lo virbr0 在 CentOS7 的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的 ...
- 好客租房32-事件绑定this指向(class实例方法)
class实例方法 利用箭头函数的class实例方法 //导入react import React from 'react' import ReactDOM from 'react-dom' // ...