WPF向UserControl传递对象时依赖属性SetValue未触发问题
问题原因
- 依赖属性的调试认知错误:WPF运行时给依赖属性赋值走的是底层
SetValue直接调用,完全不会经过你写的CLR属性封装的set块,你在ListOp1的set方法上打断点不触发是正常机制,不代表属性没被赋值。真正能捕获依赖属性值变更的位置,是你注册依赖属性时传入的静态ListOp1PropertyChanged回调,要调试就去这里打断点。 - 自定义控件的经典DataContext错误:你在
UserControlListOperations构造函数里写了this.DataContext = this;,直接破坏了绑定上下文的继承链。- 你写死的
MyString="toto"是直接赋值字符串字面量,不依赖DataContext,所以能正常显示。 - 主窗口里给
ListOp1写的{Binding Path = ListOpAss}默认基于当前DataContext找属性,你把UserControl的DataContext强行改成了控件自身,绑定就会去UserControl类里找ListOpAss属性,自然找不到值,属性当然不会更新。
- 你写死的
- 主窗口调用时漏传了
Contract属性的绑定,你现在XAML里只绑了ListOp1和MyString,Contract根本没传值,内部绑定拿不到数据。
修复方案
- 第一步:直接删除UserControl构造函数里的
this.DataContext = this;,自定义UserControl永远不要在内部强行给自己赋值DataContext,否则外层所有传进来的绑定都会找错上下文。 - 第二步:修改UserControl内部XAML的所有绑定,显式指定绑定源为控件自身,不要依赖继承的DataContext。示例修改:
<!-- 头部已声明local命名空间可直接使用 --> <Label Content="{Binding MyString, RelativeSource={RelativeSource AncestorType=local:UserControlListOperations}}"/> <Rectangle Grid.Row="1" Name="AFF_Track" Height="12" Stroke="black" StrokeThickness="1" Tag="{Binding ID, RelativeSource={RelativeSource AncestorType=local:UserControlListOperations}}"> <Rectangle.Fill> <MultiBinding Converter="{StaticResource :listOpToLinearGradientBrush}"> <Binding Path="ListOp1" RelativeSource="{RelativeSource AncestorType=local:UserControlListOperations}"/> <Binding Path="Contract" RelativeSource="{RelativeSource AncestorType=local:UserControlListOperations}"/> <Binding Source="0"/> </MultiBinding> </Rectangle.Fill> </Rectangle> <!-- AFF_Track2的绑定按相同规则修改即可 -->
- 第三步:清理冗余代码:
- 删掉所有依赖属性CLR get/set块里的
NotifyPropertyChanged调用,依赖属性本身内置了属性变更通知,不需要手动实现INotifyPropertyChanged触发,写了完全多余。 - 删掉没用到的
propertyMetaData、TextProperty_PropertyChanged这类冗余定义,避免干扰逻辑。
- 删掉所有依赖属性CLR get/set块里的
- 第四步:补全主窗口里UserControl的绑定,把Contract属性也绑上,DataTemplate里当前上下文就是每行的Contract数据对象,直接写:
<views:UserControlListOperations ListOp1="{Binding Path=ListOpAss}" Contract="{Binding}" MyString="toto"/>
对照列正常运行的原因
第二个GridViewColumn里的Rectangle没有修改自身DataContext,会自动继承DataTemplate里传入的行级数据对象作为DataContext,所以{Binding Path=ListOpAss}能正确找到对应属性,自然运行正常。
内容的提问来源于stack exchange,提问作者Siegfried.V
相关产品推荐
相关产品推荐

