一尘不染

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

c#

当我IsClosed在运行时设置值时,OnIsClosedChanged()称为正常。但是,设计器会设置属性的值,但不会调用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);
}

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


阅读 314

收藏
2020-05-19

共1个答案

一尘不染

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

原因是在XAML中,通过绑定或其他来源设置的依赖项属性不会调用CLR包装器(setter方法)。MSDN上的XAML加载和依赖项属性文章中对此原因进行了说明:

出于实现的原因,将属性标识为依赖项属性并访问属性系统的SetValue方法以对其进行设置比使用属性包装器及其设置器要便宜得多。

因为针对属性设置的XAML处理器行为的当前WPF实现完全绕过了包装,所以您不应为自定义依赖项属性在包装的集合定义中添加任何其他逻辑。如果将这样的逻辑放在集合定义中,则当在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);
}
2020-05-19