141 lines
3.9 KiB
C#
141 lines
3.9 KiB
C#
namespace CustomsComponentsVar2;
|
||
|
||
public partial class CustomTreeView: UserControl
|
||
{
|
||
/// <summary>
|
||
/// Иерархия дерева по полям класса
|
||
/// </summary>
|
||
private List<string> hierarchy;
|
||
/// <summary>
|
||
/// Список полей, для которых обязательно создаем новыую ветку (например, ФИО, на случай полных однофамильцев)
|
||
/// </summary>
|
||
private Dictionary<string, bool> newBranch;
|
||
public int SelectedIndex
|
||
{
|
||
get
|
||
{
|
||
return SelectedIndex;
|
||
}
|
||
set
|
||
{
|
||
SelectedIndex = value;
|
||
}
|
||
}
|
||
public CustomTreeView()
|
||
{
|
||
InitializeComponent();
|
||
hierarchy = new List<string>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Устанавливает иерархию по полям класса, начиная с главного
|
||
/// </summary>
|
||
/// <param name="hierarchy"></param>
|
||
/// <param name="newBranch"></param>
|
||
public void setHierarchy(List<string> hierarchy, Dictionary<string, bool> newBranch)
|
||
{
|
||
this.hierarchy = hierarchy;
|
||
this.newBranch = newBranch;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Строит дерево на основе полученных элементов
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="elements"></param>
|
||
public void build<T>(List<T> elements)
|
||
{
|
||
foreach (var el in elements)
|
||
{
|
||
add(el, hierarchy, treeView.Nodes, 0);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Рекурсивно добавляет узлы в дерево
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="el"></param>
|
||
/// <param name="hierarchy"></param>
|
||
/// <param name="nodes"></param>
|
||
/// <param name="level"></param>
|
||
private void add<T>(T el, List<string> hierarchy, TreeNodeCollection nodes, int level)
|
||
{
|
||
// если превышено количество уровней в иерархии
|
||
if (level >= hierarchy.Count)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// находим свойство (на основе иерархии) – извлекаем значение
|
||
string property = hierarchy[level];
|
||
string propertyValue = el.GetType().GetProperty(property)?.GetValue(el)?.ToString() ?? string.Empty;
|
||
|
||
// ищем, есть ли уже узел с таким названием
|
||
TreeNode foundNode = null;
|
||
foreach (TreeNode node in nodes)
|
||
{
|
||
if (node.Text == propertyValue)
|
||
{
|
||
foundNode = node;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// если не найден ИЛИ указано, что нужно создать новый узел, то добавляем новый узел
|
||
if (foundNode == null || newBranch.ContainsKey(property) && newBranch[property])
|
||
{
|
||
foundNode = nodes.Add(propertyValue);
|
||
}
|
||
|
||
// шаг на уровень глубже
|
||
add(el, hierarchy, foundNode.Nodes, level + 1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// получение выбранного элемента по индексу (с рефлексией)
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <returns></returns>
|
||
public T getSelected<T>() where T : new()
|
||
{
|
||
if (SelectedIndex >= 0 && SelectedIndex < treeView.Nodes.Count)
|
||
{
|
||
TreeNode node = treeView.Nodes[SelectedIndex];
|
||
// если последний уровень
|
||
if (node.Level == hierarchy.Count)
|
||
{
|
||
T el = new T();
|
||
setProperties(el, node, node.Level);
|
||
return el;
|
||
}
|
||
}
|
||
return default(T);
|
||
}
|
||
|
||
/// <summary>
|
||
/// получение значений свойств элемента по узлам
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="el"></param>
|
||
/// <param name="node"></param>
|
||
/// <param name="level"></param>
|
||
private void setProperties<T>(T el, TreeNode node, int level)
|
||
{
|
||
if (hierarchy.Count >= level)
|
||
{
|
||
var property = hierarchy[level];
|
||
var propertyValue = typeof(T).GetProperty(property);
|
||
if (propertyValue != null)
|
||
{
|
||
propertyValue.SetValue(el, node.Text);
|
||
}
|
||
}
|
||
|
||
if (node.Parent != null)
|
||
{
|
||
setProperties(el, node.Parent, level - 1);
|
||
}
|
||
}
|
||
}
|