176 lines
5.1 KiB
C#
176 lines
5.1 KiB
C#
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<string>? hierarchy { get; set; }
|
||
|
||
private Dictionary<string, bool> newBranch { get; set; } = new Dictionary<string, bool>();
|
||
|
||
// Отдельный публичный метод очистки всех узлов дерева
|
||
public void Clear()
|
||
{
|
||
treeView.Nodes.Clear();
|
||
}
|
||
|
||
// Публичный метод для получения выбранной записи из древовидной структуры
|
||
public T GetSelectedNode<T>() 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<T>();
|
||
}
|
||
|
||
|
||
// Приватный метод, идущий по узлам вверх (по иерархии)
|
||
private T _getNode<T>() 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>(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<TreeNode>()
|
||
.FirstOrDefault(n => n.Text == value) ?? treeView.Nodes.Add(value);
|
||
}
|
||
else
|
||
{
|
||
var childNode = currentNode.Nodes.Cast<TreeNode>().FirstOrDefault(n => n.Text == value);
|
||
|
||
// Проверка нужно ли нам создавать дочерний узел
|
||
if (childNode == null || createNewBranch)
|
||
{
|
||
childNode = currentNode.Nodes.Add(value);
|
||
}
|
||
|
||
// Переходим на уровень этого дочернего узла
|
||
currentNode = childNode;
|
||
}
|
||
|
||
if (property == propertyName)
|
||
{
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
public void SetHierarchy(List<string> hierarchy, Dictionary<string, bool> newBranch)
|
||
{
|
||
this.hierarchy = hierarchy;
|
||
this.newBranch = newBranch;
|
||
}
|
||
}
|
||
}
|