WPF中UserControl的MergedDictionaries会每次实例化时都被解析吗?
WPF合并资源与转换器实例创建问题
初始问题
有一个定义了如下资源的WPF UserControl:
<UserControl.Resources > <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="LeftHeaderDataTemplates.xaml"/> <ResourceDictionary Source="RightHeaderDataTemplates.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources>
请问该合并资源会在每个UserControl实例创建时都被解析吗?性能分析器的应用时间线似乎显示是这样,但我不确定是否解读正确。
编辑补充
正如@Andy的回答所指出:是的,ResourceDictionary每次都会被解析并创建新实例。他提到引用转换器有更合适的方式,即让转换器实现MarkupExtension。
这引出了另一个问题:根据转换器的引用/实现方式,会创建多少个转换器实例?我做了相关测试,结果如下:
测试场景
使用一个被渲染4次的UserControl:
<UserControl> <UserControl.Resources> <converters1:TestConverter3 x:Key="TestConverter3"/> </UserControl.Resources> <StackPanel Background="Black"> <TextBlock Foreground="White" Text="{Binding Converter={StaticResource TestConverter1}}"></TextBlock> <TextBlock Foreground="White" Text="{Binding Converter={StaticResource TestConverter1}}"></TextBlock> <TextBlock Foreground="White" Text="{Binding Converter={converters1:TestConverter2}}"></TextBlock> <TextBlock Foreground="White" Text="{Binding Converter={converters1:TestConverter2}}"></TextBlock> <TextBlock Foreground="White" Text="{Binding Converter={StaticResource TestConverter3}}"></TextBlock> <TextBlock Foreground="White" Text="{Binding Converter={StaticResource TestConverter3}}"></TextBlock> </StackPanel> </UserControl>
- TestConverter1:定义在App.xaml中的全局共享静态资源
- TestConverter2:通过继承MarkupExtension实现
- 3种转换器各被4个UserControl实例使用2次
测试输出(控制台)
CREATING: TestConverter1 {HashCode: 51949120} CREATING: TestConverter2 {HashCode: 27832883} CREATING: TestConverter2 {HashCode: 8329199} CREATING: TestConverter3 {HashCode: 48129282} CREATING: TestConverter2 {HashCode: 12052844} CREATING: TestConverter2 {HashCode: 24470370} CREATING: TestConverter3 {HashCode: 24336447} CREATING: TestConverter2 {HashCode: 22270914} CREATING: TestConverter2 {HashCode: 23473221} CREATING: TestConverter3 {HashCode: 11043085} CREATING: TestConverter2 {HashCode: 50932452} CREATING: TestConverter2 {HashCode: 32788649} CREATING: TestConverter3 {HashCode: 49189852} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter2 {HashCode: 27832883} Convert : TestConverter2 {HashCode: 8329199} Convert : TestConverter3 {HashCode: 48129282} Convert : TestConverter3 {HashCode: 48129282} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter2 {HashCode: 12052844} Convert : TestConverter2 {HashCode: 24470370} Convert : TestConverter3 {HashCode: 24336447} Convert : TestConverter3 {HashCode: 24336447} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter2 {HashCode: 22270914} Convert : TestConverter2 {HashCode: 23473221} Convert : TestConverter3 {HashCode: 11043085} Convert : TestConverter3 {HashCode: 11043085} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter1 {HashCode: 51949120} Convert : TestConverter2 {HashCode: 50932452} Convert : TestConverter2 {HashCode: 32788649} Convert : TestConverter3 {HashCode: 49189852} Convert : TestConverter3 {HashCode: 49189852}
测试结果
- TestConverter1:作为全局静态资源,仅创建1次,所有实例共享
- TestConverter2:作为标记扩展使用,每次绑定引用都会创建新实例,共创建8次
- TestConverter3:作为UserControl内的静态资源,每个UserControl实例创建时都会生成新实例,共创建4次
注意事项
转换器本身应设计为轻量级,所以通常不会引发内存或GC问题,但仍需留意,尤其是使用简洁的MarkupExtension语法时,会产生更多实例。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

