当前位置: 首页 > news >正文

HandyControl中Button图标展示多色路径

多色路径需求

HandyControl中支持图标和图标+文本显示,图标主要是矢量路径也就是对应着svg的数据格式。而对于多图形GeometryGroup虽然能够多路径组合,但是仅支持单色,并不支持多色,日常使用如下:

原始svg内容

<svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"fill="none"version="1.1"width="16"height="16"viewBox="0 0 16 16"><defs><clipPathid="master_svg0_103_3747"><rectx="0"y="0"width="16"height="16"rx="0"/></clipPath></defs><gclip-path="url(#master_svg0_103_3747)"><pathd="M10.832551042773437,1.59998178671875L2.8058843427734375,9.84051518671875C2.7448177427734377,9.90398218671875,2.7320177427734373,9.91651538671875,2.7082843427734375,9.97331528671875L2.6714843427734376,10.06851478671875L2.616551142773438,10.23118018671875L2.4133510427734377,10.86424728671875L2.0098843527734376,12.14691338671875L1.3573510647734375,14.24211338671875C1.2330844397734375,14.64291338671875,1.5976177427734375,15.01811338671875,1.9952178027734375,14.91758038671875L2.6701511427734372,14.69784638671875L5.239218042773437,13.85011338671875L5.939217542773438,13.61357938671875L6.079217442773437,13.56424738671875C6.099751042773438,13.55651238671875,6.116550942773437,13.55011238671875,6.131484042773438,13.54398038671875L6.192017542773438,13.51891438671875C6.248017742773437,13.49464738671875,6.260550942773437,13.48158038671875,6.321084042773437,13.42184638671875L14.353082342773437,5.17464708671875C14.756508342773438,4.760472786718751,14.756508342773438,4.10028838671875,14.353082342773437,3.68611358671875L12.341351342773438,1.61998176671875C11.930258342773438,1.19789707671875,11.254809342773438,1.18906152671875,10.832818042773438,1.60024842671875L10.832551042773437,1.59998178671875ZM3.6506848427734373,10.50264838671875L11.576818342773437,2.3642483867187503L13.589085342773437,4.430381786718749L5.645885442773437,12.58611438671875L5.209618542773438,12.73544738671875L3.7389519427734377,13.22344738671875L2.6826853427734374,13.57118138671875L3.3749520427734376,11.36104638671875L3.6157517427734374,10.60771468671875L3.6504187427734376,10.50238128671875L3.6506848427734373,10.50264838671875Z"fill="#FFFFFF"fill-opacity="1"style="mix-blend-mode:passthrough"/><pathd="M9.0365343134375,3.750135658203125C9.2321443534375,3.554630756203125,9.5447464034375,3.541084766203125,9.7565345734375,3.718935728203125L9.7906675334375,3.750135658203125L12.190666923437501,6.150135558203125C12.3937263234375,6.3518721582031255,12.4013290234375,6.677928958203125,12.2078933234375,6.888910558203126C12.0144577234375,7.099892358203125,11.688966723437499,7.120558758203125,11.470400823437501,6.935735658203125L11.4365339234375,6.904535558203126L9.0365343134375,4.5045356782031245C8.8281536104375,4.296238418203125,8.8281536104375,3.958432908203125,9.0365343134375,3.750135658203125Z"fill="#FFFFFF"fill-opacity="1"style="mix-blend-mode:passthrough"/><pathd="M13.599989443554687,13.333343505859375L13.599989443554687,13.866677345859374C13.599990343554687,14.161229195859375,13.361208443554688,14.400011205859375,13.066656543554688,14.400010105859375L8.266655443554688,14.400010105859375C7.9721040735546875,14.400011205859375,7.7333226203918475,14.161229195859375,7.7333221435546875,13.866677345859374L7.7333221435546875,13.333343505859375L13.599989443554687,13.333343505859375Z"fill="#00B386"fill-opacity="1"style="mix-blend-mode:passthrough"/></g></svg>

Geometry转换

实际转换为GeometryGroup后如下:

<GeometryGroupx:Key="InputGeometry"><Geometry>M10.832551042773437,1.59998178671875L2.8058843427734375,9.84051518671875C2.7448177427734377,9.90398218671875,2.7320177427734373,9.91651538671875,2.7082843427734375,9.97331528671875L2.6714843427734376,10.06851478671875L2.616551142773438,10.23118018671875L2.4133510427734377,10.86424728671875L2.0098843527734376,12.14691338671875L1.3573510647734375,14.24211338671875C1.2330844397734375,14.64291338671875,1.5976177427734375,15.01811338671875,1.9952178027734375,14.91758038671875L2.6701511427734372,14.69784638671875L5.239218042773437,13.85011338671875L5.939217542773438,13.61357938671875L6.079217442773437,13.56424738671875C6.099751042773438,13.55651238671875,6.116550942773437,13.55011238671875,6.131484042773438,13.54398038671875L6.192017542773438,13.51891438671875C6.248017742773437,13.49464738671875,6.260550942773437,13.48158038671875,6.321084042773437,13.42184638671875L14.353082342773437,5.17464708671875C14.756508342773438,4.760472786718751,14.756508342773438,4.10028838671875,14.353082342773437,3.68611358671875L12.341351342773438,1.61998176671875C11.930258342773438,1.19789707671875,11.254809342773438,1.18906152671875,10.832818042773438,1.60024842671875L10.832551042773437,1.59998178671875ZM3.6506848427734373,10.50264838671875L11.576818342773437,2.3642483867187503L13.589085342773437,4.430381786718749L5.645885442773437,12.58611438671875L5.209618542773438,12.73544738671875L3.7389519427734377,13.22344738671875L2.6826853427734374,13.57118138671875L3.3749520427734376,11.36104638671875L3.6157517427734374,10.60771468671875L3.6504187427734376,10.50238128671875L3.6506848427734373,10.50264838671875Z</Geometry><Geometry>M9.0365343134375,3.750135658203125C9.2321443534375,3.554630756203125,9.5447464034375,3.541084766203125,9.7565345734375,3.718935728203125L9.7906675334375,3.750135658203125L12.190666923437501,6.150135558203125C12.3937263234375,6.3518721582031255,12.4013290234375,6.677928958203125,12.2078933234375,6.888910558203126C12.0144577234375,7.099892358203125,11.688966723437499,7.120558758203125,11.470400823437501,6.935735658203125L11.4365339234375,6.904535558203126L9.0365343134375,4.5045356782031245C8.8281536104375,4.296238418203125,8.8281536104375,3.958432908203125,9.0365343134375,3.750135658203125Z</Geometry><Geometry>M13.599989443554687,13.333343505859375L13.599989443554687,13.866677345859374C13.599990343554687,14.161229195859375,13.361208443554688,14.400011205859375,13.066656543554688,14.400010105859375L8.266655443554688,14.400010105859375C7.9721040735546875,14.400011205859375,7.7333226203918475,14.161229195859375,7.7333221435546875,13.866677345859374L7.7333221435546875,13.333343505859375L13.599989443554687,13.333343505859375Z</Geometry></GeometryGroup>

Xaml 页面使用

Button需要声明全局引入引入HandyControl库并引入命名空间:

<hc:Windowx:Class="blog_hc_button.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:blog_hc_button"xmlns:hc="https://handyorg.github.io/handycontrol"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><UniformGrid><ButtonWidth="Auto"Padding="12,6"Height="36"FontSize="14"Content="测试样例"hc:IconElement.Geometry="{StaticResource InputGeometry}"hc:IconElement.Width="24"hc:IconElement.Height="20"></Button></UniformGrid></hc:Window>

运行效果如下,字体色即为文本色:

源码细节分析

查看Button样式

通过查看HandyControlButtonBaseStyle样式代码,去除无关部分,不能看出按钮的字体颜色即为路径的填充色<Path ... Fill="{TemplateBinding Foreground}"/>

<Stylex:Key="ButtonBaseStyle"BasedOn="{StaticResource ButtonBaseBaseStyle}"TargetType="Button"><Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <hc:SimplePanel> <Border Background="{TemplateBinding Background}"CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"/> <Border BorderThickness="{TemplateBinding BorderThickness}"BorderBrush="{TemplateBinding BorderBrush}"CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"> <StackPanel Orientation="Horizontal"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}"Margin="{TemplateBinding Padding}"> <!--路径图标--> <Pathx:Name="PathMain"Width="{TemplateBinding hc:IconElement.Width}"Height="{TemplateBinding hc:IconElement.Height}"Fill="{TemplateBinding Foreground}"SnapsToDevicePixels="True"Stretch="Uniform"Data="{TemplateBinding hc:IconElement.Geometry}"/> <!--文本内容--> <ContentPresenterx:Name="ContentPresenterMain"RecognizesAccessKey="True"VerticalAlignment="Center"Margin="6,0,0,0"SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </StackPanel> </Border> </hc:SimplePanel> </ControlTemplate> </Setter.Value> </Setter></Style>

