144 lines
5.5 KiB
C#
144 lines
5.5 KiB
C#
|
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;
|
|||
|
|
|||
|
namespace MyUserControls
|
|||
|
{
|
|||
|
public partial class HierarchicalTreeView : UserControl
|
|||
|
{
|
|||
|
private List<string> propertyHierarchy = new List<string>();
|
|||
|
public HierarchicalTreeView()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
}
|
|||
|
// Установка иерархии свойств
|
|||
|
public void SetPropertyHierarchy(List<string> propertyNames)
|
|||
|
{
|
|||
|
if (propertyNames == null)
|
|||
|
{
|
|||
|
throw new ArgumentNullException(nameof(propertyNames), "Объект не может быть null.");
|
|||
|
}
|
|||
|
|
|||
|
foreach (var name in propertyNames)
|
|||
|
propertyHierarchy.Add(name);
|
|||
|
}
|
|||
|
|
|||
|
// Параметризованный метод для заполнения дерева
|
|||
|
public void AddObject<T>(T obj)
|
|||
|
{
|
|||
|
if (obj == null)
|
|||
|
throw new ArgumentNullException(nameof(obj));
|
|||
|
|
|||
|
// Получаем значение первого свойства из иерархии
|
|||
|
string initialValue = GetPropertyValue(obj, propertyHierarchy[0]);
|
|||
|
TreeNode currentNode = FindOrCreateNode(treeView.Nodes, initialValue);
|
|||
|
|
|||
|
// Обходим остальные свойства и строим ветвление
|
|||
|
for (int i = 1; i < propertyHierarchy.Count; i++)
|
|||
|
{
|
|||
|
string nextProperty = propertyHierarchy[i];
|
|||
|
string nextValue = GetPropertyValue(obj, nextProperty);
|
|||
|
|
|||
|
currentNode = FindOrCreateNode(currentNode.Nodes, nextValue);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Вспомогательный метод для получения значения свойства
|
|||
|
private string GetPropertyValue<T>(T obj, string propertyName)
|
|||
|
{
|
|||
|
// Используем рефлексию для получения значения свойства
|
|||
|
PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName);
|
|||
|
if (propertyInfo == null)
|
|||
|
throw new ArgumentException($"Свойство {propertyName} не найдено в классе {typeof(T).Name}.");
|
|||
|
|
|||
|
object value = propertyInfo.GetValue(obj);
|
|||
|
return value?.ToString() ?? "null"; // Возвращаем "null" вместо null
|
|||
|
}
|
|||
|
|
|||
|
// Вспомогательный метод для нахождения или создания узла
|
|||
|
private TreeNode FindOrCreateNode(TreeNodeCollection nodes, string value)
|
|||
|
{
|
|||
|
foreach (TreeNode node in nodes)
|
|||
|
{
|
|||
|
if (node.Text.Equals(value, StringComparison.OrdinalIgnoreCase))
|
|||
|
{
|
|||
|
return node;
|
|||
|
}
|
|||
|
}
|
|||
|
TreeNode newNode = new TreeNode(value);
|
|||
|
nodes.Add(newNode);
|
|||
|
return newNode;
|
|||
|
}
|
|||
|
|
|||
|
public T? GetSelectedItem<T>() where T : class, new()
|
|||
|
{
|
|||
|
if (treeView.SelectedNode == null)
|
|||
|
{
|
|||
|
throw new Exception("There are no selected nodes");
|
|||
|
}
|
|||
|
if (treeView.SelectedNode.Nodes.Count != 0)
|
|||
|
{
|
|||
|
throw new Exception("Node is not the end node");
|
|||
|
}
|
|||
|
|
|||
|
T result = new T();
|
|||
|
Type type = typeof(T);
|
|||
|
TreeNode treeNode = treeView.SelectedNode;
|
|||
|
|
|||
|
// Перебор узлов сверху вниз, начиная с выбранного узла
|
|||
|
for (int i = propertyHierarchy.Count - 1; i >= 0 && treeNode != null; i--, treeNode = treeNode.Parent)
|
|||
|
{
|
|||
|
// Получаем свойство по названию из propertyHierarchy
|
|||
|
var property = type.GetProperty(propertyHierarchy[i]);
|
|||
|
if (property != null && property.CanWrite)
|
|||
|
{
|
|||
|
// Сеттим значение свойства из текста узла
|
|||
|
property.SetValue(result, treeNode.Text);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Проверка на выполнение условий: если treeNode не null и i >= 0 (прекращаем заполнение)
|
|||
|
if (treeNode != null || propertyHierarchy.Count > 0)
|
|||
|
{
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
// Метод для выбора узла по его индексу
|
|||
|
public void SelectNode(int index, string nodeNameToSelect)
|
|||
|
{
|
|||
|
// Получение узла по индексу
|
|||
|
if (index >= 0 && index < treeView.Nodes.Count)
|
|||
|
{
|
|||
|
TreeNode currentNode = treeView.Nodes[1];
|
|||
|
|
|||
|
for (int i = propertyHierarchy.Count - 1; i >= 0 && currentNode != null; i--, currentNode = currentNode.FirstNode)
|
|||
|
{
|
|||
|
if (currentNode.FirstNode.Text == nodeNameToSelect)
|
|||
|
{
|
|||
|
treeView.SelectedNode = currentNode.FirstNode;
|
|||
|
break; // Выход из цикла после выбора узла
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
throw new ArgumentOutOfRangeException("Неверный индекс или имя узла");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|