712:Atta. cursor;ToggleButton

1

<Buttonatta:AttacherContainer.Kind="WindowClose"Cursor="Hand"Style="{StaticResource menuIconButton}"/>

整体功能

这是程序窗口关闭按钮,点击执行ViewModel里的ShutDownCommand实现软件退出;挂载第三方附加属性做窗口关闭专用样式区分,鼠标悬浮显示手型,复用全局图标按钮模板。

2.atta:AttacherContainer.Kind="WindowClose"

  1. atta:项目中引入的附加属性命名空间(自制工具类 / HandyControl 配套Attacher工具);
  2. AttacherContainer:附加属性静态类;
  3. Kind="WiClose":标记该按钮用途为「窗口关闭」;
  • 作用:在全局menuIconButton样式/Behavior中识别类型,自动加载关闭图标、 hover红色高亮、专属缩放动画,不用单独写一套样式。
    底层原理:附加属性AttachedProperty,给Button扩展额外业务标记,纯XAML无后台代码实现差异化UI。

4.Cursor="Hand"

鼠标移入按钮时,光标变为手型,提示可点击交互,提升界面操作辨识度。

5.Style="{StaticResource menuIconButton}"

复用全局静态资源样式menuIconButton,:

  • 内置ControlTemplate+ContentPresenter承载关闭图标;
  • 自带IsMouseOver悬浮放大动画(0.1s移入放大1.05倍、0.15s回弹);
  • 统一标题栏最小化/最大化/关闭按钮尺寸、圆角、缩放交互,界面风格统一。

完整配套关联链路

  1. 样式menuIconButton内部通过atta:AttacherContainer.Kind判断按钮类型:
    • WindowClose:加载×关闭图标,hover背景变红;
    • 配套你之前的Viewbox+Polygon三角箭头逻辑,同类图标统一管理;
  2. 点击触发ShutDownCommand,完全符合MVVM分层,界面与设备退出业务解耦;
  3. 标题栏同系列按钮(最小化、还原)仅修改KindCommand,复用同一套Style,减少重复XAML代码。

典型ViewModel命令示例

// 主窗口ViewModelpublicICommandShutDownCommand{get;}publicMainViewModel(){ShutDownCommand=newRelayCommand(ExecuteShutdown);}privatevoidExecuteShutdown(){// 1. 弹窗确认是否退出varconfirm=MessageBox.Show("确定要关闭","退出提示",MessageBoxButton.YesNo);if(confirm!=MessageBoxResult.Yes)return;// 2. 停止服务、释放硬件资源_deviceService.StopScan();// 3. 保存MachineConfig设备配置_configService.SaveMachineConfig();// 4. 关闭应用程序Application.Current.Shutdown();}

踩坑注意点

  1. atta命名空间缺失:页面顶部缺少xmlns:atta="clr-namespace:项目命名空间.Utils",XAML直接报错;
  2. ShutDownCommand无响应:ViewModel未实现INotifyPropertyChanged、DataContext未正确绑定到窗口;
  3. 附加属性不生效:menuIconButton样式内未读取AttacherContainer.Kind做图标切换;
  4. 按钮无图标:模板内ContentPresenter依赖Kind加载对应矢量图形,标记写错会空白。

2

<Button.Content><StackPanel><m:MaterialIconKind="Group"><m:MaterialIcon.Effect><DropShadowEffectBlurRadius="1"ShadowDepth="1"Color="#333333"/></m:MaterialIcon.Effect></m:MaterialIcon>

整体作用

按钮内部内容使用垂直StackPanel承载大尺寸Group分组矢量图标,图标带白色半透填充+灰色投影阴影

分层拆解

1.<Button.Content>

专门用来定义按钮内部自定义复合内容;
如果不写这个标签,按钮只能填简单文字,内部需要图标+文字组合时,必须用Button.Content包裹布局容器(StackPanel/Grid)。

2. 外层<StackPanel>

布局容器,默认垂直排列(Orientation="Vertical");
当前只放了一个图标,后续可以追加<TextBlock>写按钮文字,实现「图标在上、文字在下」的标准功能按钮布局:

<StackPanel><m:MaterialIcon.../><TextBlockText="批量分组检测"Foreground="White"HorizontalAlignment="Center"/></StackPanel>

3.<m:MaterialIcon>核心图标控件

这是Material.Icons.Wpf第三方图标库控件(你项目上位机统一用的矢量图标组件)

<m:MaterialIconForeground="#e6ffffff"Kind="Group">
  • Width="70" Height="70":图标固定70×70大尺寸,首页功能大按钮规格;
  • Foreground="#e6ffffff":填充颜色,e6是透明度,后面ffffff白色 →半透白色图标
  • Kind="Group":指定图标类型,显示「分组/群组」矢量图形,用于批量BGA、多板分组检测功能入口。

4. 图标阴影特效DropShadowEffect

<m:MaterialIcon.Effect><DropShadowEffectBlurRadius="1"ShadowDepth="1"Color="#333333"/></m:MaterialIcon.Effect>

给图标增加细微灰色投影,提升悬浮立体感:

  • BlurRadius="1":阴影模糊程度1,不夸张,工业界面简洁风格;
  • ShadowDepth="1":阴影偏移距离1像素;
  • Color="#333333":深灰色阴影,不会抢白色图标的视觉重点。

完整可扩展成品(图标+文字标准按钮)

<ButtonMargin="10"Command="{Binding GroupScanCommand}"Style="{StaticResource menuIconButton}"><Button.Content><StackPanel><m:MaterialIconWidth="70"Height="70"Foreground="#e6ffffff"Kind="Group"><m:MaterialIcon.Effect><DropShadowEffectBlurRadius="1"ShadowDepth="1"Color="#333333"/></m:MaterialIcon.Effect></m:MaterialIcon><TextBlockText="分组批量扫描"Foreground="White"FontSize="14"Margin="0,8,0,0"HorizontalAlignment="Center"/></StackPanel></Button.Content></Button>

结合你之前知识点联动说明

  1. 按钮套用menuIconButton样式,自带ControlTemplateScaleTransform悬浮放大动画;
  2. 模板内部ContentPresenter会自动渲染这里的StackPanel图标内容;
  3. 鼠标移入时整套图标+文字同步缩放,交互统一;

常见踩坑点

  1. 图标空白/不显示:缺少NuGet包Material.Icons.Wpf、页面未引入命名空间xmlns:m="clr-namespace:Material.Icons.Wpf;assembly=Material.Icons.Wpf"
  2. 透明色异常:Foreground十六进制格式为AARRGGBB,透明度在前,写反会变成纯黑/纯白;
  3. 阴影卡顿:页面大量图标同时加DropShadowEffect会增加GPU消耗,首页少量大按钮使用无压力,表格小图标建议移除特效;
  4. 图标拉伸变形:必须同时设置Width+Height相等,保证矢量图标等比例不变形。

3

ToggleButton

Visibility="{Binding ElementName=ModeButton, Path=IsMouseOver, Converter={StaticResource Boolean2VisiblityConverter}}"

绑定三要素拆解

ElementName=ModeButton
指定绑定目标是外层命名为ModeButton的ToggleButton;
Path=IsMouseOver
读取按钮自带属性:鼠标是否悬浮在按钮范围内(true/false);
Boolean2VisiblityConverter 布尔转可见性转换器
转换逻辑(标准实现):
输入 true(鼠标悬浮按钮)→ 返回 Visibility.Visible → 画布显示,弹出菜单;
输入 false(鼠标离开按钮)→ 返回 Visibility.Collapsed → 画布完全隐藏,不占用布局空间。