首页 文章

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

提问于
浏览
1

当我在运行时设置 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未修改 IsClosed ,只有 IsClosedProperty 接收到xaml更改 .
我的问题是:如何在Designer中修改了值后运行 IsClosed . 或者至少为非运行时更改添加一些逻辑 .

2 回答

  • 7

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

    原因是在XAML中设置的依赖项属性或绑定或某些其他源不设置CLR包装器(setter方法) . 原因在MSDN上的XAML Loading and Dependency Properties文章中解释:

    出于实现原因,将属性标识为依赖项属性并访问属性系统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);
    }
    
  • 1

    现在就找到了答案 . 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 运行 .
    谢谢你的帮助!

相关问题