using MyCustomComponents.Extensions; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using MyCustomComponents.Attributes; using System.Xml.Linq; namespace MyCustomComponents { public partial class CustomTreeView : UserControl { public CustomTreeView() { InitializeComponent(); } // Свойство для получения и установки выбранного узла в TreeView public int SelectedTreeNode { get { if (treeView.SelectedNode != null) { return treeView.SelectedNode.Index; } return -1; } set { if (treeView.Nodes.Count > 0 && value >= 0 && value < treeView.Nodes.Count) { treeView.SelectedNode = treeView.Nodes[value]; } else { throw new ArgumentOutOfRangeException(nameof(value), $"Индекс {value} выходит за пределы допустимого диапазона. Допустимый диапазон: от 0 до {treeView.Nodes.Count - 1}."); } } } public List? hierarchy { get; set; } private Dictionary newBranch { get; set; } = new Dictionary(); // Отдельный публичный метод очистки всех узлов дерева public void Clear() { treeView.Nodes.Clear(); } // Публичный метод для получения выбранной записи из древовидной структуры public T GetSelectedNode() where T : class, new() { if (hierarchy == null) { throw new HierarchyNullException("Hierarchy is null"); } if (treeView.SelectedNode == null) { throw new InvalidSelectedElementException("TreeView null"); } // Проверка, является ли выбранный узел корневым if (treeView.SelectedNode.Parent == null) { // Выбран корневой элемент — возвращаем пустой объект throw new InvalidSelectedElementException("Parent is null"); } // Если узел выбран и существует, вызываем приватный метод для получения данных узла return _getNode(); } // Приватный метод, идущий по узлам вверх (по иерархии) private T _getNode() where T : new() { TreeNode? node = treeView.SelectedNode; var obj = new T(); int level = hierarchy.Count - 1; // Проходим по иерархии от нижнего уровня к верхнему while (node != null && level >= 0) { var property = hierarchy[level]; obj.GetType().GetProperty(property)?.SetValue(obj, node.Text); node = node.Parent; level--; } return obj; } /* Параметризированный метод, у которого в передаваемых параметрах * идёт объект какого-то класса и имя свойства/поля, до которого согласно * иерархии будет следовать формирование ветви */ public void AddNode(T obj, string propertyName) { if (hierarchy == null) { throw new HierarchyNullException("Hierarchy is null"); } if (obj == null) { throw new ArgumentNullException("Added object is null"); } // Ищем индекс свойства в иерархии int index = hierarchy.IndexOf(propertyName); if (index == -1) { throw new PropertyNullException("Property not found in hierarchy"); } // Получаем первый узел в дереве, либо нулл, если узлов нет TreeNode currentNode = treeView.SelectedNode; // Проходимся по иерархии foreach (var property in hierarchy) { // Получаем значение свойства var value = obj.GetType().GetProperty(property)?.GetValue(obj, null)?.ToString(); bool createNewBranch = newBranch != null && newBranch.ContainsKey(propertyName) && newBranch[propertyName]; if (currentNode == null) { currentNode = treeView.Nodes.Cast() .FirstOrDefault(n => n.Text == value) ?? treeView.Nodes.Add(value); } else { var childNode = currentNode.Nodes.Cast().FirstOrDefault(n => n.Text == value); // Проверка нужно ли нам создавать дочерний узел if (childNode == null || createNewBranch) { childNode = currentNode.Nodes.Add(value); } // Переходим на уровень этого дочернего узла currentNode = childNode; } if (property == propertyName) { break; } } } public void SetHierarchy(List hierarchy, Dictionary newBranch) { this.hierarchy = hierarchy; this.newBranch = newBranch; } } }