在Rx.NET / ReactiveUI中使用树

时间:2017-09-11 23:06:07

标签: c# reactiveui rx.net

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

例如,考虑具有属性TreeNodeName的班级ChildNodes。如何观察Name的任何次级的TreeNode更改?

用法可能如下所示:

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

TreeNode示例:

// 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>();
}

1 个答案:

答案 0 :(得分:1)

我无法运行您的代码 - 我最终遇到了DLL版本问题,因此我编写了一个基本类,它使用与您相同的结构来实现此功能:

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