ObservedPropertyTree_ja - Houzkin/TreeStructures GitHub Wiki

ObservedPropertyTree

ツリー構造としては少し毛色の違う使い方をします。
観測可能なオブジェクトはINotifyPropertyChangedを実装しますが、 更にそのプロパティが示すINotifyPropertyChangedを実装したオブジェクトを観測したい、更にそのまた...といった場合に使用します。

例として、親ノードのプロパティを観測してみます。
まずはノードの定義とそのプロパティとして保持するINotifyPropertyChangedを実装したオブジェクトを定義します。

public class ObservableItemNode : ObservableGeneralTreeNode<ObservableItemNode>{
	public ObservableItemNode() {
	}
	AdditionalObj _info;
	public AdditionalObj AdditionalInfo {
		get => _info;
		set => this.SetProperty(ref _info, value);
	}
	public string Name { get; set; }
}

public class AdditionalObj : INotifyPropertyChanged {
	PropertyChangeProxy proxy;
	public AdditionalObj() {
		proxy = new PropertyChangeProxy(this);
	}
	string title = string.Empty;

	public event PropertyChangedEventHandler? PropertyChanged {
		add { proxy.PropertyChanged += value; }
		remove { proxy.PropertyChanged -= value; }
	}
	public string Title {
		get { return title; }
		set { proxy.SetWithNotify(ref title, value); }
	}
}

ツリーを組み立て、nodeHのgrand parentのAdditionalInfoプロパティのTitleプロパティを観測します。

var nodeList = "ABCDEFGH".ToCharArray().ToDictionary(x=>x,x=>new ObservableItemNode(){ Name = x.ToString() });
var tree = nodeList.Values.AssembleAsNAryTree(2);

var observingTree = new ObservedPropertyTree<ObservableItemNode>(nodeList['H']);
var listener = observingTree.Subscribe(
	x => x.Parent.Parent.AdditionalInfo.Title,
	ttl => Console.WriteLine($"Parent.Parent.AdditionalInfo.Title:{ttl}"));

Console.WriteLine(tree.ToTreeDiagram(x => x.Name));

Console.WriteLine("Set info");
nodeList.Values.ForEach(x => x.AdditionalInfo = new AdditionalObj() { Title = x.Name.ToLower() });

Console.WriteLine("\nSet title");
nodeList['B'].AdditionalInfo.Title = "bB" ;

Console.WriteLine("\nmode node H to be a child node of node C");
nodeList['C'].AddChild(nodeList['H']);

Console.WriteLine("\nremove node H");
nodeList['C'].RemoveChild(nodeList['H']);

screenshot 38

Titleプロパティが変更された時だけでなく、経由するプロパティ値が変化した場合も通知を受け取ることができます。
経由するプロパティ値はINotifyPropertyChangedの実装が必須です。
経由途中でnullがあった場合はデフォルト値となります。

また、ReactivePropertyを利用しやすいように、ToNotifyObjectメソッドを用意しています。

Console.WriteLine("\nA sample using ReactiveProperty");
var rp = observingTree
	.ToNotifyObject(x => x.Parent.AdditionalInfo.Title)
	.ObserveProperty(x => x.Value)
	.ToReadOnlyReactiveProperty();


nodeList['B'].AddChild(nodeList['H']);
Console.WriteLine($"ReactivePropertyValue:{rp.Value}");

screenshot 39

ObservedPropertyTreeもツリー構造をなしているので、以下のように観測しているプロパティ名を表示することができます。

Console.WriteLine("sample tree");
Console.WriteLine(tree.ToTreeDiagram(x => x.Name));
Console.WriteLine("nodeH : observed property tree");
Console.WriteLine(observingTree.Root.ToTreeDiagram(x => x.NamedProperty));

screenshot 40

使用後、ObservedPropertyTreeは破棄してください。

overvingTree.Dispose();

Where used

  • ReadOnlySortFilterObservableCollection
⚠️ **GitHub.com Fallback** ⚠️