DynamicGridTreeUIComponent.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. using InABox.Core;
  2. using InABox.Wpf;
  3. using InABox.WPF;
  4. using Syncfusion.Data;
  5. using Syncfusion.UI.Xaml.TreeGrid;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Linq.Expressions;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Media;
  15. namespace InABox.DynamicGrid;
  16. public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>
  17. where T : BaseObject, new()
  18. {
  19. private IDynamicGridUIComponentParent<T> _parent;
  20. public IDynamicGridUIComponentParent<T> Parent
  21. {
  22. get => _parent;
  23. set
  24. {
  25. _parent = value;
  26. }
  27. }
  28. private Column<T> IDColumn;
  29. private Column<T> ParentColumn;
  30. private Column<T> DescriptionColumn;
  31. private ContextMenu _menu;
  32. private SfTreeGrid _tree;
  33. private readonly ContextMenu ColumnsMenu;
  34. private Dictionary<Guid, CoreRow>? _rowMap;
  35. public event OnContextMenuOpening OnContextMenuOpening;
  36. FrameworkElement IDynamicGridUIComponent<T>.Control => _tree;
  37. private bool _shownumbers = false;
  38. public bool ShowNumbers
  39. {
  40. get => _shownumbers;
  41. set
  42. {
  43. _shownumbers = value;
  44. _tree.Columns[1].Width = value ? 50 : 0;
  45. }
  46. }
  47. public DynamicGridTreeUIComponent(Expression<Func<T, Guid>> idColumn, Expression<Func<T, Guid>> parentIDColumn, Expression<Func<T, string>> descriptionColumn)
  48. {
  49. IDColumn = new Column<T>(CoreUtils.GetFullPropertyName(idColumn, "."));
  50. ParentColumn = new Column<T>(CoreUtils.GetFullPropertyName(parentIDColumn, "."));
  51. DescriptionColumn = new Column<T>(CoreUtils.GetFullPropertyName(descriptionColumn, "."));
  52. ColumnsMenu = new ContextMenu();
  53. ColumnsMenu.Opened += ColumnsMenu_ContextMenuOpening;
  54. _tree = new SfTreeGrid();
  55. _tree.ChildPropertyName = "Children";
  56. //_tree.ParentPropertyName = "Parent";
  57. _tree.AutoGenerateColumns = false;
  58. _tree.AutoExpandMode = AutoExpandMode.AllNodesExpanded;
  59. //_tree.NodeCollapsing += (o, e) => { e.Cancel = true; };
  60. _tree.HeaderRowHeight = 0D;
  61. _tree.HeaderContextMenu = ColumnsMenu;
  62. _tree.SelectionChanged += (o,e) =>
  63. {
  64. var row = GetRow(_tree.SelectedItem as CoreTreeNode);
  65. if(row is not null)
  66. {
  67. Parent.SelectItems(new[] { row });
  68. }
  69. else
  70. {
  71. Parent.SelectItems(Array.Empty<CoreRow>());
  72. }
  73. }
  74. _tree.AllowSelectionOnExpanderClick = false;
  75. _menu = new ContextMenu();
  76. var additem = new MenuItem() { Header = "Add Child Folder" };
  77. additem.Click += (o, e) => { DoAddItem((_tree.SelectedItem as CoreTreeNode)!.ID, true); };
  78. _menu.Items.Add(additem);
  79. _tree.ContextMenuOpening += _tree_ContextMenuOpening;
  80. _tree.ContextMenu = _menu;
  81. _tree.Background = new SolidColorBrush(Colors.DimGray);
  82. var cellStyle = new Style(typeof(TreeGridRowControl));
  83. cellStyle.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.White)));
  84. _tree.RowStyle = cellStyle;
  85. _tree.SelectionBackground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0xFF, 0x11, 0x9E, 0xD9));
  86. _tree.Columns.Add(new TreeGridTextColumn()
  87. {
  88. MappingName = "Description"
  89. }
  90. );
  91. _tree.Columns.Add(new TreeGridTextColumn()
  92. {
  93. MappingName = "Number",
  94. Width = _shownumbers ? 50 : 0,
  95. TextAlignment = TextAlignment.Right
  96. }
  97. );
  98. _tree.ColumnSizer = TreeColumnSizer.Star;
  99. _tree.RowHeight = 30D;
  100. _tree.SetValue(Grid.RowProperty, 0);
  101. }
  102. private CoreRow? GetRow(CoreTreeNode? node)
  103. {
  104. return node is not null ? _rowMap?.GetValueOrDefault(node.ID) : null;
  105. }
  106. private void ColumnsMenu_ContextMenuOpening(object sender, RoutedEventArgs e)
  107. {
  108. if (sender is not ContextMenu menu) return;
  109. menu.Items.Clear();
  110. Parent.LoadColumnsMenu(menu);
  111. }
  112. public bool OptionsChanged()
  113. {
  114. ColumnsMenu.Visibility = Parent.HasOption(DynamicTreeOption.SelectColumns) ? Visibility.Visible : Visibility.Hidden;
  115. }
  116. #region Context Menu
  117. private void _tree_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  118. {
  119. _menu.Items.Clear();
  120. if (OnContextMenuOpening is not null)
  121. {
  122. OnContextMenuOpening.Invoke((_tree.SelectedItem as CoreTreeNode)!, _menu);
  123. if(_menu.Items.Count == 0)
  124. {
  125. e.Handled = true;
  126. }
  127. }
  128. else
  129. {
  130. if (Parent.HasOption(DynamicGridOption.AddRows))
  131. {
  132. _menu.AddItem("Add Item", null, (_tree.SelectedItem as CoreTreeNode)!.ID, (id) => DoAddItem(id, true));
  133. }
  134. }
  135. }
  136. #endregion
  137. #region CRUD
  138. protected T DoCreateItem(Guid parent)
  139. {
  140. var result = Parent.CreateItem();
  141. CoreUtils.SetPropertyValue(result, ParentColumn.Property, parent);
  142. return result;
  143. }
  144. protected void DoAddItem(Guid id, bool edit)
  145. {
  146. try
  147. {
  148. var item = DoCreateItem(id);
  149. if (edit)
  150. {
  151. if (Parent.EditItems(new[] { item }))
  152. {
  153. Parent.Refresh(false, true);
  154. }
  155. }
  156. else
  157. {
  158. Parent.SaveItem(item);
  159. Parent.Refresh(false, true);
  160. }
  161. }
  162. catch (Exception e)
  163. {
  164. MessageWindow.ShowError("An error occurred while adding an item", e);
  165. }
  166. }
  167. #endregion
  168. #region Refresh
  169. public CoreTreeNodes Nodes { get; set; }
  170. public void BeforeRefresh()
  171. {
  172. throw new NotImplementedException();
  173. }
  174. public void RefreshColumns(DynamicGridColumns columns, DynamicActionColumns actionColumns)
  175. {
  176. throw new NotImplementedException();
  177. }
  178. public void RefreshData(CoreTable data)
  179. {
  180. var nodes = new CoreTreeNodes();
  181. foreach (var row in data.Rows)
  182. {
  183. var _id = row.Get<Guid>(IDColumn.Property);
  184. var _parent = row.Get<Guid>(ParentColumn.Property);
  185. var _description = row.Get<string>(DescriptionColumn.Property);
  186. nodes.Add(_id, _parent, row).Description = _description;
  187. }
  188. Nodes = nodes;
  189. _tree.ItemsSource = nodes.Nodes;
  190. CalculateRowHeight();
  191. }
  192. #endregion
  193. public CoreRow[] SelectedRows
  194. {
  195. get
  196. {
  197. return _tree.SelectedItems.OfType<CoreTreeNode>()
  198. .Select(x => GetRow(x)).NotNull().ToArray();
  199. }
  200. set
  201. {
  202. _tree.SelectedItems.Clear();
  203. foreach (var row in value)
  204. {
  205. _tree.SelectedItems.Add(Nodes.Find(row.Get<Guid>(IDColumn.Property)));
  206. }
  207. }
  208. }
  209. public double RowHeight
  210. {
  211. get => _tree.RowHeight;
  212. set => _tree.RowHeight = value;
  213. }
  214. public double HeaderRowHeight
  215. {
  216. get => _tree.HeaderRowHeight;
  217. set => _tree.HeaderRowHeight = value;
  218. }
  219. public int DesiredWidth()
  220. {
  221. throw new NotImplementedException();
  222. }
  223. public void AddVisualFilter(string column, string value, FilterType filtertype = FilterType.Contains)
  224. {
  225. }
  226. public List<Tuple<string, FilterPredicate>> GetFilterPredicates()
  227. {
  228. return new List<Tuple<string, FilterPredicate>>();
  229. }
  230. public CoreRow[] GetVisibleRows()
  231. {
  232. throw new NotImplementedException();
  233. }
  234. public void InvalidateRow(CoreRow row)
  235. {
  236. throw new NotImplementedException();
  237. }
  238. public void ScrollIntoView(CoreRow row)
  239. {
  240. throw new NotImplementedException();
  241. }
  242. public void UpdateCell(CoreRow row, string column, object? value)
  243. {
  244. throw new NotImplementedException();
  245. }
  246. public void UpdateRow(CoreRow row)
  247. {
  248. throw new NotImplementedException();
  249. }
  250. }