为什么WPF中绑定到元素自身Tag属性的绑定无法正常生效?
问题原因
- 核心是依赖属性的绑定监听逻辑和ContentPresenter的自带行为共同导致的:
- 初始版本可以正常运行,是因为你直接把
MultiBinding赋值给了ContentPresenter.Content属性,WPF会直接解析这个绑定表达式,监听所有绑定源的变更,每次变更都会触发WhateverConverter执行,返回的NotifyTask对象会直接作为Content的有效值,后续NotifyTask异步执行的状态变更可以被Content关联的显示模板正常监听。 - 改完之后绑定失效的原因有两个:
- 你给Content设置的
{Binding Path=Tag, RelativeSource={RelativeSource Self}}绑定,只会监听Tag属性本身的引用变更。当Tag上的MultiBinding第一次触发Converter返回NotifyTask实例后,Tag的引用不会再发生变化,后续NotifyTask异步执行完成后的内部属性变更,不会触发Content的绑定更新,符合你说的两步转换不生效的情况。 ContentPresenter有默认的上下文适配逻辑:当Content属性被赋值后,ContentPresenter自身的DataContext会自动指向Content的值,此时Tag上的MultiBinding如果依赖当前DataContext作为数据源,会出现上下文循环错位,导致绑定无法正常拿到最新的数据源值。
- 你给Content设置的
- 初始版本可以正常运行,是因为你直接把
解决建议
如果确实需要通过Tag做中间值存储,可以调整Content的绑定监听对象,同时固定ContentPresenter的DataContext避免上下文错位:
<ContentPresenter Content="{Binding Path=Tag.Result, RelativeSource={RelativeSource Self}}" DataContext="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}"> <ContentPresenter.Tag> <MultiBinding Converter="{StaticResource WhateverConverter}"> <Binding/> <Binding Path="DummyObject"/> </MultiBinding> </ContentPresenter.Tag> </ContentPresenter>
如果没有特殊的中间存储需求,直接用初始版本的写法即可,性能和稳定性都更好。
内容的提问来源于stack exchange,提问作者gyrojeff
相关产品推荐
相关产品推荐