查看DrawingBrush

如果需要多色,就需要将ButtonForegroundIcon的填充色进行分离,进而实现两者的独立配置,虽然GeometryGroup无法实现多色,但是Fill本身可以支持DrawingBrush,可以通过单独设置DrawingBrush实现图形填充色,使用了DrawingGroup以及GeometryDrawing,如果不熟悉可以查阅微软文档。

<DrawingBrushx:Key="Input2GeometryBrush"><DrawingBrush.Drawing><DrawingGroup><GeometryDrawingBrush="{DynamicResource PrimaryTextBrush}"Pen="{x:Null}"Geometry="M10.832551042773437,1.59998178671875L2.8058843427734375,9.84051518671875C2.7448177427734377,9.90398218671875,2.7320177427734373,9.91651538671875,2.7082843427734375,9.97331528671875L2.6714843427734376,10.06851478671875L2.616551142773438,10.23118018671875L2.4133510427734377,10.86424728671875L2.0098843527734376,12.14691338671875L1.3573510647734375,14.24211338671875C1.2330844397734375,14.64291338671875,1.5976177427734375,15.01811338671875,1.9952178027734375,14.91758038671875L2.6701511427734372,14.69784638671875L5.239218042773437,13.85011338671875L5.939217542773438,13.61357938671875L6.079217442773437,13.56424738671875C6.099751042773438,13.55651238671875,6.116550942773437,13.55011238671875,6.131484042773438,13.54398038671875L6.192017542773438,13.51891438671875C6.248017742773437,13.49464738671875,6.260550942773437,13.48158038671875,6.321084042773437,13.42184638671875L14.353082342773437,5.17464708671875C14.756508342773438,4.760472786718751,14.756508342773438,4.10028838671875,14.353082342773437,3.68611358671875L12.341351342773438,1.61998176671875C11.930258342773438,1.19789707671875,11.254809342773438,1.18906152671875,10.832818042773438,1.60024842671875L10.832551042773437,1.59998178671875ZM3.6506848427734373,10.50264838671875L11.576818342773437,2.3642483867187503L13.589085342773437,4.430381786718749L5.645885442773437,12.58611438671875L5.209618542773438,12.73544738671875L3.7389519427734377,13.22344738671875L2.6826853427734374,13.57118138671875L3.3749520427734376,11.36104638671875L3.6157517427734374,10.60771468671875L3.6504187427734376,10.50238128671875L3.6506848427734373,10.50264838671875Z"/><GeometryDrawingBrush="{DynamicResource PrimaryTextBrush}"Pen="{x:Null}"Geometry="M9.0365343134375,3.750135658203125C9.2321443534375,3.554630756203125,9.5447464034375,3.541084766203125,9.7565345734375,3.718935728203125L9.7906675334375,3.750135658203125L12.190666923437501,6.150135558203125C12.3937263234375,6.3518721582031255,12.4013290234375,6.677928958203125,12.2078933234375,6.888910558203126C12.0144577234375,7.099892358203125,11.688966723437499,7.120558758203125,11.470400823437501,6.935735658203125L11.4365339234375,6.904535558203126L9.0365343134375,4.5045356782031245C8.8281536104375,4.296238418203125,8.8281536104375,3.958432908203125,9.0365343134375,3.750135658203125Z"/><GeometryDrawingBrush="{DynamicResource PrimaryBrush}"Pen="{x:Null}"Geometry="M13.599989443554687,13.333343505859375L13.599989443554687,13.866677345859374C13.599990343554687,14.161229195859375,13.361208443554688,14.400011205859375,13.066656543554688,14.400010105859375L8.266655443554688,14.400010105859375C7.9721040735546875,14.400011205859375,7.7333226203918475,14.161229195859375,7.7333221435546875,13.866677345859374L7.7333221435546875,13.333343505859375L13.599989443554687,13.333343505859375Z"/></DrawingGroup></DrawingBrush.Drawing></DrawingBrush>

