Kategorie
This commit is contained in:
174
FasdDesktopUi/Basics/Models/HierarchicalSelectionItem.cs
Normal file
174
FasdDesktopUi/Basics/Models/HierarchicalSelectionItem.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user