【问题标题】:How to subscribe to a nested property in a observable collection in ReactiveUI如何订阅 ReactiveUI 中可观察集合中的嵌套属性
【发布时间】:2021-02-02 14:32:21
【问题描述】:

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

查看模型:

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?

这只是一个例子,我暂时没有写任何代码。

提前致谢。

【问题讨论】:

  • 请为当前的写更完整的代码我不明白你的问题。
  • 谢谢,我编辑了代码,我不知道如何订阅 viewmodel 类中的 isPassed 属性。
  • @BarakD - 你的意思是ObservableCollection&lt;HWTest&gt; 还是IObservable&lt;HWTest&gt;?你不能订阅ObservableCollection
  • 我是 reactiveui 的新手,所以我使用 Observablecollection 来观察我在视图模型中拥有的所有 HWTest,
  • @BarakD - 这没有回答我的问题。你的意思是ObservableCollection&lt;HWTest&gt; 还是IObservable&lt;HWTest&gt;?你不能订阅ObservableCollection

标签: mvvm system.reactive reactiveui


【解决方案1】:

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

以下是如何使用 (1) ObservableCollection&lt;T&gt; 和 (2) IObservable&lt;T&gt; 来完成您的要求。

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

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&lt;HWInterface&gt; 来使用:

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.

【讨论】:

    【解决方案2】:

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

    一般来说,对于给定的ObservableCollection,我们想知道INotifyCollectionChangedINotifyPropertyChanged,这需要一些手动设置。我就这个话题写了blog

    TLDR

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多