CoreTreeNodes.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. namespace InABox.Core
  8. {
  9. public class CoreTreeNode<TKey> : INotifyPropertyChanged
  10. {
  11. private CoreTreeNodes<TKey> _owner;
  12. public ObservableCollection<CoreTreeNode<TKey>> Children => new ObservableCollection<CoreTreeNode<TKey>>(_owner.GetChildrenOfParent(_id));
  13. private TKey _id;
  14. public TKey ID
  15. {
  16. get { return _id; }
  17. set
  18. {
  19. _id = value;
  20. RaisedOnPropertyChanged("ID");
  21. }
  22. }
  23. private TKey _parent;
  24. public TKey Parent
  25. {
  26. get { return _parent; }
  27. set
  28. {
  29. _parent = value;
  30. RaisedOnPropertyChanged("Parent");
  31. }
  32. }
  33. private object _image;
  34. public object Image
  35. {
  36. get => _image;
  37. set
  38. {
  39. _image = value;
  40. RaisedOnPropertyChanged("Image");
  41. }
  42. }
  43. private CoreRow _row;
  44. public CoreRow Row
  45. {
  46. get => _row;
  47. set
  48. {
  49. _row = value;
  50. RaisedOnPropertyChanged("Row");
  51. RaisedOnPropertyChanged("Item[]");
  52. }
  53. }
  54. public object? this[string column]
  55. {
  56. get => Row[column];
  57. set
  58. {
  59. Row[column] = value;
  60. _owner.DoColumnChanged(this, column);
  61. }
  62. }
  63. public event PropertyChangedEventHandler? PropertyChanged;
  64. public void RaisedOnPropertyChanged(string propertyName)
  65. {
  66. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  67. }
  68. public CoreTreeNode(CoreTreeNodes<TKey> owner, CoreRow row)
  69. {
  70. _owner = owner;
  71. _row = row;
  72. }
  73. public CoreTreeNode(CoreTreeNodes<TKey> owner, TKey id, TKey parent, CoreRow row) : this(owner, row)
  74. {
  75. _id = id;
  76. _parent = parent;
  77. }
  78. public CoreTreeNode<TKey>? GetParent() => _owner[_parent];
  79. public int Index()
  80. {
  81. var parent = GetParent();
  82. return parent != null
  83. ? parent.Children.IndexOf(this) + 1
  84. : _owner.Nodes.IndexOf(this) + 1;
  85. }
  86. public void InvalidateData()
  87. {
  88. RaisedOnPropertyChanged("Row");
  89. RaisedOnPropertyChanged("Item[]");
  90. }
  91. public String Number
  92. {
  93. get
  94. {
  95. String result = Index().ToString();
  96. var parent = GetParent();
  97. while (parent != null)
  98. {
  99. int index = parent.Index();
  100. result = $"{index}.{result}";
  101. parent = parent.GetParent();
  102. }
  103. return result;
  104. }
  105. }
  106. }
  107. public class CoreTreeNodes<TNode, TKey> where TNode : CoreTreeNode<TKey>
  108. {
  109. private List<TNode> _nodes;
  110. private Dictionary<TKey, TNode> _nodeMap;
  111. public TKey DefaultKey { get; set; }
  112. public ObservableCollection<TNode> Nodes => new ObservableCollection<TNode>(_nodes.Where(x => Equals(x.Parent, DefaultKey)));
  113. public TNode? this[TKey id] => _nodeMap.GetValueOrDefault(id);
  114. public CoreTreeNodes(TKey defaultKey)
  115. {
  116. _nodes = new List<TNode>();
  117. _nodeMap = new Dictionary<TKey, TNode>();
  118. DefaultKey = defaultKey;
  119. }
  120. public TNode Add(TKey id, TKey parent, CoreRow row)
  121. {
  122. var node = (TNode)Activator.CreateInstance(typeof(TNode), this, id, parent, row );
  123. _nodes.Add(node);
  124. _nodeMap[id] = node;
  125. return node;
  126. }
  127. public TNode Find(TKey id) => _nodeMap.GetValueOrDefault(id);
  128. public TNode? Find(CoreRow row) => _nodes.FirstOrDefault(x => x.Row == row);
  129. /// <summary>
  130. /// Gets a given node and recursively all its children given by <paramref name="id"/>.
  131. /// </summary>
  132. /// <param name="id"></param>
  133. /// <returns></returns>
  134. public IEnumerable<TNode> GetChildren(TKey id)
  135. {
  136. if(!_nodeMap.TryGetValue(id, out var node))
  137. {
  138. yield break;
  139. }
  140. yield return node;
  141. var children = GetChildrenOfParent(id);
  142. foreach (var child in children)
  143. foreach (var item in GetChildren(child.ID))
  144. yield return item;
  145. }
  146. /// <summary>
  147. /// Get all the direct children of the parent given by <paramref name="id"/>.
  148. /// </summary>
  149. /// <param name="id"></param>
  150. /// <returns></returns>
  151. public IEnumerable<TNode> GetChildrenOfParent(TKey id)
  152. {
  153. return _nodes.Where(x => object.Equals(x.Parent, id) && !object.Equals(x.ID, id));
  154. }
  155. public void Load<T>(CoreTable table, Expression<Func<T, TKey>> id, Expression<Func<T, TKey>> parentid)
  156. {
  157. _nodes.Clear();
  158. foreach (var row in table.Rows)
  159. {
  160. var _id = row.Get(id);
  161. var _parent = row.Get(parentid);
  162. Add(_id, _parent, row);
  163. }
  164. }
  165. public delegate void ColumnChangedEventHandler(CoreTreeNode<TKey> node, string column);
  166. public event ColumnChangedEventHandler? ColumnChanged;
  167. internal void DoColumnChanged(CoreTreeNode<TKey> node, string column)
  168. {
  169. ColumnChanged?.Invoke(node, column);
  170. }
  171. }
  172. public class CoreTreeNodes<TKey> : CoreTreeNodes<CoreTreeNode<TKey>, TKey>
  173. {
  174. public CoreTreeNodes(TKey defaultKey) : base(defaultKey)
  175. {
  176. }
  177. }
  178. }