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

能否让PropertyChanged Fody为ObservableCollection关联属性生成变更事件?

如何配置PropertyChanged Fody,让ObservableCollection元素变化时触发关联属性的PropertyChanged事件?

当前遇到的问题:

  • 类MyModel实现INotifyPropertyChanged后,Name属性已通过PropertyChanged Fody自动生成PropertyChanged事件触发逻辑
  • Color1、Color2是依赖私有ObservableCollection<Brush>字段_colors元素的只读属性,当_colors中对应元素被替换时,无法自动触发这两个属性的PropertyChanged事件

相关代码

public class MyModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name { get; set; }

    public Brush Color1 => _colors[0];
    public Brush Color2 => _colors[1];

    private ObservableCollection<Brush> _colors;

    public MyModel()
    {
        _colors = new ObservableCollection<Brush>()
        {
            Brushes.Transparent,
            Brushes.Black,
        };
    }

    public void DoSomething()
    {
        _colors[0] = Brushes.Green;
        _colors[1] = Brushes.Red;
    }

    protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
    {
        PropertyChanged?.Invoke(this, eventArgs);
    }
}

ILSpy反编译验证

反编译后可见Color1、Color2未生成事件触发逻辑:

public string Name
{
    [CompilerGenerated]
    get
    {
        return <Name>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        if (!string.Equals(<Name>k__BackingField, value, StringComparison.Ordinal))
        {
            <Name>k__BackingField = value;
            OnPropertyChanged(<>PropertyChangedEventArgs.Name);
        }
    }
}

public Brush Color1 => _colors[0];

public Brush Color2 => _colors[1];

解决方案

PropertyChanged Fody原生不支持自动监听ObservableCollection内部元素的变化来触发关联属性的PropertyChanged事件,需要手动补充逻辑:

方法1:手动订阅集合的CollectionChanged事件

修改MyModel的构造函数,给_colors订阅CollectionChanged事件,当集合内元素被替换时,触发对应属性的通知:

public MyModel()
{
    _colors = new ObservableCollection<Brush>()
    {
        Brushes.Transparent,
        Brushes.Black,
    };
    // 订阅集合变化事件
    _colors.CollectionChanged += Colors_CollectionChanged;
}

private void Colors_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // 仅处理元素替换的场景(对应你的DoSomething方法逻辑)
    if (e.Action == NotifyCollectionChangedAction.Replace)
    {
        // 遍历变化的元素索引
        for (int i = 0; i < e.NewItems.Count; i++)
        {
            int changedIndex = e.NewStartingIndex + i;
            switch (changedIndex)
            {
                case 0:
                    OnPropertyChanged(new PropertyChangedEventArgs(nameof(Color1)));
                    break;
                case 1:
                    OnPropertyChanged(new PropertyChangedEventArgs(nameof(Color2)));
                    break;
            }
        }
    }
    // 若需要处理添加、移除元素等场景,可补充对应case逻辑
}

方法2:结合DependsOn特性(仅辅助,仍需手动处理集合内部变化)

PropertyChanged Fody的[DependsOn]特性可以标记属性依赖的字段,但它仅会在字段本身被重新赋值时触发事件,不会追踪集合内部元素变化。可以用来增强依赖关系的声明,但核心逻辑还是需要方法1的事件订阅:

[DependsOn(nameof(_colors))]
public Brush Color1 => _colors[0];

[DependsOn(nameof(_colors))]
public Brush Color2 => _colors[1];

总结

最直接有效的方案是手动订阅ObservableCollection的CollectionChanged事件,在元素替换时触发对应属性的PropertyChanged通知。PropertyChanged Fody目前没有原生功能支持自动监听集合内部元素变化来触发关联属性的事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:03:16