如何在 ReactiveUI 的可观察集合中订阅嵌套属性

问题描述

如何订阅可观察集合中的嵌套属性

查看模型:

Public Class viewmodel{

    //a collection of all Hardware Tests.
    public observableCollection<HWTest> AllHWTests;


    //constructors
    viewmodel{

    //here I want to subscribe to Ispassed changes.
    
    }



}



硬件测试:


public class HWTest{

    //a Collection of all Hardware types,each element have a isPassed property 
    //of  type bool.
    observableCollection<HWInterface> AllSignals;
}

硬件接口:

public Class HWInterface{

    //the property I would like to subscribe to at the view model
    public bool isPassed;

}

我如何订阅 isPassed?

这只是一个例子,我目前没有写任何代码

提前致谢。

解决方法

ObservableCollection<T> 只让你观察集合成员的变化。您需要使用它来附加到每个类成员实现的事件,以查看集合成员中的各个属性何时发生变化。

以下是如何使用 (1) ObservableCollection<T> 和 (2) IObservable<T> 来完成您的要求。

首先我们需要设置我们想要观察的类:

public class HWInterface : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    
    public HWInterface(string name)
    {
        this.Name = name;
    }
    
    public string Name { get; private set; }
    
    private bool _isPassed = false;
    public bool IsPassed
    {
        get => _isPassed;
        set
        {
            if (_isPassed != value)
            {
                _isPassed = value;
                this.PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("IsPassed"));
            }
        }
    }
}

请注意,我已将您的大小写更改为使用普通的 C# 惯用形式。

现在我需要一个 ObservableCollection<HWInterface> 来使用:

var oc = new ObservableCollection<HWInterface>();

对于 (1) 我需要此代码来观看集合中的项目:

PropertyChangedEventHandler pceh = (s,e)  => Console.WriteLine($"1: {(s as HWInterface).Name} \"{e.PropertyName}\" changed to {(s as HWInterface).IsPassed}.");

oc.CollectionChanged += (s,e) =>
{
    if (e.NewItems != null) foreach (var f in e.NewItems.OfType<HWInterface>()) f.PropertyChanged += pceh;
    if (e.OldItems != null) foreach (var f in e.OldItems.OfType<HWInterface>()) f.PropertyChanged -= pceh;
};

对于 (2) 我需要此代码来观看集合中的项目:

var query =
    Observable
        .FromEventPattern<NotifyCollectionChangedEventHandler,NotifyCollectionChangedEventArgs>(
            h => oc.CollectionChanged += h,h => oc.CollectionChanged -= h)
        .Select(x =>
            oc
                .ToObservable()
                .SelectMany(f =>
                    Observable
                        .FromEventPattern<PropertyChangedEventHandler,PropertyChangedEventArgs>(
                            h => f.PropertyChanged += h,h => f.PropertyChanged -= h)
                        .Select(y => new { foo = f,property = y.EventArgs.PropertyName })))
        .Switch();
        
IDisposable subscription =
    query
        .Subscribe(x => Console.WriteLine($"2: {x.foo.Name} \"{x.property}\" changed to {x.foo.IsPassed}."));

现在我可以运行一些测试代码了:

var a = new HWInterface("A");
var b = new HWInterface("B");
var c = new HWInterface("C");

oc.Add(a);
oc.Add(b);
oc.Add(c);

b.IsPassed = true;

b.IsPassed = false;

oc.Remove(b);

b.IsPassed = true; // `b` has been removed so doesn't fire anymore
c.IsPassed = true;

这是我的输出:

1: B "IsPassed" changed to True.
2: B "IsPassed" changed to True.
1: B "IsPassed" changed to False.
2: B "IsPassed" changed to False.
1: C "IsPassed" changed to True.
2: C "IsPassed" changed to True.
,

开箱即用 ObservableCollection 没有为您提供您想要的。顾名思义,您可以观察列表内部的事物(列表中元素的 INotifyPropertyChangedEvent)。

通常,我们想知道给定 INotifyCollectionChangedINotifyPropertyChangedObservableCollection,这需要一些手动设置。我写了一篇关于这个主题的blog

TLDR

您要使用的是DynamicData。它将允许您从列表的内部元素获取属性更改通知。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...