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

如何在ReactiveUI中监听子集合元素的属性变更?

ReactiveUI实现父VM监听子VM属性变化方案

1. 定义子ViewModel(ReactiveUI版)

子VM继承ReactiveObject,用[Reactive]特性标记需监听的属性,自动实现属性变更通知:

public class ChildViewModel : ReactiveObject
{
    [Reactive]
    public string UserInput { get; set; } // 监听的用户输入属性

    // 其他子VM属性...
}

2. 父ViewModel核心实现

父VM同样继承ReactiveObject,通过两个关键步骤完成监听:监听集合的增删事件,为新增子VM订阅属性变更;为每个子VM的目标属性添加订阅并触发操作。

public class ParentViewModel : ReactiveObject
{
    public ObservableCollection<ChildViewModel> Children { get; } = new ObservableCollection<ChildViewModel>();

    public ParentViewModel()
    {
        // 监听集合变更事件
        Children.CollectionChanged += OnChildrenCollectionChanged;

        // 为初始化时已存在的子VM订阅属性变化
        foreach (var child in Children)
        {
            SubscribeToChildPropertyChanges(child);
        }
    }

    private void OnChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // 为新增子VM订阅属性变化
        if (e.NewItems != null)
        {
            foreach (ChildViewModel child in e.NewItems)
            {
                SubscribeToChildPropertyChanges(child);
            }
        }

        // 移除已删除子VM的订阅,避免内存泄漏
        if (e.OldItems != null)
        {
            foreach (ChildViewModel child in e.OldItems)
            {
                UnsubscribeFromChildPropertyChanges(child);
            }
        }
    }

    private IDisposable _childPropertySubscription;

    private void SubscribeToChildPropertyChanges(ChildViewModel child)
    {
        // 使用WhenAnyValue监听子VM的UserInput属性变化,执行父VM操作
        _childPropertySubscription = child.WhenAnyValue(x => x.UserInput)
            .Subscribe(newValue =>
            {
                HandleChildUserInputChanged(child, newValue);
            });
    }

    private void UnsubscribeFromChildPropertyChanges(ChildViewModel child)
    {
        _childPropertySubscription?.Dispose();
    }

    private void HandleChildUserInputChanged(ChildViewModel child, string newInput)
    {
        // 这里编写父VM对该子VM实例的操作逻辑
        Console.WriteLine($"子VM {child.GetHashCode()} 的UserInput更新为: {newInput}");
        // 你的业务逻辑,比如更新父VM状态、触发校验等...
    }
}

3. 更贴合ReactiveUI风格的集合监听方式

可以用WhenAnyObservable简化集合变更的监听逻辑,替换构造函数中的CollectionChanged事件绑定:

// 父VM构造函数内替换原有监听代码
this.WhenAnyValue(x => x.Children)
    .SelectMany(children => children.ObserveCollectionChanged())
    .Subscribe(e =>
    {
        if (e.NewItems != null)
        {
            foreach (ChildViewModel child in e.NewItems)
            {
                SubscribeToChildPropertyChanges(child);
            }
        }
        if (e.OldItems != null)
        {
            foreach (ChildViewModel child in e.OldItems)
            {
                UnsubscribeFromChildPropertyChanges(child);
            }
        }
    });

关键注意事项

  • 必须为移除的子VM取消订阅,防止内存泄漏
  • 子VM的目标属性需是ReactiveUI响应式属性([Reactive]特性或手动调用RaiseAndSetIfChanged)
  • WhenAnyValue会自动处理属性变更通知,无需手动监听PropertyChanged事件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 21:12:08