Kategorie

This commit is contained in:
Meik
2025-11-11 19:43:15 +01:00
parent dc3e8a2e4c
commit 05fb34815a
27 changed files with 1832 additions and 1109 deletions

View File

@@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
namespace FasdDesktopUi.Basics.Models
{
public class HierarchicalSelectionItem : INotifyPropertyChanged
{
private bool _isExpanded;
public string Id { get; set; }
public string DisplayName { get; set; }
public string ParentId { get; set; }
public string ParentDisplayName { get; set; }
public ObservableCollection<HierarchicalSelectionItem> Children { get; } = new ObservableCollection<HierarchicalSelectionItem>();
public HierarchicalSelectionItem Parent { get; private set; }
public bool IsExpanded
{
get => _isExpanded;
set
{
if (_isExpanded == value)
return;
_isExpanded = value;
OnPropertyChanged(nameof(IsExpanded));
}
}
public string FullPath
{
get
{
if (Parent == null || string.IsNullOrWhiteSpace(Parent.DisplayName))
return DisplayName ?? string.Empty;
if (string.IsNullOrWhiteSpace(DisplayName))
return Parent.FullPath;
return $"{Parent.FullPath} / {DisplayName}";
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public void AddChild(HierarchicalSelectionItem child)
{
if (child == null)
return;
child.Parent = this;
Children.Add(child);
}
public void ClearChildren()
{
foreach (var child in Children)
child.Parent = null;
Children.Clear();
}
public void SortChildrenRecursive()
{
if (Children == null || Children.Count == 0)
return;
var orderedChildren = Children
.OrderBy(child => child.DisplayName, StringComparer.CurrentCultureIgnoreCase)
.ToList();
Children.Clear();
foreach (var child in orderedChildren)
{
Children.Add(child);
child.SortChildrenRecursive();
}
}
public IEnumerable<HierarchicalSelectionItem> SelfAndDescendants()
{
yield return this;
foreach (var child in Children)
{
foreach (var descendant in child.SelfAndDescendants())
yield return descendant;
}
}
public void SetExpandedRecursive(bool isExpanded)
{
IsExpanded = isExpanded;
foreach (var child in Children)
child.SetExpandedRecursive(isExpanded);
}
public HierarchicalSelectionItem CloneWithoutChildren()
{
return new HierarchicalSelectionItem
{
Id = Id,
DisplayName = DisplayName,
ParentId = ParentId,
ParentDisplayName = ParentDisplayName
};
}
public HierarchicalSelectionItem CloneBranch(Func<HierarchicalSelectionItem, bool> predicate)
{
bool matches = predicate?.Invoke(this) ?? true;
var matchingChildren = new List<HierarchicalSelectionItem>();
foreach (var child in Children)
{
var childClone = child.CloneBranch(predicate);
if (childClone != null)
matchingChildren.Add(childClone);
}
if (!matches && matchingChildren.Count == 0)
return null;
var clone = CloneWithoutChildren();
foreach (var childClone in matchingChildren)
clone.AddChild(childClone);
return clone;
}
public static ObservableCollection<HierarchicalSelectionItem> BuildTree(IEnumerable<HierarchicalSelectionItem> items)
{
if (items == null)
return new ObservableCollection<HierarchicalSelectionItem>();
var lookup = items
.Where(item => !string.IsNullOrWhiteSpace(item?.Id))
.GroupBy(item => item.Id)
.Select(group => group.First())
.ToDictionary(item => item.Id);
foreach (var entry in lookup.Values)
entry.ClearChildren();
var roots = new List<HierarchicalSelectionItem>();
foreach (var item in lookup.Values)
{
if (!string.IsNullOrWhiteSpace(item.ParentId) && lookup.TryGetValue(item.ParentId, out var parent))
{
parent.AddChild(item);
}
else
{
item.Parent = null;
roots.Add(item);
}
}
foreach (var root in roots)
root.SortChildrenRecursive();
return new ObservableCollection<HierarchicalSelectionItem>(
roots.OrderBy(root => root.DisplayName, StringComparer.CurrentCultureIgnoreCase));
}
}
}