在 Rx.NET / ReactiveUI 中使用树

Working with Trees in Rx.NET / ReactiveUI

如何观察 属性 树的任何子级别的变化?

例如,考虑具有属性 NameChildNodes 的 class TreeNode。如何在 TreeNode 的任何子级别观察 Name 变化?

用法可能如下所示:

rootNode.FlattenTreeToObservable(x => x.ChildNodes)
        .WhenAnyValue(x => x.Name)
        .Subscribe(...)

树节点示例:

// NuGet: Install-Package reactiveui
// In case of Splat version issue: Install-Package Splat -Version 1.6.2
using ReactiveUI; 

public class TreeNode: ReactiveObject 
{
    public string Name
    {
        get { return this._name; }
        set { this.RaiseAndSetIfChanged(ref this._name, value); }
    }
    private string _name = "";

    public ReactiveList<TreeNode> ChildNodes
    {
        get { return this._childNodes; }
        set { this.RaiseAndSetIfChanged(ref this._childNodes, value); }
    }
    private ReactiveList<TreeNode> _childNodes = new ReactiveList<TreeNode>();
}

我无法将您的代码获取到 运行 - 我最终遇到了 DLL 版本控制问题,因此我编写了一个基本的 class,它使用与您的相同的结构来使其工作:

public class TreeNode
{
    public string Name { get; set; }

    public Subject<TreeNode> ChildNodes { get; }
        = new Subject<TreeNode>();
}

然后我添加了以下方法:

    public IObservable<TreeNode> FlattenTreeToObservable()
    {
        return
            this.ChildNodes
                .SelectMany(cn => cn.FlattenTreeToObservable())
                .StartWith(this);
    }

现在当我运行这个测试代码时:

var root = new TreeNode() { Name = "R" };

root.FlattenTreeToObservable().Subscribe(tn => Console.WriteLine(tn.Name));

var a1 = new TreeNode() { Name = "A1" };
root.ChildNodes.OnNext(a1);

var b11 = new TreeNode() { Name = "B11" };
a1.ChildNodes.OnNext(b11);

var b12 = new TreeNode() { Name = "B12" };
a1.ChildNodes.OnNext(b12);

var a2 = new TreeNode() { Name = "A2" };
root.ChildNodes.OnNext(a2);

var b21 = new TreeNode() { Name = "B21" };
a2.ChildNodes.OnNext(b21);

var b22 = new TreeNode() { Name = "B22" };
a2.ChildNodes.OnNext(b22);  

我得到这个输出:

R
A1
B11
B12
A2
B21
B22