using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; using InABox.Core; using InABox.WPF; using Syncfusion.UI.Xaml.TreeGrid; namespace InABox.DynamicGrid { // public class CoreTreeNode : INotifyPropertyChanged // { // // private CoreTreeNodes _owner; // // public ObservableCollection 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 CoreTreeNode(CoreTreeNodes owner) // { // _owner = owner; // _description = ""; // } // // public CoreTreeNode(CoreTreeNodes owner, Guid id, Guid parent) : this(owner) // { // _id = id; // _parent = parent; // } // } // // public class CoreTreeNodes // { // // private List _nodes; // public ObservableCollection Nodes => new ObservableCollection(_nodes.Where(x => x.Parent == Guid.Empty)); // // public CoreTreeNode? this[Guid id] => _nodes.FirstOrDefault(x => x.ID == id); // // public CoreTreeNodes() // { // _nodes = new List(); // } // // public CoreTreeNode Add(Guid id, Guid parent) // { // var node = new CoreTreeNode(this, id, parent); // _nodes.Add(node); // return node; // } // // public void GetChildren(List nodes, Guid id) // { // nodes.Add(id); // var children = GetChilden(id); // foreach (var child in children) // GetChildren(nodes, child.ID); // } // // public ObservableCollection GetChilden(Guid id) // { // // return new ObservableCollection(_nodes.Where(x => x.Parent.Equals(id) && (x.ID != id))); // } // // public void Load(CoreTable table, Expression> id, Expression> parentid, Expression> description) // { // _nodes.Clear(); // foreach (var row in table.Rows) // { // Guid _id = row.Get(id); // Guid _parent = row.Get(parentid); // String _description = row.Get(description); // Add(_id, _parent).Description = _description; // } // } // // } public enum DynamicTreeOption { Add, Edit, Delete } public delegate void OnSelectItem(CoreTreeNode node); public delegate void OnContextMenuOpening(CoreTreeNode node, ContextMenu menu); public abstract class DynamicTreeView : ContentControl where T : BaseObject, new() { protected abstract Expression> ID { get; } protected abstract Expression> ParentID { get; } protected abstract Expression> Description { get; } public CoreTable Data { get; private set; } private ContextMenu _menu; private SfTreeGrid _tree; private DockPanel _dock; private Grid _grid; private Button _add; private Button _edit; private Button _delete; private Label _spacer; public FluentList Options { get; private set; } public event OnSelectItem OnSelectItem; public event OnContextMenuOpening OnContextMenuOpening; 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(); } } private bool _shownumbers = false; public bool ShowNumbers { get => _shownumbers; set { _shownumbers = value; _tree.Columns[1].Width = value ? 50 : 0; } } /*public double RowHeight { get => _tree.RowHeight; set => _tree.RowHeight = value; }*/ public DynamicTreeView() : base() { Options = new FluentList(); 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) }); _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 CoreTreeNode)!); _tree.AllowSelectionOnExpanderClick = false; _menu = new ContextMenu(); var additem = new MenuItem() { Header = "Add Child Folder" }; additem.Click += (o, e) => { DoAddItem((_tree.SelectedItem as CoreTreeNode)!.ID, true); }; _menu.Items.Add(additem); _tree.ContextMenuOpening += _tree_ContextMenuOpening; _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.Columns.Add(new TreeGridTextColumn() { MappingName = "Number", Width = _shownumbers ? 50 : 0, TextAlignment = TextAlignment.Right } ); _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(Wpf.Resources.add.AsBitmapImage(System.Drawing.Color.White), "", "Add Item", (o) => DoAddItem(Guid.Empty, true)); _add.Margin = new Thickness(0, 2, 2, 0); _add.Visibility = Visibility.Collapsed; _add.SetValue(DockPanel.DockProperty, Dock.Left); _dock.Children.Add(_add); _edit = CreateButton(Wpf.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(Wpf.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; } #region Public Interface public void AddItem(CoreTreeNode? parentNode = null, bool edit = true) { var id = parentNode?.ID ?? Guid.Empty; DoAddItem(id, edit); } #endregion private void _tree_ContextMenuOpening(object sender, ContextMenuEventArgs e) { _menu.Items.Clear(); if (OnContextMenuOpening is not null) { OnContextMenuOpening.Invoke((_tree.SelectedItem as CoreTreeNode)!, _menu); if(_menu.Items.Count == 0) { e.Handled = true; } } else { if (Options.Contains(DynamicTreeOption.Add)) { _menu.AddItem("Add Item", null, (_tree.SelectedItem as CoreTreeNode)!.ID, (id) => DoAddItem(id, true)); } } } 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