PIbd-33_FIrsov_Kirill_KOP/CheckedListBoxLibrary/VisualComponents/HierarchicalTreeView.cs
2024-11-17 13:31:27 +04:00

144 lines
5.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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("Неверный индекс или имя узла");
}
}
}
}