WPF ControlTemplate触发器使用StaticResource/x:Static时值为NULL
问题现象
WPF开发中存在可稳定复现的异常:在ControlTemplate.Triggers的Setter中配合转换器使用StaticResource或x:Static标记扩展时,转换器的value入参始终为NULL;完全相同的写法在非触发器的普通控件属性赋值场景下可正常运行。
已验证复现环境:.NET 4.5、.NET 4.7.2、.NET 4.8,Visual Studio 2019 16.11.15
场景对比验证
正常运行场景
在普通StackPanel布局中,分别使用DynamicResource、x:Static、带转换器的StaticResource/x:Static绑定方式引用自定义加减号图标资源,所有写法均可正常渲染,转换器可正确接收到资源对象入参,无异常。
异常场景表现
在TreeViewItem、Button的自定义ControlTemplate触发器中,使用{Binding Source={StaticResource 资源名}, Converter={StaticResource 转换器}}写法设置控件Content属性时,存在时间相关的异常表现:
- 程序启动后立即触发对应触发器:可正常获取资源值、完成转换渲染
- 等待数秒后再触发触发器:转换器接收到的
value为NULL,对应图标消失 - 移除转换器后,直接通过Binding包装
StaticResource赋值的写法仍然存在该问题,说明异常与转换器逻辑无关
问题根因
Binding机制设计用于绑定可动态变更、可触发PropertyChanged通知的值,并不适用于静态对象引用的赋值场景,错误使用Binding包装StaticResource实现静态资源引用是问题产生的核心原因。
修复方案
避免使用Binding包装静态资源,直接在Setter中通过标记扩展引用资源即可,值转换逻辑直接在标记扩展上配置转换器:
<!-- 错误写法(会触发上述Null异常) --> <Setter Property="Content" Value="{Binding Source={StaticResource MinusIcon}, Converter={StaticResource IconToImageConverter}}"/> <!-- 正确写法 --> <Setter Property="Content" Value="{StaticResource MinusIcon, Converter={StaticResource IconToImageConverter}}"/>
引用x:Static静态成员时逻辑一致:
<Setter Property="Content" Value="{x:Static local:IconResources.PlusIcon, Converter={StaticResource IconToImageConverter}}"/>
内容的提问来源于stack exchange,提问作者Nawed Nabi Zada

