You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中封装DependencyProperties到DependencyObject后属性变更能否转发到UserControl

问题1解答:不会自动转发

你给外层Arrow依赖属性加的AffectsMeasure标记,只会在Arrow属性本身的值发生变更(也就是替换了整个MyArrowProperties对象实例)的时候才会触发重测。你修改Arrow.StrokeThickness属于内部子属性变更,外层依赖属性感知不到,不会触发MeasureOverride。

解决方法

推荐两种常用实现方案,你可以根据场景选择:

方案1:继承Freezable(最符合WPF原生设计,代码改动最小)

WPF的Freezable类型原生支持子属性变更通知,当它作为依赖属性的值时,内部属性变更会自动向外层所属的FrameworkElement发送通知,触发对应标记的重测/重绘逻辑。
你只需要把你的属性类从DependencyObject改成继承Freezable,实现必要的抽象方法即可:

internal class MyArrowProperties : Freezable
{
    // 实现Freezable要求的抽象方法
    protected override Freezable CreateInstanceCore()
    {
        return new MyArrowProperties();
    }

    // 原有依赖属性注册代码不需要改动,你之前加的AffectsMeasure标记会自动生效
    private static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
        "StrokeThickness", 
        typeof(double), 
        typeof(MyArrowProperties), 
        new FrameworkPropertyMetadata(2d, FrameworkPropertyMetadataOptions.AffectsMeasure), 
        ValidateStrokeThickness);

    // 其他属性保持不变
}

改完之后你修改Arrow.StrokeThickness就会自动触发外层ProjectListTreePanel的MeasureOverride,不需要额外写事件监听代码。

方案2:手动实现事件监听

如果你因为其他逻辑不能继承Freezable,可以自己实现属性变更通知转发:

  1. 首先给MyArrowProperties添加属性变更事件:
internal class MyArrowProperties : DependencyObject
{
    // 定义向外通知的属性变更事件
    public event EventHandler SubPropertyChanged;

    private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var instance = (MyArrowProperties)d;
        instance.SubPropertyChanged?.Invoke(instance, EventArgs.Empty);
    }

    // 原有属性注册逻辑不变
    private static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
        "StrokeThickness", 
        typeof(double), 
        typeof(MyArrowProperties), 
        new FrameworkPropertyMetadata(2d, PropertyChangedCallback), 
        ValidateStrokeThickness);
}
  1. 在外层UserControl的Arrow属性变更回调中,订阅/取消订阅子属性变更事件,收到通知后主动触发重测:
public partial class ProjectListTreePanel : UserControl
{
    private static readonly DependencyProperty ArrowProperty = DependencyProperty.Register(
        "Arrow", 
        typeof(MyArrowProperties), 
        typeof(ProjectListTreePanel), 
        new FrameworkPropertyMetadata(null, ArrowPropertyChangedCallback));

    private static void ArrowPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var panel = (ProjectListTreePanel)d;
        // 取消旧实例的事件订阅,避免内存泄漏
        if (e.OldValue is MyArrowProperties oldProp)
        {
            oldProp.SubPropertyChanged -= panel.OnArrowSubPropertyChanged;
        }
        // 订阅新实例的事件
        if (e.NewValue is MyArrowProperties newProp)
        {
            newProp.SubPropertyChanged += panel.OnArrowSubPropertyChanged;
        }
    }

    private void OnArrowSubPropertyChanged(object sender, EventArgs e)
    {
        // 手动触发重测
        InvalidateMeasure();
    }
}

内容的提问来源于stack exchange,提问作者AxD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:54:01