- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
HandyControl 对 WPF 原生PasswordBox控件提供了一套分层样式体系,核心文件为 src/Shared/HandyControl_Shared/Themes/Styles/PasswordBox.xaml 与 src/Shared/HandyControl_Shared/Themes/Styles/Base/PasswordBoxBaseStyle.xaml。本文围绕PasswordBoxBaseStyle、PasswordBoxExtendBaseStyle、PasswordBoxExtend三个关键样式展开,说明如何使用附加属性为原生密码框添加标题(Title)与水印(Placeholder),并深入解读PasswordBoxAttach.PasswordLength的底层实现机制。读完本文,你将能直接在项目中对原生PasswordBox应用 HandyControl 的默认样式、扩展样式及小尺寸变体,并理解其模板触发器与附加属性的协作原理。
一、样式层级总览:三个关键 Style
HandyControl 为原生PasswordBox定义了三层递进关系,全部基于BasedOn继承:
| 样式 Key | 继承关系 | 用途 |
|---|---|---|
PasswordBoxBaseStyle | 基于InputElementBaseStyle | 原生密码框默认样式,不推荐直接使用,仅作为其它样式的基类 |
PasswordBoxExtendBaseStyle | BasedOnPasswordBoxBaseStyle | 扩展默认样式,同样不推荐直接使用,只作为派生基类 |
PasswordBoxExtend | BasedOnPasswordBoxExtendBaseStyle | 对外可用的扩展样式,借助附加属性实现标题、水印功能 |
此外还有两个便捷变体:PasswordBox.Small(基于PasswordBoxBaseStyle,设置MinHeight="20"、Padding="6,0")和PasswordBoxExtend.Small(基于PasswordBoxExtend,同时通过hc:InfoElement.MinContentHeight、hc:InfoElement.ContentHeight、hc:TitleElement.MarginOnTheLeft、hc:TitleElement.MarginOnTheTop调整紧凑布局),定义见 PasswordBox.xaml。
需要特别注意的是:文档与源码都明确强调PasswordBoxBaseStyle和PasswordBoxExtendBaseStyle不应该被直接引用,而应始终被其它样式以BasedOn的方式复用,这与 HandyControl 整体"基类样式 + 派生样式"的设计约定一致。
二、PasswordBoxBaseStyle:原生密码框的基础外观
PasswordBoxBaseStyle在 PasswordBoxBaseStyle.xaml 中定义,它集中设置了一组输入控件通用属性:
PasswordChar默认值为●(圆点);KeyboardNavigation.TabNavigation="None",避免 Tab 导航干扰;HorizontalContentAlignment="Left";AllowDrop="True",支持拖放;ScrollViewer.PanningMode="VerticalFirst"、Stylus.IsFlicksEnabled="False",优化触摸与手写笔输入体验。
其控件模板以hc:SimplePanel为根,内部包含一个Border(背景/边框容器)和一个ScrollViewer(名为PART_ContentHost,即 WPF 密码框约定的内容宿主)。模板触发器定义了三态边框反馈:
IsEnabled=false:border透明度降为0.4;IsMouseOver=true:BorderBrush切换为{DynamicResource SecondaryBorderBrush};IsFocused=true:BorderBrush切换为主题色{DynamicResource PrimaryBrush}。
Border的圆角通过hc:BorderElement.CornerRadius附加属性绑定,因此你可以像下面这样让密码框直接具备圆角外观:
<PasswordBox PasswordChar="*" VerticalAlignment="Center" Width="120" />上面的示例未显式指定Style,此时将命中 HandyControl 提供的无 Key 隐式样式(<Style BasedOn="{StaticResource PasswordBoxBaseStyle}" TargetType="PasswordBox"/>,见 PasswordBox.xaml)。这也是文档中给出的"原生密码框默认样式"用例。
三、PasswordBoxExtend:让原生密码框拥有标题与水印
PasswordBoxExtendBaseStyle(PasswordBoxBaseStyle.xaml)在PasswordBoxBaseStyle基础上进一步注入扩展能力:
hc:InfoElement.Symbol="●":默认标记符号;hc:InfoElement.ContentHeight为NaN、hc:InfoElement.MinContentHeight取DefaultControlHeight(默认控件高度),控制内容区域高度;hc:PasswordBoxAttach.IsMonitoring="True":默认开启密码长度监测(详见下一节);- 模板默认使用
PasswordBoxExtendTopTemplate(标题在上方),当hc:InfoElement.TitlePlacement为Left时通过样式触发器切换到PasswordBoxExtendLeftTemplate(标题在左侧),并把Width设为Auto。
PasswordBoxExtend是继承该基类、无额外设置的对外样式(PasswordBox.xaml)。文档给出的核心用法如下:
<!--为使普通密码输入文本框显示水印,需要设定 PasswordBoxAttach.PasswordLength="0"--> <PasswordBox Style="{DynamicResource PasswordBoxExtend}" PasswordChar="*" hc:PasswordBoxAttach.PasswordLength="0" hc:InfoElement.Placeholder="请输入密码" VerticalAlignment="Center" Width="120"></PasswordBox> <PasswordBox Style="{DynamicResource PasswordBoxExtend}" PasswordChar="*" hc:TitleElement.Title="用户密码:" hc:TitleElement.TitlePlacement="Top" VerticalAlignment="Center" Width="120"></PasswordBox>第一个示例实现"带水印的密码输入框",第二个示例实现"带标题的密码输入框"。两者可以同时组合使用(标题 + 水印 + 必填标记),这在 demo 页面 NativePasswordBoxDemo.xaml 中有完整呈现。
3.1 水印的显示原理:PasswordBoxAttach.PasswordLength
水印能正确显示的关键在于附加属性hc:PasswordBoxAttach.PasswordLength。在PasswordBoxExtendTopTemplate/PasswordBoxExtendLeftTemplate中,模板内有一个名为placeholder的TextBlock,默认Visibility="Collapsed",其文本绑定hc:InfoElement.Placeholder;模板触发器如下:
<Trigger Property="hc:PasswordBoxAttach.PasswordLength" Value="0"> <Setter Property="Visibility" TargetName="placeholder" Value="Visible"/> </Trigger>也就是说:当密码长度为 0(即尚未输入任何字符)时,水印可见;一旦用户输入任意字符,水印自动隐藏。这正是文档中注释"为使普通密码输入文本框显示水印,需要设定PasswordBoxAttach.PasswordLength="0""的原因——必须把该附加属性显式设置为 0,触发器才能命中并显示水印。
该附加属性的实现位于 src/Shared/HandyControl_Shared/Controls/Attach/PasswordBoxAttach.cs:
PasswordLengthProperty:int类型附加属性,默认值ValueBoxes.Int0Box(即 0),通过SetPasswordLength/GetPasswordLength访问;IsMonitoringProperty:bool类型附加属性,声明了FrameworkPropertyMetadataOptions.Inherits(沿元素树向下继承),默认false;- 当
IsMonitoring变为true时,OnIsMonitoringChanged会为该PasswordBox挂接PasswordChanged事件;事件处理器PasswordChanged会把当前Password.Length写回PasswordLength附加属性,从而驱动模板触发器。
PasswordBoxExtendBaseStyle将IsMonitoring默认为True,因此只要应用扩展样式,密码长度就会随输入实时更新,水印的显隐也因此完全自动化。
3.2 标题与水印来自哪:InfoElement 与 TitleElement 附加属性
水印文本通过hc:InfoElement.Placeholder设置,其定义在 src/Shared/HandyControl_Shared/Controls/Attach/InfoElement.cs 中,类型为string,且同样带Inherits选项。InfoElement还提供了与表单输入密切相关的其它附加属性:
hc:InfoElement.Necessary(bool):是否必填,为true时在标题右侧渲染红色必填标记;hc:InfoElement.Symbol(string):必填/标记符号,扩展样式默认●;hc:InfoElement.ContentHeight/MinContentHeight/MaxContentHeight:内容区高度控制,默认分别为28.0、28.0、+∞;hc:InfoElement.ShowClearButton(bool):是否在悬停时显示一键清空按钮(配合hc:PasswordBox扩展控件使用);hc:InfoElement.RegexPattern、hc:InfoElement.IsReadOnly:正则校验与只读相关。
标题文本通过hc:TitleElement.Title设置。TitleElement(src/Shared/HandyControl_Shared/Controls/Attach/TitleElement.cs)还定义了布局相关的附加属性:
TitlePlacement(TitlePlacementType):标题位置,默认Top(上方),可设为Left(左侧);TitleWidth(GridLength):标题列宽,默认Auto,左置标题时常用定值(如 demo 中的140);HorizontalAlignment/VerticalAlignment:标题对齐方式;MarginOnTheLeft/MarginOnTheTop:左置 / 上置标题的边距;Padding、MinHeight、MinWidth等辅助布局属性。
这些属性在PasswordBoxExtendTopTemplate/PasswordBoxExtendLeftTemplate中通过RelativeSource={RelativeSource TemplatedParent}绑定到模板元素,从而保证标题、标记、水印与输入框在同一个模板内协同工作。
四、完整可运行示例:标题、水印、必填、左置组合
综合上述特性,一个"标题在上方 + 水印 + 必填标记"的密码框可以写成:
<PasswordBox Style="{DynamicResource PasswordBoxExtend}" PasswordChar="*" hc:PasswordBoxAttach.PasswordLength="0" hc:InfoElement.Title="登录密码" hc:InfoElement.Placeholder="请输入密码" hc:InfoElement.Necessary="True" VerticalAlignment="Center" Width="240"/>若希望标题位于左侧并固定宽度,则使用TitlePlacement="Left"与TitleWidth:
<PasswordBox Style="{DynamicResource PasswordBoxExtend}" PasswordChar="*" hc:PasswordBoxAttach.PasswordLength="0" hc:InfoElement.Title="用户密码:" hc:InfoElement.TitlePlacement="Left" hc:InfoElement.TitleWidth="140" hc:InfoElement.Placeholder="请输入密码" hc:InfoElement.Necessary="True" VerticalAlignment="Center" Width="380"/>这两个组合分别对应 demo 页面 NativePasswordBoxDemo.xaml 中的第二、第四组示例。标题在左侧时,样式触发器会自动将模板切换为PasswordBoxExtendLeftTemplate(PasswordBoxBaseStyle.xaml),该模板用两列Grid划分标题区与输入区,输入区列宽由TitleWidth决定。
五、小尺寸变体与扩展控件说明
5.1 紧凑布局:PasswordBoxExtend.Small
在工具栏、表格等需要紧凑排布的场景,可使用PasswordBoxExtend.Small:
<PasswordBox Style="{DynamicResource PasswordBoxExtend.Small}" PasswordChar="*" hc:PasswordBoxAttach.PasswordLength="0" hc:InfoElement.Title="用户密码:" hc:InfoElement.TitlePlacement="Left" hc:InfoElement.TitleWidth="140" hc:InfoElement.Placeholder="请输入密码" hc:InfoElement.Necessary="True" Width="380"/>该样式在 PasswordBox.xaml 中定义,额外设置MinHeight="20"、Padding="6,0",并把InfoElement.ContentHeight/MinContentHeight压缩到20,同时调整了标题的左右/上下边距,使整体高度明显小于默认控件。
5.2 更强大的 hc:PasswordBox 扩展控件
除本文所述的原生PasswordBox样式外,HandyControl 还提供了独立的扩展控件hc:PasswordBox(位于HandyControl.Controls命名空间),其基类样式为PasswordBoxPlusBaseStyle。它额外支持:
ShowEyeButton:显示"眼睛"切换按钮,可在明文与密文间切换(模板中由ToggleButton+IconSwitchElement实现);hc:InfoElement.ShowClearButton:悬停时显示清空按钮;IsSafeEnabled:是否启用安全模式(demo 中通过绑定UnsafePassword演示明文回显)。
相关模板PasswordBoxPlusTopTemplate/PasswordBoxPlusLeftTemplate同样定义于 PasswordBoxBaseStyle.xaml,完整用法可参考 PasswordBoxDemo.xaml。
六、小结
围绕"原生密码框"这一场景,HandyControl 的解决方案可以归纳为一条清晰的主线:
- 基类样式(
PasswordBoxBaseStyle/PasswordBoxExtendBaseStyle)负责统一外观与交互反馈,并通过BasedOn逐层复用,不直接对外使用; - 对外样式(
PasswordBoxExtend)借助InfoElement.Placeholder、TitleElement.Title等附加属性实现标题、水印、必填标记,并通过PasswordBoxAttach.IsMonitoring+PasswordChanged事件实时同步PasswordLength,驱动模板触发器完成水印显隐; - 模板双布局(
Top/Left)由TitlePlacement一键切换,配合TitleWidth、MarginOnTheLeft等属性即可适配表单与紧凑场景。
掌握这套"附加属性 + 模板触发器"的组合模式后,你不仅能直接复用PasswordBoxExtend,还能参照 PasswordBoxBaseStyle.xaml 的写法,为其它原生输入控件定制同样具备标题、水印能力的分层样式。
- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
相关推荐
HandyControl DatePicker 日期选择器样式体系全解析:从默认样式到标题、水印与必填扩展
HandyControl DatePicker 日期选择器样式体系全解析:从默认样式到标题、水印与必填扩展 本指南以 HandyControl 原生 WPF D
UI组件桌面应用HandyControl 文本框(TextBox)样式体系实战指南:标题、水印与必填标记的附加属性用法
HandyControl 文本框(TextBox)样式体系实战指南:标题、水印与必填标记的附加属性用法 本文以 HandyControl 原生文本框 TextB
UI组件桌面应用HandyControl PasswordBox 密码框控件完全指南:从基础用法到源码级原理剖析
HandyControl PasswordBox 密码框控件完全指南:从基础用法到源码级原理剖析 本文围绕 HandyControl 中的 PasswordBo
UI组件桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考