WPF 用户控件分享之边上带输入框的圆圈

WPF 用户控件分享之边上带输入框的圆圈

独立观察员 2022 年 8 月 20 日

最近有这样一个需求,有一圈圆形,每个圆形边上有个输入框,以下是完成后的效果图:

3aa81e2511c8fd415cbfab2e68b5981f.png

拿到这个需求后,分析界面上每个圆形和输入框应该视为一个用户控件,且输入框相对于圆形的位置不是一致的,所以应该要能够通过一个属性来设置输入框的位置。那么就以这个为突破口,创建一个用户控件,在代码隐藏页中添加一个用于控制输入框位置的依赖属性 “TextBoxPlacement”:

8730a24f8c044832b70d9b8992fc066f.png

【题外话]】添加依赖属性的方法为,输入 “propdp” 然后按 Tab 键(也就是使用官方提供的代码片段),然后修改类型、修改名称、修改所属类、修改默认值,如下:

5a5de193e3cc125f3b85481f4568af0d.png

继续说回 TextBoxPlacement 属性,我给它的类型是 PlacementMode,这是借用的 Popup 控件的方位属性:

400f4b677c1db81b7dba55102f26a2f0.png

这是个枚举,有很多取值情况,本次只是用到了它的子集(上下左右):

2883defb322353b5b9720b76a08bc413.png

好了,控制位置的属性有了,那么怎么动态切换呢?别急,我们先来看看整个用户控件的界面布局:

cbe5d1f55848aa5066f5c3690ceb825a.png

可以看到,界面上就只有一个 Control 元素,给它设置了一个样式,将在该样式中使用 DataTrigger(数据触发器)来切换不同的控件模板,从而改变布局。最开始想用数据模板选择器的,后来发现那个应该是适用于列表控件中依据数据不同从而动态选择子项的模板的情况,不适用于这种用户控件中。

最重要的就是给 Control 设置的样式 “CircleWithTextBoxStyle”:

c0d7f93546ad8a9f6649be7660542d08.png

上下左右这四种情况都是通过设置 Control 的 Template 的属性(具体是控件模板 ControlTemplate)来实现不同的布局的。默认是输入框在圆圈右边的布局,其余的 左、上、下 则是通过数据触发器 DataTrigger 来实现的,数据触发器绑定 UserControl 的 TextBoxPlacement 属性(前面我们添加的那个),依据不同的值来切换不同的控件模板。至于四种情况的布局实现,容器都是 StackPanel,左和右的时候是横向的,上和下的时候是纵向的;左和上的时候输入框部分写在前面,右和下的时候输入框部分写在后面。

圆圈和输入框部分也分别是一个 Control 元素,通过样式设置模板,样式如下:

8b7d50d0005171adbe2fdea73e9d7fa6.png

圆圈就是一个 Border,使用样式 BorderStyle。圈内文本是一个 TextBlock,使用样式 InfoStyle,文本内容绑定了一个依赖属性 CircleInfo。输入框就是一个 TextBox,使用样式 TextBoxStyle。

先来看看圆圈内文本样式,涉及两个依赖属性,一个是文字颜色属性 CircleForeground,另一个是文字大小属性 InfoFontSize(输入框也是用这个设置文字大小的),具体如下:

be39fab3697bb8403feb29802ed878e9.png

然后是圆圈和输入框的样式,涉及圆圈边框色属性 CircleBorderBackground,圆圈背景色属性 CircleBackground,圆圈直径和输入框宽度的共用属性 CircleAndTextBoxWidth,以及输入框的值属性 TextBoxValue: 

e82ba94688dd6259dac2ef2a99376f28.png

【题外话]】此处用到了一个叫做 CalcBinding 的库,可以绑定表达式,这样就省去了转换器,感兴趣的朋友可以自己搜索研究一下。

比如,此处的圆圈,是用宽高相等的 Border,然后圆角 CornerRadius 设为宽高的一半,直接绑定为 'Width / 2' 即可,十分方便。再比如,输入框和圆圈等宽,高度为宽度的五分之三,直接绑定 'Width * 3 / 5' 即可。

后面提到的依赖属性如下:

0c52cfa20ade2b20d7ae9d19e723c9b6.png

好了,整个用户控件都讲完了,那么如何使用呢?很简单,直接放在界面上,然后设置需要的依赖属性即可(此 Demo 源码地址文末会给出):

05479ca934bedde87894bb30f2e37909.png

开局那幅图(一整圈)的布局也可以浅看一下:

c2ba3f18d6ed1b78c374af98d3936236.png

其实也是分为上下左右四部分,通过 ItemsControl 来绑定数据,然后在数据模板中使用本文介绍的用户控件,样式如下,一些属性进行了设置和绑定:

03e7cf4817af71ce0af29c8761f29479.png

由于界面上的编号不是按布局的顺序来的,所以初始化时做了些处理:

09da4186eb25a48a946d22a7f4ca5739.png

Demo 源码地址(子模块中有用户控件源码):

https://gitee.com/dlgcy/DLGCY_WPFPractice/tree/Blog20220820 

f5bcc31656a9ff0e5e8206e6b5a22d53.png

全文完,感谢阅读!


WPF

分享一个 WPF 气泡弹框

WPF 表单验证之 INotifyDataErrorlnfo 接口的使用示例

[翻译] WPF 中用户控件 DataContext/Binding 和依赖属性的问题

OxyPlot 导出图片及 WPF 元素导出为图片的方法

让 WPF 的 RadioButton 支持再次点击取消选中的功能

WPF DataGrid 如何将被选中行带到视野中

WPF 触屏事件后触发鼠标事件的问题及 DataGrid 误触问题

WPF DataGrid 通过自定义表头模拟首行固定

WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换

【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF

WPF 使用 Expression Design 画图导出及使用 Path 画图

WPF MVVM 弹框之等待框

解决 WPF 绑定集合后数据变动界面却不更新的问题(使用 ObservableCollection)

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面

真・WPF 按钮拖动和调整大小

WPF MVVM 模式下的弹窗

WPF 让一组 Button 实现 RadioButton 的当前样式效果

WPF 原生绑定和命令功能使用指南

WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘

在WPF的MVVM模式中使用OCX组件

第三方库使用

WPF 表格控件 ReoGrid 的简单使用

OxyPlot.WPF 公共属性一览

OxyPlot.Wpf 图表控件使用备忘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值