123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using InABox.Core;
- using InABox.WPF;
- using NPOI.OpenXmlFormats.Dml.Chart;
- using Syncfusion.UI.Xaml.TreeGrid;
- using Syncfusion.UI.Xaml.TreeView;
- using Syncfusion.Windows.Tools.Controls;
- namespace InABox.DynamicGrid
- {
- public class DynamicTreeNode : INotifyPropertyChanged
- {
- private DynamicTreeNodes _owner = null;
-
- public ObservableCollection<DynamicTreeNode> Children => _owner.GetChilden(_id);
-
- private Guid _id;
- public Guid ID
- {
- get { return _id; }
- set
- {
- _id = value;
- RaisedOnPropertyChanged("ID");
- }
- }
-
- private Guid _parent;
- public Guid Parent
- {
- get { return _parent; }
- set
- {
- _parent = value;
- RaisedOnPropertyChanged("Parent");
- }
- }
- private string _description;
- public string Description
- {
- get { return _description; }
- set
- {
- _description = value;
- RaisedOnPropertyChanged("Description");
- }
- }
-
- private ImageSource? _image;
- public ImageSource? Image
- {
- get { return _image; }
- set
- {
- _image = value;
- RaisedOnPropertyChanged("Image");
- }
- }
- public event PropertyChangedEventHandler PropertyChanged;
- public void RaisedOnPropertyChanged(string propertyName)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- public DynamicTreeNode(DynamicTreeNodes owner)
- {
- _owner = owner;
- }
- public DynamicTreeNode(DynamicTreeNodes owner, Guid id, Guid parent) : this(owner)
- {
- _id = id;
- _parent = parent;
- }
- }
- public class DynamicTreeNodes
- {
- private List<DynamicTreeNode> _nodes = null;
- public ObservableCollection<DynamicTreeNode> Nodes => new ObservableCollection<DynamicTreeNode>(_nodes.Where(x=>x.Parent == Guid.Empty));
-
- public DynamicTreeNodes()
- {
- _nodes = new List<DynamicTreeNode>();
- }
- public DynamicTreeNode Add(Guid id, Guid parent)
- {
- var node = new DynamicTreeNode(this, id, parent);
- _nodes.Add(node);
- return node;
- }
- public ObservableCollection<DynamicTreeNode> GetChilden(Guid id)
- {
- return new ObservableCollection<DynamicTreeNode>(_nodes.Where(x => x.Parent.Equals(id) && (x.ID != id)));
- }
- public void Load<T>(CoreTable table, Expression<Func<T, Guid>> id, Expression<Func<T, Guid>> parentid, Expression<Func<T, String>> description)
- {
- _nodes.Clear();
- foreach (var row in table.Rows)
- {
- Guid _id = row.Get<T, Guid>(id);
- Guid _parent = row.Get<T, Guid>(parentid);
- String _description = row.Get<T, String>(description);
- Add(_id, _parent).Description = _description;
- }
- }
-
- }
-
- public enum DynamicTreeOption
- {
- Add,
- Edit,
- Delete
- }
- public delegate void OnSelectItem(DynamicTreeNode node);
-
- public abstract class DynamicTreeView<T> : ContentControl where T : BaseObject, new()
- {
- protected abstract Expression<Func<T, Guid>> ID { get; }
- protected abstract Expression<Func<T, Guid>> ParentID { get; }
- protected abstract Expression<Func<T, String>> Description { get; }
- protected CoreTable Data { get; private set; }
- private ContextMenu _menu = null;
- private SfTreeGrid _tree = null;
- private DockPanel _dock = null;
- private Grid _grid = null;
- private Button _add = null;
- private Button _edit = null;
- private Button _delete = null;
- private Label _spacer = null;
- public FluentList<DynamicTreeOption> Options { get; private set; }
- public event OnSelectItem OnSelectItem;
- private double minRowHeight = 30D;
- private double maxRowHeight = 30D;
- public double MinRowHeight
- {
- get => minRowHeight;
- set
- {
- minRowHeight = value;
- CalculateRowHeight();
- }
- }
- public double MaxRowHeight
- {
- get => maxRowHeight;
- set
- {
- maxRowHeight = value;
- CalculateRowHeight();
- }
- }
- /*public double RowHeight
- {
- get => _tree.RowHeight;
- set => _tree.RowHeight = value;
- }*/
-
- public DynamicTreeView() : base()
- {
-
- Options = new FluentList<DynamicTreeOption>();
- Options.OnChanged += OptionsChanged;
-
- _grid = new Grid();
- _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1D, GridUnitType.Star) });
- _grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1D, GridUnitType.Star) });
- _grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1D, GridUnitType.Auto) });
- _menu = new ContextMenu();
- var additem = new MenuItem() { Header = "Add Child Folder" };
- additem.Click += (o, e) => { AddItem((_tree.SelectedItem as DynamicTreeNode).ID); };
- _menu.Items.Add(additem);
-
- _tree = new SfTreeGrid();
- _tree.ChildPropertyName = "Children";
- //_tree.ParentPropertyName = "Parent";
- _tree.AutoGenerateColumns = false;
- _tree.AutoExpandMode = AutoExpandMode.AllNodesExpanded;
- //_tree.NodeCollapsing += (o, e) => { e.Cancel = true; };
- _tree.HeaderRowHeight = 0D;
- _tree.SelectionChanged += (o,e) => OnSelectItem?.Invoke(_tree.SelectedItem as DynamicTreeNode);
- _tree.AllowSelectionOnExpanderClick = false;
-
- _tree.ContextMenu = _menu;
- _tree.Background = new SolidColorBrush(Colors.DimGray);
-
- var cellStyle = new Style(typeof(TreeGridRowControl));
- cellStyle.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(Colors.White)));
- _tree.RowStyle = cellStyle;
-
- _tree.SelectionBackground = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0xFF, 0x11, 0x9E, 0xD9));
- _tree.Columns.Add(new TreeGridTextColumn()
- {
- MappingName = "Description"
- }
- );
- _tree.ColumnSizer = TreeColumnSizer.Star;
- _tree.RowHeight = 30D;
- _tree.SetValue(Grid.RowProperty, 0);
- _grid.Children.Add(_tree);
-
- _dock = new DockPanel();
- _dock.SetValue(Grid.RowProperty, 1);
- _grid.Children.Add(_dock);
- _add = CreateButton(Properties.Resources.add.AsBitmapImage(System.Drawing.Color.White), "", "Add Item", (o) => AddItem(Guid.Empty));
- _add.Margin = new Thickness(0, 2, 2, 0);
- _add.Visibility = Visibility.Collapsed;
- _add.SetValue(DockPanel.DockProperty, Dock.Left);
- _dock.Children.Add(_add);
-
- _edit = CreateButton(Properties.Resources.pencil.AsBitmapImage(System.Drawing.Color.White), "", "Edit Item", EditItem);
- _edit.Margin = new Thickness(0, 2, 2, 0);
- _edit.Visibility = Visibility.Collapsed;
- _edit.SetValue(DockPanel.DockProperty, Dock.Left);
- _dock.Children.Add(_edit);
- _delete = CreateButton(Properties.Resources.delete.AsBitmapImage(System.Drawing.Color.White), "", "Delete Item", DeleteItem);
- _delete.Margin = new Thickness(2, 2, 0, 0);
- _delete.Visibility = Visibility.Collapsed;
- _delete.SetValue(DockPanel.DockProperty, Dock.Right);
- _dock.Children.Add(_delete);
-
- _spacer = new Label();
- _spacer.SetValue(DockPanel.DockProperty, Dock.Left);
- _dock.Children.Add(_spacer);
- Content = _grid;
- SizeChanged += DynamicTreeView_SizeChanged;
- }
- private void DynamicTreeView_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- CalculateRowHeight();
- }
- private void CalculateRowHeight()
- {
- if(Data != null && Data.Rows.Count > 0)
- {
- var contentHeight = _tree.ActualHeight - (_tree.Padding.Top + _tree.Padding.Bottom) - 2; // Two extra pixels of space
- var targetHeight = contentHeight / Data.Rows.Count;
- _tree.RowHeight = Math.Max(Math.Min(targetHeight, MaxRowHeight), MinRowHeight);
- }
- }
-
- private Button CreateButton(BitmapImage? image = null, string? text = null, string? tooltip = null, Action<Button>? action = null)
- {
- var button = new Button();
- button.SetValue(BorderBrushProperty, new SolidColorBrush(Colors.Gray));
- button.SetValue(BorderThicknessProperty, new Thickness(0.75));
- button.Height = 30;
- button.MinWidth = 30;
- button.Click += (o, e) => action?.Invoke(button);
- UpdateButton(button, image, text, tooltip);
- return button;
- }
- protected void UpdateButton(Button button, BitmapImage? image, string? text, string? tooltip = null)
- {
- var stackPnl = new StackPanel();
- stackPnl.Orientation = Orientation.Horizontal;
- if (image != null)
- {
- var img = new Image();
- img.Source = image;
- img.Margin = new Thickness(2);
- img.ToolTip = tooltip;
- stackPnl.Children.Add(img);
- }
- if (!string.IsNullOrEmpty(text))
- {
- var lbl = new Label();
- lbl.Content = text;
- lbl.VerticalAlignment = VerticalAlignment.Stretch;
- lbl.VerticalContentAlignment = VerticalAlignment.Center;
- lbl.Margin = new Thickness(2, 0, 5, 0);
- lbl.ToolTip = ToolTip;
- stackPnl.Children.Add(lbl);
- }
- button.Content = stackPnl;
- button.ToolTip = tooltip;
- }
-
- private void OptionsChanged(object sender, EventArgs args)
- {
- _add.Visibility = Options.Contains(DynamicTreeOption.Add) ? Visibility.Visible : Visibility.Collapsed;
- _edit.Visibility = Options.Contains(DynamicTreeOption.Edit) ? Visibility.Visible : Visibility.Collapsed;
- _delete.Visibility = Options.Contains(DynamicTreeOption.Delete) ? Visibility.Visible : Visibility.Collapsed;
- }
- protected virtual T DoCreateItem(Guid parent)
- {
- T result = new T();
- var node = _tree.SelectedItem as DynamicTreeNode;
- CoreUtils.SetPropertyValue(result, CoreUtils.GetFullPropertyName(ParentID, "."), parent);
- return result;
- }
- protected abstract T? DoLoadItem(Guid id);
- protected virtual bool DoEditItem(T item)
- {
- var form = new DynamicEditorForm(typeof(T));
- form.Items = new T[] { item };
- return form.ShowDialog() == true;
- }
- protected abstract void DoSaveItem(T item);
- protected abstract bool DoDeleteItem(Guid id);
- private void AddItem(Guid id)
- {
- try
- {
- T item = DoCreateItem(id);
- if (DoEditItem(item))
- {
- DoSaveItem(item);
- Refresh();
- }
- }
- catch (Exception e)
- {
- MessageBox.Show(e.Message);
- }
- }
-
- private void EditItem(Button button)
- {
- var node = _tree.SelectedItem as DynamicTreeNode;
- if (node == null)
- {
- MessageBox.Show("Please Select an item to edit!");
- return;
- }
- var item = DoLoadItem(node.ID);
- if (item != null && DoEditItem(item))
- {
- DoSaveItem(item);
- Refresh();
- }
- }
- private void DeleteItem(Button button)
- {
- var node = _tree.SelectedItem as DynamicTreeNode;
- if (node == null)
- {
- MessageBox.Show("Please Select an item to edit!");
- return;
- }
- if (DoDeleteItem(node.ID))
- {
- Refresh();
- }
- }
-
- public DynamicTreeNodes Nodes { get; set; }
- protected abstract void DoRefresh(Action<CoreTable?, Exception?> action);
- private void AfterRefresh()
- {
- var nodes = new DynamicTreeNodes();
- foreach (var row in Data.Rows)
- {
- var _id = row.Get(ID);
- var _parent = row.Get(ParentID);
- var _description = row.Get(Description);
- nodes.Add(_id, _parent).Description = _description;
- }
- Nodes = nodes;
- _tree.ItemsSource = nodes.Nodes;
- CalculateRowHeight();
- }
- public void Refresh()
- {
- DoRefresh((table, exception) =>
- {
- if(exception != null)
- {
- Dispatcher.Invoke(() =>
- {
- MessageBox.Show(String.Format("Error: {0}", exception.Message));
- });
- }
- Data = table;
- Dispatcher.Invoke(() =>
- {
- AfterRefresh();
- });
- });
- }
- }
- }
|