尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HandyControl ListBox 列表框样式体系全解:从 BaseStyle 继承链到 Custom 自定义布局实战

HandyControl ListBox 列表框样式体系全解:从 BaseStyle 继承链到 Custom 自定义布局实战 UI组件桌面应用【免费下载链接】HandyControlContains some simple and commonly used WPF controls项目地址https://gitcode.com/gh_mirrors/ha/HandyControl点击查看免费下载本篇技术指南围绕 HandyControl 原生控件native_controls中ListBox 列表框的完整样式体系展开系统讲解ListBoxBaseStyle、ListBoxCustom以及四种布局变体WrapPanelHorizontalListBox、WrapPanelVerticalListBox、StackPanelHorizontalListBox、StackPanelVerticalListBox的继承关系、源码实现与实战用法。读完本文你将掌握如何以BasedOn方式在 HandyControl 主题之上定制 ListBox、如何通过自定义ItemTemplate实现个性化数据展示以及如何一键切换水平/垂直的 StackPanel 与 WrapPanel 布局并理解选中态、空列表占位与选中集合双向绑定等底层机制。一、ListBox 样式体系一览一条继承链贯穿五种样式HandyControl 为 ListBox 提供的样式并非彼此独立而是构成了一条清晰的BasedOn继承链。官方文档doc/source/handycontrol/native_controls/listBox/index.md定义的继承关系如下ListBoxBaseStyle └── ListBoxCustom保留基础属性数据展示交由用户自定义 ├── WrapPanelHorizontalListBoxWrapPanel 水平 ├── WrapPanelVerticalListBoxWrapPanel 垂直 ├── StackPanelHorizontalListBoxStackPanel 水平 └── StackPanelVerticalListBoxStackPanel 垂直这五种样式均定义在 Themes/Styles/ListBox.xaml 中而同目录下还存在一个隐式默认样式不带x:Key作用于所有 ListBox!--默认样式-- Style BasedOn{StaticResource ListBoxBaseStyle} TargetTypeListBox/也就是说只要你引入 HandyControl 主题资源所有未显式指定Style的 ListBox 会自动应用ListBoxBaseStyle的外观。五种具名样式则专门用于需要差异化定制的场景。二、ListBoxBaseStyle所有样式的基座2.1 设计定位ListBoxBaseStyle是 ListBox 的默认基础样式。官方文档明确指出不推荐直接使用它应该始终被其它样式以BasedOn的方式使用。这样做的目的是让派生样式只需覆盖少数属性即可获得完整的默认外观避免重复定义模板。在自定义样式时标准写法如下Style BasedOn{StaticResource ListBoxBaseStyle} TargetTypeListBox/BasedOn会完整继承基样式中的所有 Setter 与模板你可以在此基础上继续追加自己的 Setter例如覆盖背景色、圆角、间距等。2.2 源码剖析基样式的组成ListBoxBaseStyle的真正实现位于 Themes/Styles/Base/ListBoxBaseStyle.xaml。它实际上由两部分组成1ListBoxItemBaseStyle列表项基础样式Style x:KeyListBoxItemBaseStyle BasedOn{StaticResource BaseStyle} TargetTypeListBoxItem Setter PropertyPadding Value10,0/ Setter PropertyMinHeight Value{StaticResource DefaultControlHeight}/ Setter PropertyBackground Value{DynamicResource RegionBrush}/ Setter PropertyBorderBrush ValueTransparent/ Setter PropertyBorderThickness Value0/ Setter PropertyMargin Value0,0,0,2 / !-- 模板带圆角的 Border ContentPresenter -- /Style列表项模板的关键交互触发器Style.Triggers定义了完整的选中态反馈状态触发条件效果悬停IsMouseOverTrue背景切换为SecondaryRegionBrush选中IsSelectedTrue背景切换为主题主色PrimaryBrush前景切换为TextIconBrush失焦选中IsSelectedTrue且Selector.IsSelectionActivefalse且hc:VisualElement.StaysHighlightedfalse背景切换为DarkDefaultBrush避免窗口失焦时选中项消失禁用IsEnabledfalse整体不透明度降至 0.4边缘内容hc:EdgeElement.ShowEdgeContenttrue模板切换为「16×16 左侧内容 正文」的横向布局其中圆角由附加属性hc:BorderElement.CornerRadius提供默认取DefaultCornerRadius资源。2ListBoxBaseStyle列表框基础样式Setter PropertyBackground Value{DynamicResource RegionBrush}/ Setter PropertyBorderBrush Value{DynamicResource BorderBrush}/ Setter PropertyBorderThickness Value1/ Setter Propertyhc:ScrollViewer.HorizontalScrollBarVisibility ValueDisabled/ Setter Propertyhc:ScrollViewer.VerticalScrollBarVisibility ValueAuto/ Setter Propertyhc:ScrollViewer.CanContentScroll Valuetrue/ Setter Propertyhc:ScrollViewer.PanningMode ValueBoth/ Setter Propertyhc:BorderElement.CornerRadius Value{StaticResource DefaultCornerRadius}/ Setter PropertyItemContainerStyle Value{StaticResource ListBoxItemBaseStyle}/值得注意的细节滚动行为通过 HandyControl 附加属性控制默认水平滚动条禁用Disabled、垂直滚动条自动Auto、允许内容滚动CanContentScrolltrue保证虚拟化、支持双向触控平移PanningModeBoth空列表占位机制模板中使用hc:ToggleBlock绑定HasItems——有数据时展示ScrollViewer ItemsPresenter无数据时展示hc:Empty占位控件避免空白区域带来的突兀感圆角、边框、背景全部采用DynamicResource引用主题资源因此随皮肤SkinDark / SkinDefault / SkinViolet 等切换自动变色。此外ListBox.xaml 还基于ListBoxBaseStyle提供了紧凑变体ListBox.Small配套ListBoxItemBaseStyle.SmallPadding6,0、MinHeight24适合工具栏、下拉类紧凑场景。三、ListBoxCustom个性化定制数据的入口3.1 设计定位与用法ListBoxCustom继承自ListBoxBaseStyle保留了 ListBox 的基本属性样式边框、背景、滚动、选中反馈等而数据显示样式完全交由当前用户自定义从而实现个性化定制。官方文档给出的完整用例ListBox Margin10 ItemsSource{Binding Datas} Style{DynamicResource ListBoxCustom} ListBox.ItemTemplate DataTemplate Border BorderThickness1 BorderBrushBlack Margin0,5 DockPanel LastChildFillTrue Path DockPanel.DockLeft FillYellowGreen Width20 Margin10,0,10,0 HorizontalAlignmentCenter Data{DynamicResource BubbleTailGeometry}/Path TextBlock Padding10 Text{Binding Name}/TextBlock /DockPanel /Border /DataTemplate /ListBox.ItemTemplate /ListBox这段代码展示了典型用法ItemsSource绑定数据集合Style通过DynamicResource引用ListBoxCustom再通过ItemTemplate自定义每个条目的视觉呈现此例为一个带左边小图标、右侧文本的气泡式条目。注意官方示例统一使用DynamicResource引用样式便于在运行时切换主题或动态替换样式资源。3.2 源码剖析ListBoxItemCustom 做了什么ListBoxCustom之所以能实现完全自定义显示关键在于它同时替换了容器项样式源码见 ListBox.xamlStyle x:KeyListBoxItemCustom TargetTypeListBoxItem Setter PropertySnapsToDevicePixels ValueTrue/ Setter PropertyFocusVisualStyle Value{x:Null}/ Setter PropertyPadding Value0/ Setter PropertyBackground ValueTransparent/ Setter PropertyBorderBrush ValueTransparent/ Setter PropertyBorderThickness Value0/ Setter PropertyTemplate Setter.Value ControlTemplate TargetTypeListBoxItem ContentPresenter HorizontalAlignment{TemplateBinding HorizontalContentAlignment} SnapsToDevicePixels{TemplateBinding SnapsToDevicePixels} VerticalAlignment{TemplateBinding VerticalContentAlignment}/ /ControlTemplate /Setter.Value /Setter /Style Style x:KeyListBoxCustom BasedOn{StaticResource ListBoxBaseStyle} TargetTypeListBox Setter PropertyItemContainerStyle Value{StaticResource ListBoxItemCustom}/ Setter PropertyHorizontalContentAlignment ValueStretch/ /Style对比默认的ListBoxItemBaseStyle可以看到剥离了所有默认装饰背景、边框全部置为TransparentPadding0移除焦点虚线框FocusVisualStyle{x:Null}模板瘦身为纯ContentPresenter不再包裹默认 Border因此每个条目的背景、边框、间距完全由你的ItemTemplate决定HorizontalContentAlignmentStretch让ItemTemplate的根元素横向拉伸填满整行保证点击区域与条目宽度一致由于透明背景悬停/选中的默认变色被让位给你的自定义模板若仍需选中反馈可在你的DataTemplate内自行绑定触发器实现。四、四种布局样式WrapPanel 与 StackPanel 的横竖组合在ListBoxCustom之上HandyControl 提供了四种预置布局样式区别仅在ItemsPanel条目承载面板的容器类型与排列方向样式继承自容器排列方向WrapPanelHorizontalListBoxListBoxCustomWrapPanel水平自动换行WrapPanelVerticalListBoxListBoxCustomWrapPanel垂直自动换列StackPanelHorizontalListBoxListBoxCustomStackPanel水平单行StackPanelVerticalListBoxListBoxCustomStackPanel垂直单列4.1 WrapPanelHorizontalListBox水平换行布局容器为 WrapPanel水平方向显示条目从左到右排列空间不足时自动换行。ListBox Margin10 ItemsSource{Binding Datas} Style{DynamicResource WrapPanelHorizontalListBox} ListBox.ItemTemplate DataTemplate Border BorderThickness1 BorderBrushBlack Margin5,0 DockPanel LastChildFillTrue Path DockPanel.DockLeft FillYellowGreen Width20 Margin10,0,10,0 HorizontalAlignmentCenter Data{DynamicResource BubbleTailGeometry}/Path TextBlock Padding10 Text{Binding Name}/TextBlock /DockPanel /Border /DataTemplate /ListBox.ItemTemplate /ListBox4.2 WrapPanelVerticalListBox垂直换列布局容器为 WrapPanel垂直方向显示条目从上到下排列高度不足时自动换列。ListBox Margin10 ItemsSource{Binding Datas} Style{DynamicResource WrapPanelVerticalListBox} ListBox.ItemTemplate DataTemplate Border BorderThickness1 BorderBrushBlack Margin0,5 DockPanel LastChildFillTrue Path DockPanel.DockLeft FillYellowGreen Width20 Margin10,0,10,0 HorizontalAlignmentCenter Data{DynamicResource BubbleTailGeometry}/Path TextBlock Padding10 Text{Binding Name}/TextBlock /DockPanel /Border /DataTemplate /ListBox.ItemTemplate /ListBox4.3 StackPanelHorizontalListBox水平单行布局容器为 StackPanel水平方向显示所有条目在单行内依次排列不换行。ListBox Margin10 ItemsSource{Binding Datas} Style{DynamicResource StackPanelHorizontalListBox} ListBox.ItemTemplate DataTemplate Border BorderThickness1 BorderBrushBlack Margin5,0 DockPanel LastChildFillTrue Path DockPanel.DockLeft FillYellowGreen Width20 Margin10,0,10,0 HorizontalAlignmentCenter Data{DynamicResource BubbleTailGeometry}/Path TextBlock Padding10 Text{Binding Name}/TextBlock /DockPanel /Border /DataTemplate /ListBox.ItemTemplate /ListBox4.4 StackPanelVerticalListBox垂直单列布局容器为 StackPanel垂直方向显示所有条目在单列内依次排列即最接近原生 ListBox 的纵向列表形态。ListBox Margin10 ItemsSource{Binding Datas} Style{DynamicResource StackPanelVerticalListBox} ListBox.ItemTemplate DataTemplate Border BorderThickness1 BorderBrushBlack Margin0,1 DockPanel LastChildFillTrue Path DockPanel.DockLeft FillYellowGreen Width20 Margin10,0,10,0 HorizontalAlignmentCenter Data{DynamicResource BubbleTailGeometry}/Path TextBlock Padding10 Text{Binding Name}/TextBlock /DockPanel /Border /DataTemplate /ListBox.ItemTemplate /ListBox4.5 源码剖析四种布局的实现方式四种样式的源码实现极为简洁见 ListBox.xaml全部通过ItemsPanel属性注入预置的ItemsPanelTemplateStyle x:KeyWrapPanelHorizontalListBox BasedOn{StaticResource ListBoxCustom} TargetTypeListBox Setter PropertyItemsPanel Value{StaticResource WrapHorizontalItemsPanelTemplate}/ /Style Style x:KeyWrapPanelVerticalListBox BasedOn{StaticResource ListBoxCustom} TargetTypeListBox Setter PropertyItemsPanel Value{StaticResource WrapVerticalItemsPanelTemplate}/ /Style Style x:KeyStackPanelHorizontalListBox BasedOn{StaticResource ListBoxCustom} TargetTypeListBox Setter PropertyItemsPanel Value{StaticResource StackHorizontalItemsPanelTemplate}/ /Style Style x:KeyStackPanelVerticalListBox BasedOn{StaticResource ListBoxCustom} TargetTypeListBox Setter PropertyItemsPanel Value{StaticResource StackVerticalItemsPanelTemplate}/ /Style这些ItemsPanelTemplate定义于 Themes/Styles/Base/ItemsPanelTemplate.xaml是 HandyControl 布局体系的公共积木ItemsPanelTemplate x:KeyStackHorizontalItemsPanelTemplate StackPanel FocusVisualStyle{x:Null} OrientationHorizontal/ /ItemsPanelTemplate ItemsPanelTemplate x:KeyStackVerticalItemsPanelTemplate StackPanel FocusVisualStyle{x:Null}/ /ItemsPanelTemplate ItemsPanelTemplate x:KeyWrapHorizontalItemsPanelTemplate WrapPanel FocusVisualStyle{x:Null} HorizontalAlignmentCenter VerticalAlignmentCenter/ /ItemsPanelTemplate ItemsPanelTemplate x:KeyWrapVerticalItemsPanelTemplate WrapPanel FocusVisualStyle{x:Null} OrientationVertical HorizontalAlignmentCenter VerticalAlignmentCenter/ /ItemsPanelTemplate几个关键点StackVertical的 StackPanel 未设置Orientation默认即为垂直而StackHorizontal显式设为Horizontal两个 WrapPanel 模板均设置了居中对齐因此条目不足一行/一列时会在容器内居中呈现同文件还提供了VirtualizingStackHorizontal/VerticalItemsPanelTemplate虚拟化栈布局与DockItemsPanelTemplate等公共模板方便你在自定义控件时复用这类模板资源也复用于其他控件——例如 ElementGroupBaseStyle.xaml 中的元素分组即引用了相同的 Stack 面板模板可见该资源文件的公共性。五、ListBoxAttach.SelectedItems选中集合的双向绑定除了样式之外HandyControl 还针对 ListBox 提供了一项实用的附加能力将SelectedItems选中项集合暴露为可绑定的附加属性便于在 MVVM 中直接拿到多选结果。实现位于 Controls/Attach/ListBoxAttach.cspublic static readonly DependencyProperty SelectedItemsProperty DependencyProperty.RegisterAttached( SelectedItems, typeof(IList), typeof(ListBoxAttach), new FrameworkPropertyMetadata(default(IList), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsChanged));从注册参数可以看出类型为IList支持任何列表/集合类型的 ViewModel 属性默认双向绑定BindsTwoWayByDefault用户勾选时自动回写 ViewModel内部通过OnListBoxSelectionChanged在SelectionChanged事件中将listBox.SelectedItems复制到绑定属性反向设置时则清空并重建SelectedItems并用InternalActionProperty布尔标志防止双向同步造成的递归。XAML 中的典型用法命名空间hc引用 HandyControl如xmlns:hchttps://handyorg.github.io/handycontrolListBox ItemsSource{Binding Datas} SelectionModeMultiple Style{DynamicResource ListBoxCustom} hc:ListBoxAttach.SelectedItems{Binding SelectedItems}/这样在 ViewModel 中只需一个IList SelectedItems属性即可双向感知用户的选中变化无需手动挂接SelectionChanged事件。六、跨平台扩展Avalonia 版本的同名样式HandyControl 在 Avalonia 分支中提供了与 WPF 版本同构的 ListBox 主题见 src/Avalonia/HandyControl_Avalonia/Themes/Styles/ListBox.axaml。该文件以ControlTheme形式定义了ListBoxItemBaseStyle同样的RegionBrush背景、Padding10,0、MinHeightDefaultControlHeight并通过:pointerover、:selected、:disabled选择器实现悬停/选中/禁用反馈ListBoxBaseStyle同样包裹Border ScrollViewer ItemsPresenter圆角同样来自hc:BorderElement.CornerRadius隐式主题{x:Type ListBox}、紧凑变体ListBox.Small以及ListBoxItemCustomListBoxCustom的自定义模式与 WPF 版本一一对应。如果你的项目同时维护 WPF 与 Avalonia 双端这套样式命名与层级可以直接对照迁移大幅降低双端 UI 的维护成本。七、在 Demo 工程中查看实际效果HandyControl 的官方 Demo 提供了 ListBox 的真实运行样例见 src/Shared/HandyControlDemo_Shared/UserControl/Styles/ListBoxDemo.xaml。样例在hc:TransitioningContentControl内放置了一个WrapPanel并排展示了两个宽度 200 的 ListBox第一个直接使用默认样式隐式应用ListBoxBaseStyleItemTemplate仅显示Name文本第二个使用Style{StaticResource ListBox.Small}紧凑变体ItemTemplate同样绑定Name。配合其代码后置ListBoxDemo.xaml.cs中的DataList数据集合你可以直接运行 Demo 观察默认样式与紧凑样式的尺寸、间距与选中态差异并以此为起点尝试ListBoxCustom及四种布局样式。小结HandyControl 的 ListBox 样式体系遵循清晰的BasedOn继承设计ListBoxBaseStyle作为不可直接使用的基座提供默认外观、滚动行为与选中态反馈ListBoxCustom在此基础上剥离容器装饰把数据显示完全交给用户的ItemTemplate四种布局变体则通过公共ItemsPanelTemplate一键切换 WrapPanel/StackPanel 的水平与垂直方向。配合ListBoxAttach.SelectedItems的双向绑定选中集合能力以及 Avalonia 分支的同构实现你可以快速构建从简单列表到复杂网格、标签云、气泡列表等多种形态的列表框界面。所有样式与模板均可在 Themes/Styles/ListBox.xaml 与 Themes/Styles/Base/ListBoxBaseStyle.xaml 中查阅并二次定制。赞分享UI组件桌面应用【免费下载链接】HandyControlContains some simple and commonly used WPF controls项目地址https://gitcode.com/gh_mirrors/ha/HandyControl点击查看免费下载相关推荐FAST 组件库 Listbox 类全解析从 FoundationListboxElement 到 fast-listbox 的继承体系与实战指南FAST 组件库 Listbox 类全解析从 FoundationListboxElement 到 fast listbox 的继承体系与实战指南 micr前端UI组件Win11Debloat免费给 Windows 10/11 瘦身5 分钟该做什么Win11Debloat免费给 Windows 10/11 瘦身5 分钟该做什么 新装的 Windows 11是不是装完就开始被用不上的预装应用、后台遥桌面应用CLI三步实现界面风格统一HandyControl样式继承全攻略三步实现界面风格统一HandyControl样式继承全攻略 你是否还在为WPF界面开发中重复编写相似样式而烦恼是否希望快速定制出符合产品风格的控件库本文将UI组件桌面应用上一篇Hackintool 终极指南一站式 macOS 系统优化与 EFI 配置工具下一篇3分钟掌握Rust HTML抓取神器easy-scraper终极教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表