291 lines
8.5 KiB
C#
291 lines
8.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Media;
|
|
|
|
namespace WPFluent.Controls.Primitives;
|
|
|
|
public static class VisualTree
|
|
{
|
|
public static FrameworkElement? FindDescendantByName(this DependencyObject element, string name)
|
|
{
|
|
if (element == null || string.IsNullOrWhiteSpace(name))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (name.Equals((element as FrameworkElement)?.Name, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return element as FrameworkElement;
|
|
}
|
|
|
|
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
|
for (var i = 0; i < childrenCount; i++)
|
|
{
|
|
var frameworkElement = VisualTreeHelper.GetChild(element, i).FindDescendantByName(name);
|
|
if (frameworkElement != null)
|
|
{
|
|
return frameworkElement;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static T? FindDescendant<T>(this DependencyObject element) where T : DependencyObject
|
|
{
|
|
T? val = null;
|
|
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
|
for (var i = 0; i < childrenCount; i++)
|
|
{
|
|
var child = VisualTreeHelper.GetChild(element, i);
|
|
if (child is T val2)
|
|
{
|
|
val = val2;
|
|
break;
|
|
}
|
|
|
|
val = child.FindDescendant<T>();
|
|
if (val != null)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
public static object? FindDescendant(this DependencyObject element, Type type)
|
|
{
|
|
object? obj = null;
|
|
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
|
for (var i = 0; i < childrenCount; i++)
|
|
{
|
|
var child = VisualTreeHelper.GetChild(element, i);
|
|
if (child.GetType() == type)
|
|
{
|
|
obj = child;
|
|
break;
|
|
}
|
|
|
|
obj = child.FindDescendant(type);
|
|
if (obj != null)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
public static IEnumerable<T> FindDescendants<T>(this DependencyObject element) where T : DependencyObject
|
|
{
|
|
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
|
for (var i = 0; i < childrenCount; i++)
|
|
{
|
|
var child = VisualTreeHelper.GetChild(element, i);
|
|
if (child is T val)
|
|
{
|
|
yield return val;
|
|
}
|
|
|
|
foreach (var item in child.FindDescendants<T>())
|
|
{
|
|
yield return item;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static FrameworkElement? FindAscendantByName(this DependencyObject element, string name)
|
|
{
|
|
if (element == null || string.IsNullOrWhiteSpace(name))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var parent = VisualTreeHelper.GetParent(element);
|
|
if (parent == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (name.Equals((parent as FrameworkElement)?.Name, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return parent as FrameworkElement;
|
|
}
|
|
|
|
return parent.FindAscendantByName(name);
|
|
}
|
|
|
|
public static T? FindAscendant<T>(this DependencyObject element) where T : DependencyObject
|
|
{
|
|
var parent = VisualTreeHelper.GetParent(element);
|
|
if (parent == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (parent is T)
|
|
{
|
|
return parent as T;
|
|
}
|
|
|
|
return parent.FindAscendant<T>();
|
|
}
|
|
|
|
public static object? FindAscendant(this DependencyObject element, Type type)
|
|
{
|
|
var parent = VisualTreeHelper.GetParent(element);
|
|
if (parent == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (parent.GetType() == type)
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
return parent.FindAscendant(type);
|
|
}
|
|
|
|
public static IEnumerable<DependencyObject> FindAscendants(this DependencyObject element)
|
|
{
|
|
for (var parent = VisualTreeHelper.GetParent(element); parent != null; parent = VisualTreeHelper.GetParent(parent))
|
|
{
|
|
yield return parent;
|
|
}
|
|
}
|
|
|
|
public static bool DetachFromParent(this FrameworkElement element, DependencyObject parent)
|
|
{
|
|
try
|
|
{
|
|
if (parent is Panel panel)
|
|
{
|
|
panel.Children.Remove(element);
|
|
return true;
|
|
}
|
|
|
|
if (parent is Decorator decorator)
|
|
{
|
|
if (decorator.Child == element)
|
|
{
|
|
decorator.Child = null;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (parent is ContentControl contentControl)
|
|
{
|
|
contentControl.Content = null;
|
|
return true;
|
|
}
|
|
|
|
if (parent is ContentPresenter contentPresenter)
|
|
{
|
|
contentPresenter.Content = null;
|
|
return true;
|
|
}
|
|
|
|
if (parent is Popup popup)
|
|
{
|
|
popup.Child = null;
|
|
return true;
|
|
}
|
|
|
|
if (parent is ItemsControl itemsControl)
|
|
{
|
|
if (itemsControl.Items.Contains(element))
|
|
{
|
|
itemsControl.Items.Remove(element);
|
|
return true;
|
|
}
|
|
|
|
if (itemsControl.Items.Contains(element.DataContext))
|
|
{
|
|
itemsControl.Items.Remove(element.DataContext);
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var type = parent.GetType();
|
|
var bindingAttr = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public;
|
|
List<PropertyInfo> obj =
|
|
[
|
|
type.GetProperty("Children", bindingAttr),
|
|
type.GetProperty("Child", bindingAttr),
|
|
type.GetProperty("Content", bindingAttr),
|
|
type.GetProperty("Items", bindingAttr)
|
|
];
|
|
var flag = false;
|
|
foreach (var item in obj)
|
|
{
|
|
switch (item.Name.ToLower())
|
|
{
|
|
case "children":
|
|
{
|
|
var value = item.GetValue(parent, null);
|
|
var methods = value?.GetType().GetMethods() ?? [];
|
|
foreach (var methodInfo in methods)
|
|
{
|
|
if (methodInfo.Name.ToLower() == "remove")
|
|
{
|
|
methodInfo.Invoke(value, [element]);
|
|
flag = true;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case "child":
|
|
case "content":
|
|
if (item.GetValue(parent) == element)
|
|
{
|
|
item.SetValue(parent, null);
|
|
flag = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
if (Debugger.IsAttached)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool DetachFromLogicalParent(this FrameworkElement element)
|
|
{
|
|
var parent = element.Parent;
|
|
element.DetachFromParent(parent);
|
|
return element.Parent != parent;
|
|
}
|
|
|
|
public static bool DetachFromVisualParent(this FrameworkElement element)
|
|
{
|
|
var parent = VisualTreeHelper.GetParent(element);
|
|
element.DetachFromParent(parent);
|
|
return VisualTreeHelper.GetParent(element) != parent;
|
|
}
|
|
}
|