更新
This commit is contained in:
119
WPFDark/Internals/DependencyObjectExtensions.cs
Normal file
119
WPFDark/Internals/DependencyObjectExtensions.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace WPFDark.Internals
|
||||
{
|
||||
// http://blog.xin9le.net/entry/2013/10/29/222336 を参考にしました
|
||||
|
||||
internal static class DependencyObjectExtensions
|
||||
{
|
||||
public static IEnumerable<DependencyObject> Children(this DependencyObject obj)
|
||||
{
|
||||
if (obj is null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
if (obj is Popup popup)
|
||||
if (popup.Child != null)
|
||||
yield return popup.Child;
|
||||
|
||||
var count = VisualTreeHelper.GetChildrenCount(obj);
|
||||
if (count == 0)
|
||||
yield break;
|
||||
|
||||
for (var i = 0; i != count; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(obj, i);
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj)
|
||||
{
|
||||
if (obj is null)
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
|
||||
var children = ArrayPool<DependencyObject>.Shared.Rent(obj.MaximumChildrenCount());
|
||||
|
||||
try
|
||||
{
|
||||
var childrenCount = obj.Children(children);
|
||||
|
||||
for (var i = 0; i != childrenCount; ++i)
|
||||
{
|
||||
var child = children[i];
|
||||
|
||||
yield return child;
|
||||
|
||||
foreach (var grandChild in child.Descendants())
|
||||
yield return grandChild;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<DependencyObject>.Shared.Return(children);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int MaximumChildrenCount(this DependencyObject obj)
|
||||
{
|
||||
return VisualTreeHelper.GetChildrenCount(obj) + 1;
|
||||
}
|
||||
|
||||
private static int Children(this DependencyObject obj, Span<DependencyObject> result)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
if (obj is Popup popup)
|
||||
if (popup.Child != null)
|
||||
result[count++] = popup.Child;
|
||||
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(obj);
|
||||
|
||||
for (var i = 0; i != childrenCount; i++)
|
||||
result[count++] = VisualTreeHelper.GetChild(obj, i);
|
||||
|
||||
return count;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取父元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="self"></param>
|
||||
/// <returns></returns>
|
||||
public static T? GetParent<T>(this DependencyObject self) where T : class
|
||||
{
|
||||
var parent = self;
|
||||
|
||||
do
|
||||
{
|
||||
if (parent is T tp)
|
||||
return tp;
|
||||
|
||||
parent = VisualTreeHelper.GetParent(parent);
|
||||
} while (parent != null);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DependencyObject? GetParent(this DependencyObject self, Type type)
|
||||
{
|
||||
var parent = self;
|
||||
|
||||
do
|
||||
{
|
||||
if (parent.GetType().IsSubclassOf(type))
|
||||
return parent;
|
||||
|
||||
parent = VisualTreeHelper.GetParent(parent);
|
||||
} while (parent != null);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user