逻辑代码调整

创建附加属性

那又该如何在Button控件中使用?实际可以参考HandyControl原有自带的附加属性IconElement相关属性。本地构建一个IconElement类增加一个Brush类型的附加属性IconElement.Foreground

usingSystem.Windows;usingSystem.Windows.Media;namespaceblog_hc_button{publicclassIconElement{publicstaticBrushGetForeground(DependencyObjectobj){return(Brush)obj.GetValue(ForegroundProperty);}publicstaticvoidSetForeground(DependencyObjectobj,Brushvalue){obj.SetValue(ForegroundProperty,value);}publicstaticreadonlyDependencyPropertyForegroundProperty=DependencyProperty.RegisterAttached("Foreground",typeof(Brush),typeof(IconElement),newPropertyMetadata(Brushes.Transparent));}}

需要重写原有ButtonBaseStyle样式,添加IconElement.Foreground这个附加属性,首先添加本地命名空间声明。

xmlns:local="clr-namespace:blog_hc_button"

重写Button样式

进行Button样式覆写,进而能够在控件使用时传入附加属性决定图标的颜色。

<hc:Windowx:Class="blog_hc_button.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:blog_hc_button"xmlns:hc="https://handyorg.github.io/handycontrol"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><hc:Window.Resources><Stylex:Key="ButtonBaseStyleX"BasedOn="{StaticResource ButtonBaseBaseStyle}"TargetType="Button"><Setter Property="BorderThickness"Value="1"/> <Setter Property="Background"Value="{DynamicResource RegionBrush}"/> <Setter Property="hc:BorderElement.CornerRadius"Value="{StaticResource DefaultCornerRadius}"/> <!--给local:IconElement.Foreground设置一个默认颜色--> <Setter Property="local:IconElement.Foreground"Value="{DynamicResource PrimaryTextBrush}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <hc:SimplePanel> <Border Background="{TemplateBinding Background}"CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"/> <Border BorderThickness="{TemplateBinding BorderThickness}"BorderBrush="{TemplateBinding BorderBrush}"CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"> <StackPanel Orientation="Horizontal"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}"Margin="{TemplateBinding Padding}"> <!--路径图标,设置local:IconElement.Foreground为Path的填充色--> <Pathx:Name="PathMain"Width="{TemplateBinding hc:IconElement.Width}"Height="{TemplateBinding hc:IconElement.Height}"Fill="{TemplateBinding local:IconElement.Foreground}"SnapsToDevicePixels="True"Stretch="Uniform"Data="{TemplateBinding hc:IconElement.Geometry}"/> <ContentPresenterx:Name="ContentPresenterMain"RecognizesAccessKey="True"VerticalAlignment="Center"Margin="6,0,0,0"SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </StackPanel> </Border> </hc:SimplePanel> <ControlTemplate.Triggers> <Trigger Property="Content"Value="{x:Null}"> <Setter Property="Visibility"Value="Collapsed"TargetName="ContentPresenterMain"/> </Trigger> <Trigger Property="hc:IconElement.Geometry"Value="{x:Null}"> <Setter Property="Visibility"Value="Collapsed"TargetName="PathMain"/> <Setter Property="Margin"Value="0"TargetName="ContentPresenterMain"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver"Value="True"> <Setter Property="Opacity"Value=".9"/> </Trigger> <Trigger Property="IsPressed"Value="True"> <Setter Property="Opacity"Value=".6"/> </Trigger> <Trigger Property="IsEnabled"Value="False"> <Setter Property="Opacity"Value="0.4"/> </Trigger> </Style.Triggers></Style></hc:Window.Resources></hc:Window>

