WPF双滑块控件以及强制捕获鼠标事件焦点

打印 上一主题 下一主题

主题 876|帖子 876|积分 2628

效果


概述

最近有个小需求要用双滑块表示一个取值范围,于是就简单做了个用户控件,在此记录下.
使用矩形Rectangle表示范围,椭圆Ellipse表示滑块,使用Canvas控制滑块的左右移动.
椭圆的鼠标按下事件里强制获取鼠标事件焦点,避免移动过快或移出控件范围时,滑块就不跟着跑了.椭圆的鼠标抬起事件释放强制获取鼠标事件焦点
代码部分

需求比较简单,只定义了4个依赖属性,范围的最大值和最小值,取值的最大值和最小值.
接下来就是计算滑块和高亮矩形的位置,计算时注意减去椭圆Ellipse控件(圆)的半径,使圆心对准值,而不是左侧对准值.
鼠标移动的时候,计算当前位置对应的值,去改变依赖属性的值:
  1. 1         private void ell_MouseMove(object sender, MouseEventArgs e)
  2. 2         {
  3. 3             if (e.LeftButton == MouseButtonState.Pressed)
  4. 4             {
  5. 5                 double percentage = e.GetPosition(rect).X / rect.ActualWidth;
  6. 6                 double value = (Maximum - Minimum) * percentage + Minimum;
  7. 7                 if (_ellFromPressed)
  8. 8                 {
  9. 9                     MinValue = (int)value;
  10. 10
  11. 11                 }
  12. 12                 if (_ellToPressed)
  13. 13                 {
  14. 14                     MaxValue = (int)value;
  15. 15                 }
  16. 16             }
  17. 17         }
复制代码
 
依赖属性的值变化,引起滑块的位置变化和高亮滑块宽度和位置的变化:
  1. 1         //最小值变化
  2. 2         private void MinValuePropertyChanged()
  3. 3         {
  4. 4             if (MinValue < Minimum)
  5. 5             {
  6. 6                 MinValue = Minimum;
  7. 7                 return;
  8. 8             }
  9. 9             if (MinValue > MaxValue)
  10. 10             {
  11. 11                 MaxValue = MinValue;
  12. 12             }
  13. 13             //滑块位置变化
  14. 14             _offsetFrom = (MinValue - Minimum) * rect.ActualWidth / (Maximum - Minimum) - 8;
  15. 15             Canvas.SetLeft(ellFrom, _offsetFrom);
  16. 16             //高亮矩形长度和位置的变化
  17. 17             if (_offsetTo != -1)
  18. 18             {
  19. 19                 double diff = _offsetTo - _offsetFrom;
  20. 20                 if (diff >= 0)
  21. 21                 {
  22. 22                     rectHighLight.Width = diff;
  23. 23                     Canvas.SetLeft(rectHighLight, _offsetFrom);
  24. 24                 }
  25. 25             }
  26. 26         }
  27. 27
  28. 28         //最大值变化
  29. 29         private void MaxValuePropertyChanged()
  30. 30         {
  31. 31             if (MaxValue > Maximum)
  32. 32             {
  33. 33                 MaxValue = Maximum;
  34. 34                 return;
  35. 35             }
  36. 36             if (MaxValue < MinValue)
  37. 37             {
  38. 38                 MinValue = MaxValue;
  39. 39             }
  40. 40             //滑块位置变化
  41. 41             _offsetTo = (MaxValue - Minimum) * rect.ActualWidth / (Maximum - Minimum) - 8;
  42. 42             Canvas.SetLeft(ellTo, _offsetTo);
  43. 43             //高亮矩形长度和位置的变化
  44. 44             if (_offsetFrom != -1)
  45. 45             {
  46. 46                 double diff = _offsetTo - _offsetFrom;
  47. 47                 if (diff >= 0)
  48. 48                 {
  49. 49                     rectHighLight.Width = diff;
  50. 50                     Canvas.SetLeft(rectHighLight, _offsetFrom);
  51. 51                 }
  52. 52             }
  53. 53         }
复制代码
 
取值的TextBox没有封装在用户控件里,是单独的两个TextBox跟依赖属性双向绑定的.注意绑定的时候触发方式最好不要用PropertyChanged,没有防抖效果,不然体验不是很好.回车触发就可以了.
前台双向绑定:
  1. 1         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
  2. 2             <local:DoubleThumbSlider x:Name="dts" Width="500" Minimum="100" Maximum="200"></local:DoubleThumbSlider>
  3. 3             <TextBox Name="tMin" Width="48" Text="{Binding ElementName=dts,Path=MinValue,UpdateSourceTrigger=Explicit,Mode=TwoWay}" PreviewKeyUp="tbox_PreviewKeyUp"></TextBox>
  4. 4             <TextBlock Margin="5,0" Text="-"></TextBlock>
  5. 5             <TextBox Name="tMax" Width="48" Text="{Binding ElementName=dts,Path=MaxValue,UpdateSourceTrigger=Explicit,Mode=TwoWay}" PreviewKeyUp="tbox_PreviewKeyUp"></TextBox>
  6. 6         </StackPanel>
复制代码
 
后台回车触发:
  1. 1         private void tbox_PreviewKeyUp(object sender, KeyEventArgs e)
  2. 2         {
  3. 3             if (e.Key == Key.Enter)
  4. 4             {
  5. 5                 TextBox tbox = (TextBox)sender;
  6. 6                 var binding = tbox.GetBindingExpression(TextBox.TextProperty);
  7. 7                 binding.UpdateSource();
  8. 8             }
  9. 9         }
复制代码
 
 
 源码下载:DoubleThumbSlider.zip
 
参考连接:
1.https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.uielement.capturemouse?view=windowsdesktop-6.0

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表