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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

全文完,感谢阅读!