其中样式中设置一个默认颜色。

<!--给local:IconElement.Foreground设置一个默认颜色--><SetterProperty="local:IconElement.Foreground"Value="{DynamicResource PrimaryTextBrush}"/>

页面使用附加属性

在案例项目中引入,并设置local:IconElement.ForegroundInput2GeometryBrush

<ButtonStyle="{StaticResource ButtonBaseStyleX}"Width="Auto"Padding="12,6"Height="36"FontSize="14"Content="多色样例"hc:IconElement.Geometry="{StaticResource InputGeometry}"local:IconElement.Foreground="{StaticResource Input2GeometryBrush}"hc:IconElement.Width="24"hc:IconElement.Height="20"></Button>

比对效果如下:

当然,不这样弄行不行?也可以通过三方开源nugetSharpVectors直接使用svg文件,减少重复Brush对象的创建。

总结

以上就是在HandyControl库中,不引入其他三方库时,实现多彩路径svg按钮的解决方案,这里主要是对GeometryGroupStyle覆写、DrawingBrushDrawingGroupDrawingGeometry以及附加属性的整合应用,内容有点绕,目的也就是为了多彩路径。

http://www.cnnetsun.cn/news/1380314.html

相关文章:

  • STM32F103CBT6通过I2C接口高效读取LC709203F锂电池电量数据的实战指南
  • 告别Tkinter!用pywebview+HTML5打造Python桌面应用的3种实战姿势
  • 透视投影实战:用Python+OpenCV实现3D点云到2D图像的转换(附完整代码)
  • Ubuntu 22.04 上如何用 vLLM 加速 Qwen3 32B 模型推理(含 GPU 配置优化)
  • 彻底搞懂 UDP 网络编程:单播、广播与组播的原理与实战避坑指南
  • Windows下用scrcpy实现手机投屏:如何单独投声音或画面(附完整脚本)
  • 3个技术突破让百度网盘下载速度提升10倍:资源获取加速工具全攻略
  • AudioSeal快速上手:AudioSeal Web界面多语言切换(中/英/日/韩)配置方法
  • 深入AUTOSAR E2E状态机:Profile1的OK、ERROR、SYNC状态到底在说什么?一个例子讲清楚
  • 永磁同步电机无位置传感器转子初始位置检测探索
  • Qwen3-4B Instruct-2507效果展示:圆角UI+动态光标交互体验实录
  • 机械臂轨迹规划避坑指南:为什么五次多项式比三次更好用?
  • 告别PuTTY!VSCode+Remote-SSH打造可视化Ubuntu远程开发环境(2023最新版)
  • AI编程革命:LiuJuan20260223Zimage代码生成实践
  • Z-Image-Turbo_Sugar脸部Lora模型生成视频封面:结合AE制作动态片段片头
  • TensorFlow-v2.15快速入门:5行代码获取TensorFlow中GPU设备信息
  • 豆包Doubao-Seedream-4.5 API生图实战:从代码到创意,解锁文生图、图生图与多图融合的深度应用
  • 告别手动改版本号!用MSBuild脚本让C#类库每次编译自动+1(附完整PowerShell脚本)
  • 虚拟环境名消失?用这招让Pycharm Terminal秒识别你的Python环境(Win/Mac双平台)
  • TTL与RS232/USB转换器的核心应用与选型指南
  • Stable Yogi 模型运维指南:生产环境高可用部署与监控
  • 基于Vue.js与Granite TimeSeries FlowState R1打造交互式预测分析仪表盘
  • 树莓派5 GPU加速实战:从OpenCL到TensorFlow Lite的完整配置指南
  • 颠覆传统Unreal资产编辑:UAssetGUI实现300%效率提升的5大核心方案
  • Alluxio与OCI深度集成:解锁AI训练新范式,从数据瓶颈到TB级吞吐的实战跃迁
  • Rust reqwest库实战:5个高并发场景下的性能优化技巧(附代码)
  • CANoe CAPL实战:LIN调度表动态切换与IG控制的深度解析
  • 半导体材料中的晶体结构解析:从NaCl到金刚石,工程师必备知识
  • Selenium 与 Playwright:浏览器自动化工具的深度对比
  • 3步突破:解锁VMware macOS虚拟化的开源方案