WPF使用Style设置Button内容时仅最后一个图标显示异常问题
问题原因
这不是WPF的Bug,是你的XAML写法不符合WPF的视觉元素规则:
- WPF中每个UI元素实例在同一时间只能属于一个父级视觉节点。你直接把
<ContentControl>写在btIcon样式的ContentSetter值里,相当于全局只创建了一个ContentControl实例,所有应用该样式的Button都会争抢这个实例作为内容,最终它只会被挂载到最后一个应用样式的Button上,因此只有最后一个按钮显示图标。
修复方案
最简单的修复方式是将样式中的Content赋值改为ContentTemplate赋值,用数据模板生成每个按钮独立的内容实例,修改后的样式代码如下:
<Style TargetType="Button" x:Key="btIcon"> <Setter Property="Background" Value="Transparent" /> <Setter Property="BorderThickness" Value="0" /> <Setter Property="Margin" Value="3" /> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <ContentControl Style="{StaticResource ctlIcon}" Template="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Tag}"/> </DataTemplate> </Setter.Value> </Setter> </Style>
修改后原有调用代码无需改动,所有按钮都能正常显示图标。
更优的图标按钮实现方案
你当前用ControlTemplate存SVG转的矢量图标是可行的,但还有两种更轻量、更易维护的实现方式:
- 用DrawingImage存储图标
将SVG转为DrawingImage资源,比ControlTemplate更轻量,无需构建额外的Control视觉树,使用时直接赋值给Image的Source属性即可:
<DrawingImage x:Key="icSend"> <DrawingImage.Drawing> <DrawingGroup> <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" /> <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M0,2.1346L1.463,7.5006 0,12.8656 0,14.4666 16,8.1806 16,6.8196 0,0.533600000000001z" /> <GeometryDrawing Brush="#FF424242" Geometry="F1M3.4004,8L10.9924,8 2.4894,11.341z M2.4894,3.659L10.9924,7 3.4004,7z M15.0004,7.5L1.0004,2 2.5004,7.5 1.0004,13z" /> </DrawingGroup> </DrawingImage.Drawing> </DrawingImage>
- 自定义附加属性替代Tag
Tag是无类型约束的通用属性,容易和其他逻辑冲突,你可以自定义一个IconTemplate附加属性专门用来传递图标模板,类型安全且代码可读性更高。
内容的提问来源于stack exchange,提问作者ish1313
相关产品推荐
相关产品推荐

