PIbd-33_FIrsov_Kirill_KOP/CheckedListBoxLibrary/VisualComponents/HierarchicalTreeView.cs

144 lines
5.5 KiB
C#
Raw Permalink Normal View History

2024-11-17 13:25:39 +04:00
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("Неверный индекс или имя узла");
}
}
}
}