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

pgky5nke  于 2023-11-14  发布在  其他
关注(0)|答案(2)|浏览(160)

当我在运行时设置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。或者至少为非运行时更改添加一些逻辑。

093gszye

093gszye1#

您必须使用属性元数据注册PropertyChangedCallback
原因是在XAML中或由绑定或其他源设置的依赖项属性不会调用XML Package 器(setter方法)。在MSDN上的XAML Loading and Dependency Properties文章中解释了原因:
出于实现原因,将属性标识为依赖项属性并访问属性系统SetValue方法来设置它,而不是使用属性 Package 及其setter,在计算上开销更小。
...
由于属性设置的XAML处理器行为的当前WPF实现完全绕过 Package ,因此不应将任何其他逻辑放入自定义依赖项属性的 Package 的集定义中。如果将此类逻辑放入集定义中,则在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);
}

字符串

hujrc8aj

hujrc8aj2#

现在我自己找到了答案。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运行。
谢谢你们的帮助!

相关问题