依赖属性收到xaml更改时的回调

当我在运行时设置IsClosed的值时, OnIsClosedChanged()被称为罚款。 但是,Designer会设置属性的值,但不会调用OnIsClosedChanged()

 public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)); public bool IsClosed { get { return (bool)this.GetValue(IsClosedProperty); } set { if ((bool)this.GetValue(IsClosedProperty) == value) return; this.SetValue(IsClosedProperty, value); OnIsClosedChanged(); } } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); } 

显然,Designer不会修改IsClosedProperty ,只有IsClosedProperty会收到xaml更改。
我的问题是:如何在Designer中修改了值后运行IsClosed 。 或者至少为非运行时更改添加一些逻辑。

您必须使用属性元数据注册PropertyChangedCallback 。

原因是在XAML中设置的依赖项属性或绑定或某些其他源不会调用CLR包装器(setter方法)。 原因在MSDN上的XAML加载和依赖属性文章中进行了解释:

出于实现原因,将属性标识为依赖项属性并访问属性系统SetValue方法来设置它,而不是使用属性包装器及其setter,计算成本更低。

由于属性设置的XAML处理器行为的当前WPF实现完全绕过包装器,因此不应将任何其他逻辑放入自定义依赖项属性的包装器的集定义中。 如果将这样的逻辑放在set定义中,那么当在XAML中而不是在代码中设置属性时,将不会执行逻辑。

您的代码应如下所示:

 public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register( "IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((GroupBox)o).OnIsClosedChanged())); public bool IsClosed { get { return (bool)GetValue(IsClosedProperty); } set { SetValue(IsClosedProperty, value); } } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); } 

现在就找到了答案。 ValidateValueCallback非常接近! (正如Alex K指出的那样)但它是一个静态方法,我没有得到任何已经改变的实例的引用。 关键是在FrameworkPropertyMetadata中使用PropertyChangedCallback,它也是传递给Property.Register方法的参数。
看到:

 public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnIsClosedChangedPCC))); public bool IsClosed { get { return (bool)this.GetValue(IsClosedProperty); } set { this.SetValue(IsClosedProperty, value); OnIsClosedChanged(); } } private static void OnIsClosedChangedPCC(DependencyObject d, DependencyPropertyChangedEventArgs e) { GroupBox current = (GroupBox)d; current.IsClosed = current.IsClosed; } private void OnIsClosedChanged() { _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); } 

现在这样做会重新设置IsClosedValue ,触发OnIsClosedChanged运行。
谢谢你的帮助!