diff --git a/Source/Wif.Utilities/Extensions/ByteExtension.cs b/Source/Wif.Utilities/Extensions/ByteExtension.cs
new file mode 100644
index 0000000..c0da329
--- /dev/null
+++ b/Source/Wif.Utilities/Extensions/ByteExtension.cs
@@ -0,0 +1,82 @@
+/**************************************************************************
+ * File Name:SerializationHelper.cs
+ * Description:SerializationHelper.cs class description...
+ * Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved.
+ * Creator:Leo Yang
+ * Create Time:2024/03/08
+ *Project Address:https://github.com/LeoYang-Chuese/wif
+ **************************************************************************/
+
+
+using System;
+using System.Collections;
+using System.Linq;
+
+namespace Frontier.Wif.Utilities.Extensions
+{
+ ///
+ /// 表示bit、byte和数据类型转换的扩展方法。
+ ///
+ public static class ByteExtension
+ {
+ #region BitArray Extension
+
+ ///
+ /// Convert bits to bytes.
+ ///
+ ///
+ ///
+ public static byte[] ToBytes(this BitArray bitArray)
+ {
+ int length = bitArray.Length / 8 + (bitArray.Length % 8 == 0 ? 0 : 1);
+ var array = new byte[length];
+ bitArray.CopyTo(array, 0);
+ return array;
+ }
+
+ ///
+ /// Convert bits to short.
+ ///
+ ///
+ ///
+ public static short ToShort(this BitArray bitArray)
+ {
+ byte[] bytes = bitArray.ToBytes();
+ return bytes.ToShort();
+ }
+
+ #endregion BitArray Extension
+
+ #region ValueType Extension
+
+ ///
+ /// Convert short to bits.
+ ///
+ ///
+ ///
+ public static BitArray ToBitArray(this short value)
+ {
+ byte[] bytes = BitConverter.GetBytes(value);
+ var bits = new BitArray(bytes);
+ return bits;
+ }
+
+ ///
+ /// Convert bytes to bits.
+ ///
+ ///
+ ///
+ public static short ToShort(this byte[] bytes)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return BitConverter.ToInt16(bytes, 0);
+ }
+
+ byte[] revValue = bytes.Reverse().ToArray();
+ return BitConverter.ToInt16(revValue, 0);
+ }
+
+ #endregion ValueType Extension
+ }
+}
\ No newline at end of file
diff --git a/Source/Wif.Utilities/Extensions/CharEncodingConverter.cs b/Source/Wif.Utilities/Extensions/CharEncodingConverter.cs
new file mode 100644
index 0000000..02183ce
--- /dev/null
+++ b/Source/Wif.Utilities/Extensions/CharEncodingConverter.cs
@@ -0,0 +1,84 @@
+/**************************************************************************
+ * File Name:SerializationHelper.cs
+ * Description:SerializationHelper.cs class description...
+ * Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved.
+ * Creator:Leo Yang
+ * Create Time:2024/03/08
+ *Project Address:https://github.com/LeoYang-Chuese/wif
+ **************************************************************************/
+
+
+using System;
+using System.Text;
+
+namespace Frontier.Wif.Utilities.Extensions
+{
+ ///
+ /// 表示字符编码转换器。
+ ///
+ public class CharEncodingConverter
+ {
+ #region 字符串转16进制编解码
+
+ ///
+ /// 字符串转十六进制编码。
+ ///
+ ///
+ ///
+ public static string StringToHex(string str)
+ {
+ var sb = new StringBuilder();
+ foreach (char c in str)
+ {
+ sb.Append(((int)c).ToString("X4"));
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// 十六进制编码转字符串。
+ ///
+ ///
+ /// 出现不符合十六进制字符则返回空字符。
+ /// true:转换成功;false:转换失败
+ public static bool HexToString(string hex, out string str)
+ {
+ str = string.Empty;
+ var sb = new StringBuilder();
+ for (var i = 0; i < hex.Length; i += 4)
+ {
+ string hexChar = hex.Substring(i, 4);
+ if (!IsHex(hexChar))
+ {
+ return false;
+ }
+
+ sb.Append((char)Convert.ToInt32(hexChar, 16));
+ }
+
+ str = sb.ToString();
+ return true;
+ }
+
+ ///
+ /// 判断字符串是否符合十六进制数。
+ ///
+ ///
+ ///
+ public static bool IsHex(string str)
+ {
+ foreach (char c in str)
+ {
+ if (!Uri.IsHexDigit(c))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Source/Wif.Utilities/Extensions/VisualTreeHelperExtensions.cs b/Source/Wif.Utilities/Extensions/VisualTreeHelperExtensions.cs
index 6cb0060..b6d13b8 100644
--- a/Source/Wif.Utilities/Extensions/VisualTreeHelperExtensions.cs
+++ b/Source/Wif.Utilities/Extensions/VisualTreeHelperExtensions.cs
@@ -1,73 +1,126 @@
/**************************************************************************
-* File Name:VisualTreeHelperExtensions.cs
-* Description:VisualTreeHelperExtensions.cs class description...
-* Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved.
-* Creator:Leo Yang
-* Create Time:2020/12/15
-*Project Address:https://github.com/LeoYang-Chuese/wif
-**************************************************************************/
-
+ * File Name:VisualTreeHelperExtensions.cs
+ * Description:VisualTreeHelperExtensions.cs class description...
+ * Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved.
+ * Creator:Leo Yang
+ * Create Time:2020/12/15
+ *Project Address:https://github.com/LeoYang-Chuese/wif
+ **************************************************************************/
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
+using System.Windows.Media.Media3D;
namespace Frontier.Wif.Utilities.Extensions
{
///
- /// 查找控件扩展方法
- /// http://www.hardcodet.net/uploads/2009/06/UIHelper.cs
+ /// 查找控件扩展方法 http://www.hardcodet.net/uploads/2009/06/UIHelper.cs
///
public static class VisualTreeHelperExtensions
{
#region Methods
+ ///
+ /// The GetParent
+ ///
+ /// The
+ /// The
+ /// The
+ private static DependencyObject GetParent(DependencyObject element, bool recurseIntoPopup)
+ {
+ if (recurseIntoPopup)
+ {
+ // Case 126732 : To correctly detect parent of a popup we must do that exception case
+
+ if (element is Popup popup && popup.PlacementTarget != null)
+ {
+ return popup.PlacementTarget;
+ }
+ }
+
+ DependencyObject parent = element is not Visual visual ? null : VisualTreeHelper.GetParent(visual);
+
+ if (parent == null)
+ {
+ // No Visual parent. Check in the logical tree.
+
+ if (element is FrameworkElement fe)
+ {
+ parent = fe.Parent;
+
+ if (parent == null)
+ {
+ parent = fe.TemplatedParent;
+ }
+ }
+ else
+ {
+ if (element is FrameworkContentElement fce)
+ {
+ parent = fce.Parent;
+
+ if (parent == null)
+ {
+ parent = fce.TemplatedParent;
+ }
+ }
+ }
+ }
+
+ return parent;
+ }
+
///
/// Finds a Child of a given item in the visual tree.
///
/// The type of the queried item.
/// A direct parent of the queried item.
- /// x:Name or Name of child.
- /// The
- public static T FindChild(DependencyObject parent, string childName)
- where T : DependencyObject
+ /// x:Name or Name of child.
+ /// The
+ public static T FindChild(DependencyObject parent, string childName) where T : DependencyObject
{
- // Confirm parent and childName are valid.
- if (parent == null) return null;
+ // Confirm parent and childName are valid.
+ if (parent == null)
+ {
+ return null;
+ }
T foundChild = null;
- var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
+ int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childrenCount; i++)
{
- var child = VisualTreeHelper.GetChild(parent, i);
+ DependencyObject child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
- var childType = child as T;
- if (childType == null)
+ if (child is not T childType)
{
// recursively drill down the tree
foundChild = FindChild(child, childName);
- // If the child is found, break so we do not overwrite the found child.
- if (foundChild != null) break;
+ // If the child is found, break so we do not overwrite the found child.
+ if (foundChild != null)
+ {
+ break;
+ }
}
else if (!string.IsNullOrEmpty(childName))
{
- var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
- if (frameworkElement != null && frameworkElement.Name == childName)
+ if (child is FrameworkElement frameworkElement && frameworkElement.Name == childName)
{
// if the child's name is of the request name
- foundChild = (T) child;
+ foundChild = (T)child;
break;
}
}
else
{
// child element found.
- foundChild = (T) child;
+ foundChild = (T)child;
break;
}
}
@@ -77,23 +130,25 @@ public static T FindChild(DependencyObject parent, string childName)
///
/// This will search for a child of the specified type. The search is performed
- /// hierarchically, breadth first (as opposed to depth first).
+ /// hierarchically, breadth first (as opposed to depth first).
///
/// The type of the element to find
- /// The root of the tree to search for. This element itself is not checked.
- /// The additionalCheck
+ ///
+ /// The root of the tree to search for. This element itself is not checked.
+ ///
+ /// The additionalCheck
/// Returns the found element. Null if nothing is found.
- public static T FindChild(this DependencyObject parent, Func additionalCheck = null)
- where T : DependencyObject
+ public static T FindChild(this DependencyObject parent, Func additionalCheck = null) where T : DependencyObject
{
- var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
- T child;
+ int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
+ T child;
for (var index = 0; index < childrenCount; index++)
{
child = VisualTreeHelper.GetChild(parent, index) as T;
if (child != null)
+ {
if (additionalCheck == null)
{
return child;
@@ -101,8 +156,11 @@ public static T FindChild(this DependencyObject parent, Func additio
else
{
if (additionalCheck(child))
+ {
return child;
+ }
}
+ }
}
for (var index = 0; index < childrenCount; index++)
@@ -110,86 +168,99 @@ public static T FindChild(this DependencyObject parent, Func additio
child = FindChild(VisualTreeHelper.GetChild(parent, index), additionalCheck);
if (child != null)
+ {
return child;
+ }
}
return null;
}
///
- /// 根据控件名称,查找子控件
- /// elementName为空时,查找指定类型的子控件
+ /// 根据控件名称,查找子控件 elementName为空时,查找指定类型的子控件
///
///
- /// The obj
- /// The elementName
- /// The
- public static T FindChildByName(this DependencyObject obj, string elementName)
- where T : FrameworkElement
+ /// The obj
+ /// The elementName
+ /// The
+ public static T FindChildByName(this DependencyObject obj, string elementName) where T : FrameworkElement
{
DependencyObject child = null;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
child = VisualTreeHelper.GetChild(obj, i);
- if (child is T && ((T) child).Name == elementName || string.IsNullOrEmpty(elementName))
- return (T) child;
+ if ((child is T && ((T)child).Name == elementName) || string.IsNullOrEmpty(elementName))
+ {
+ return (T)child;
+ }
var grandChild = FindChildByName(child, elementName);
- if (grandChild != null) return grandChild;
+ if (grandChild != null)
+ {
+ return grandChild;
+ }
}
return null;
}
///
- /// Analyzes both visual and logical tree in order to find all elements of a given
- /// type that are descendants of the item.
+ /// Analyzes both visual and logical tree in order to find all elements of a given type that
+ /// are descendants of the item.
///
/// The type of the queried items.
- /// The source
- /// Sometimes it's better to search in the VisualTree (e.g. in tests)
+ /// The source
+ ///
+ /// Sometimes it's better to search in the VisualTree (e.g. in tests)
+ ///
/// All descendants of that match the requested type.
- public static IEnumerable FindChildren(DependencyObject source,
- bool forceUsingTheVisualTreeHelper = false) where T : DependencyObject
+ public static IEnumerable FindChildren(DependencyObject source, bool forceUsingTheVisualTreeHelper = false) where T : DependencyObject
{
if (source != null)
{
var childs = GetChildObjects(source, forceUsingTheVisualTreeHelper);
- foreach (var child in childs)
+ foreach (DependencyObject child in childs)
{
//analyze if children match the requested type
- if (child != null && child is T) yield return (T) child;
+ if (child != null && child is T)
+ {
+ yield return (T)child;
+ }
//recurse tree
- foreach (var descendant in FindChildren(child)) yield return descendant;
+ foreach (T descendant in FindChildren(child))
+ {
+ yield return descendant;
+ }
}
}
}
///
- /// 根据控件名称,查找子控件集合
- /// elementName为空时,查找指定类型的所有子控件
+ /// 根据控件名称,查找子控件集合 elementName为空时,查找指定类型的所有子控件
///
///
- /// The obj
- /// The elementName
- /// The
- public static List FindChildsByName(this DependencyObject obj, string elementName)
- where T : FrameworkElement
+ /// The obj
+ /// The elementName
+ /// The
+ public static List FindChildsByName(this DependencyObject obj, string elementName) where T : FrameworkElement
{
- DependencyObject child = null;
- var childList = new List();
+ DependencyObject child = null;
+ var childList = new List();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
child = VisualTreeHelper.GetChild(obj, i);
- if (child is T && ((T) child).Name == elementName || string.IsNullOrEmpty(elementName))
+ if ((child is T && ((T)child).Name == elementName) || string.IsNullOrEmpty(elementName))
{
- childList.Add((T) child);
+ childList.Add((T)child);
}
else
{
var grandChildList = FindChildsByName(child, elementName);
- if (grandChildList != null) childList.AddRange(grandChildList);
+ if (grandChildList != null)
+ {
+ childList.AddRange(grandChildList);
+ }
}
}
@@ -200,7 +271,9 @@ public static List FindChildsByName(this DependencyObject obj, string elem
/// This will search for a parent of the specified type.
///
/// The type of the element to find
- /// The node where the search begins. This element is not checked.
+ ///
+ /// The node where the search begins. This element is not checked.
+ ///
/// Returns the found element. Null if nothing is found.
public static T FindParent(DependencyObject startingObject) where T : DependencyObject
{
@@ -214,8 +287,7 @@ public static T FindParent(DependencyObject startingObject) where T : Depende
/// The node where the search begins.
/// Should the specified startingObject be checked first.
/// Returns the found element. Null if nothing is found.
- public static T FindParent(DependencyObject startingObject, bool checkStartingObject)
- where T : DependencyObject
+ public static T FindParent(DependencyObject startingObject, bool checkStartingObject) where T : DependencyObject
{
return FindParent(startingObject, checkStartingObject, null);
}
@@ -226,19 +298,19 @@ public static T FindParent(DependencyObject startingObject, bool checkStartin
/// The type of the element to find
/// The node where the search begins.
/// Should the specified startingObject be checked first.
- /// The additionalCheck
+ /// The additionalCheck
/// Returns the found element. Null if nothing is found.
- public static T FindParent(DependencyObject startingObject, bool checkStartingObject,
- Func additionalCheck) where T : DependencyObject
+ public static T FindParent(DependencyObject startingObject, bool checkStartingObject, Func additionalCheck) where T : DependencyObject
{
- T foundElement;
- var parent = checkStartingObject ? startingObject : GetParent(startingObject, true);
+ T foundElement;
+ DependencyObject parent = checkStartingObject ? startingObject : GetParent(startingObject, true);
while (parent != null)
{
foundElement = parent as T;
if (foundElement != null)
+ {
if (additionalCheck == null)
{
return foundElement;
@@ -246,8 +318,11 @@ public static T FindParent(DependencyObject startingObject, bool checkStartin
else
{
if (additionalCheck(foundElement))
+ {
return foundElement;
+ }
}
+ }
parent = GetParent(parent, true);
}
@@ -256,21 +331,22 @@ public static T FindParent(DependencyObject startingObject, bool checkStartin
}
///
- /// 根据控件名称,查找父控件
- /// elementName为空时,查找指定类型的父控件
+ /// 根据控件名称,查找父控件 elementName为空时,查找指定类型的父控件
///
///
- /// The obj
- /// The elementName
- /// The
- public static T FindParentByName(this DependencyObject obj, string elementName)
- where T : FrameworkElement
+ /// The obj
+ /// The elementName
+ /// The
+ public static T FindParentByName(this DependencyObject obj, string elementName) where T : FrameworkElement
{
- var parent = VisualTreeHelper.GetParent(obj);
+ DependencyObject parent = VisualTreeHelper.GetParent(obj);
while (parent != null)
{
- if (parent is T && (((T) parent).Name == elementName || string.IsNullOrEmpty(elementName)))
- return (T) parent;
+ if (parent is T && (((T)parent).Name == elementName || string.IsNullOrEmpty(elementName)))
+ {
+ return (T)parent;
+ }
+
parent = VisualTreeHelper.GetParent(parent);
}
@@ -286,15 +362,22 @@ public static T FindParentByName(this DependencyObject obj, string elementNam
public static T FindVisualChildItem(this DependencyObject obj) where T : DependencyObject
{
if (null != obj)
+ {
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
- var child = VisualTreeHelper.GetChild(obj, i);
- if (child != null && child is T) return (T) child;
+ DependencyObject child = VisualTreeHelper.GetChild(obj, i);
+ if (child != null && child is T)
+ {
+ return (T)child;
+ }
var childOfChild = FindVisualChildItem(child);
if (childOfChild != null)
+ {
return childOfChild;
+ }
}
+ }
return null;
}
@@ -309,91 +392,125 @@ public static T FindVisualChildItem(this DependencyObject obj) where T : Depe
public static T FindVisualChildItem(this DependencyObject obj, string name) where T : FrameworkElement
{
if (null != obj)
+ {
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
- var child = VisualTreeHelper.GetChild(obj, i);
- if (child != null && child is T && (child as T).Name.Equals(name)) return (T) child;
+ DependencyObject child = VisualTreeHelper.GetChild(obj, i);
+ if (child != null && child is T && (child as T).Name.Equals(name))
+ {
+ return (T)child;
+ }
var childOfChild = FindVisualChildItem(child, name);
if (childOfChild != null && childOfChild is T && childOfChild.Name.Equals(name))
+ {
return childOfChild;
+ }
}
+ }
return null;
}
///
- /// This method is an alternative to WPF's
- /// method, which also
- /// supports content elements. Keep in mind that for content elements,
- /// this method falls back to the logical tree of the element.
+ /// This method is an alternative to WPF's method,
+ /// which also supports content elements. Keep in mind that for content elements, this
+ /// method falls back to the logical tree of the element.
///
/// The item to be processed.
- /// Sometimes it's better to search in the VisualTree (e.g. in tests)
+ ///
+ /// Sometimes it's better to search in the VisualTree (e.g. in tests)
+ ///
/// The submitted item's child elements, if available.
- public static IEnumerable GetChildObjects(DependencyObject parent,
- bool forceUsingTheVisualTreeHelper = false)
+ public static IEnumerable GetChildObjects(DependencyObject parent, bool forceUsingTheVisualTreeHelper = false)
{
- if (parent == null) yield break;
+ if (parent == null)
+ {
+ yield break;
+ }
if (!forceUsingTheVisualTreeHelper && (parent is ContentElement || parent is FrameworkElement))
{
//use the logical tree for content / framework elements
- foreach (var obj in LogicalTreeHelper.GetChildren(parent))
+ foreach (object obj in LogicalTreeHelper.GetChildren(parent))
{
- var depObj = obj as DependencyObject;
- if (depObj != null) yield return (DependencyObject) obj;
+ if (obj is DependencyObject depObj)
+ {
+ yield return (DependencyObject)obj;
+ }
}
}
else
{
//use the visual tree per default
- var count = VisualTreeHelper.GetChildrenCount(parent);
- for (var i = 0; i < count; i++) yield return VisualTreeHelper.GetChild(parent, i);
+ int count = VisualTreeHelper.GetChildrenCount(parent);
+ for (var i = 0; i < count; i++)
+ {
+ yield return VisualTreeHelper.GetChild(parent, i);
+ }
+ }
+ }
+
+ ///
+ /// 返回从叶节点开始的完整逻辑祖先链。
+ ///
+ /// 叶节点
+ /// 返回一个包含从叶节点开始的所有逻辑祖先的迭代器
+ public static IEnumerable GetLogicalAncestry(this DependencyObject leaf)
+ {
+ while (leaf != null)
+ {
+ yield return leaf;
+ leaf = LogicalTreeHelper.GetParent(leaf);
}
}
///
- /// Tries its best to return the specified element's parent. It will
- /// try to find, in this order, the VisualParent, LogicalParent, LogicalTemplatedParent.
- /// It only works for Visual, FrameworkElement or FrameworkContentElement.
+ /// Tries its best to return the specified element's parent. It will try to find, in this
+ /// order, the VisualParent, LogicalParent, LogicalTemplatedParent. It only works for
+ /// Visual, FrameworkElement or FrameworkContentElement.
///
- /// The element
- /// The
+ /// The element
+ /// The
public static DependencyObject GetParent(DependencyObject element)
{
return GetParent(element, true);
}
///
- /// This method is an alternative to WPF's
- /// method, which also
- /// supports content elements. Keep in mind that for content element,
- /// this method falls back to the logical tree of the element!
+ /// This method is an alternative to WPF's method,
+ /// which also supports content elements. Keep in mind that for content element, this method
+ /// falls back to the logical tree of the element!
///
/// The item to be processed.
- /// The
+ /// The
public static DependencyObject GetParentObject(this DependencyObject child)
{
- if (child == null) return null;
+ if (child == null)
+ {
+ return null;
+ }
//handle content elements separately
- var contentElement = child as ContentElement;
- if (contentElement != null)
+ if (child is ContentElement contentElement)
{
- var parent = ContentOperations.GetParent(contentElement);
- if (parent != null) return parent;
+ DependencyObject parent = ContentOperations.GetParent(contentElement);
+ if (parent != null)
+ {
+ return parent;
+ }
- var fce = contentElement as FrameworkContentElement;
- return fce != null ? fce.Parent : null;
+ return contentElement is FrameworkContentElement fce ? fce.Parent : null;
}
//also try searching for parent in framework elements (such as DockPanel, etc)
- var frameworkElement = child as FrameworkElement;
- if (frameworkElement != null)
+ if (child is FrameworkElement frameworkElement)
{
- var parent = frameworkElement.Parent;
- if (parent != null) return parent;
+ DependencyObject parent = frameworkElement.Parent;
+ if (parent != null)
+ {
+ return parent;
+ }
}
//if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
@@ -401,31 +518,48 @@ public static DependencyObject GetParentObject(this DependencyObject child)
}
///
- /// Returns true if the specified element is a child of parent somewhere in the visual
- /// tree. This method will work for Visual, FrameworkElement and FrameworkContentElement.
+ /// 返回从叶节点开始的完整视觉祖先链。
+ /// 如果元素不是 或 , 则使用逻辑祖先链。
+ ///
+ /// 叶节点
+ /// 返回一个包含从叶节点开始的所有祖先的迭代器
+ public static IEnumerable GetVisualAncestry(this DependencyObject leaf)
+ {
+ while (leaf != null)
+ {
+ yield return leaf;
+ leaf = leaf is Visual || leaf is Visual3D ? VisualTreeHelper.GetParent(leaf) : LogicalTreeHelper.GetParent(leaf);
+ }
+ }
+
+ ///
+ /// Returns true if the specified element is a child of parent somewhere in the visual tree.
+ /// This method will work for Visual, FrameworkElement and FrameworkContentElement.
///
/// The element that is potentially a child of the specified parent.
/// The element that is potentially a parent of the specified element.
- /// The
+ /// The
public static bool IsDescendantOf(DependencyObject element, DependencyObject parent)
{
return IsDescendantOf(element, parent, true);
}
///
- /// Returns true if the specified element is a child of parent somewhere in the visual
- /// tree. This method will work for Visual, FrameworkElement and FrameworkContentElement.
+ /// Returns true if the specified element is a child of parent somewhere in the visual tree.
+ /// This method will work for Visual, FrameworkElement and FrameworkContentElement.
///
/// The element that is potentially a child of the specified parent.
/// The element that is potentially a parent of the specified element.
- /// The recurseIntoPopup
- /// The
+ /// The recurseIntoPopup
+ /// The
public static bool IsDescendantOf(DependencyObject element, DependencyObject parent, bool recurseIntoPopup)
{
while (element != null)
{
if (element == parent)
+ {
return true;
+ }
element = GetParent(element, recurseIntoPopup);
}
@@ -433,20 +567,44 @@ public static bool IsDescendantOf(DependencyObject element, DependencyObject par
return false;
}
+ ///
+ /// 判断一个DependencyObject是否是另一个DependencyObject的后代。
+ ///
+ /// 可能是后代的DependencyObject
+ /// 可能是祖先的DependencyObject
+ /// 如果leaf是ancestor的后代,则返回true,否则返回false
+ public static bool IsDescendantOfDependencyObject(this DependencyObject leaf, DependencyObject ancestor)
+ {
+ DependencyObject parent = null;
+ foreach (DependencyObject node in leaf.GetVisualAncestry())
+ {
+ if (Equals(node, ancestor))
+ {
+ return true;
+ }
+
+ parent = node;
+ }
+
+ return parent?.GetLogicalAncestry().Contains(ancestor) == true;
+ }
+
///
/// Finds a parent of a given item on the visual tree.
///
/// The type of the queried item.
- /// The child
- /// The
- public static T TryFindParent(this DependencyObject child)
- where T : DependencyObject
+ /// The child
+ /// The
+ public static T TryFindParent(this DependencyObject child) where T : DependencyObject
{
//get parent item
- var parentObject = GetParentObject(child);
+ DependencyObject parentObject = GetParentObject(child);
//we've reached the end of the tree
- if (parentObject == null) return null;
+ if (parentObject == null)
+ {
+ return null;
+ }
//check if the parent matches the type we're looking for
var parent = parentObject as T;
@@ -454,52 +612,30 @@ public static T TryFindParent(this DependencyObject child)
}
///
- /// The GetParent
+ /// 提供了一种以深度优先的方式遍历DependencyObject的视觉树的方法。
///
- /// The
- /// The
- /// The
- private static DependencyObject GetParent(DependencyObject element, bool recurseIntoPopup)
+ /// 需要遍历的DependencyObject节点。
+ /// 返回一个包含视觉树中所有DependencyObject的迭代器。
+ /// 当提供的DependencyObject为null时,抛出此异常。
+ public static IEnumerable VisualDepthFirstTraversal(this DependencyObject node)
{
- if (recurseIntoPopup)
+ if (node == null)
{
- // Case 126732 : To correctly detect parent of a popup we must do that exception case
- var popup = element as Popup;
-
- if (popup != null && popup.PlacementTarget != null)
- return popup.PlacementTarget;
+ throw new ArgumentNullException(nameof(node));
}
- var visual = element as Visual;
- var parent = visual == null ? null : VisualTreeHelper.GetParent(visual);
+ yield return node;
- if (parent == null)
+ for (var i = 0; i < VisualTreeHelper.GetChildrenCount(node); i++)
{
- // No Visual parent. Check in the logical tree.
- var fe = element as FrameworkElement;
-
- if (fe != null)
+ DependencyObject child = VisualTreeHelper.GetChild(node, i);
+ foreach (DependencyObject descendant in child.VisualDepthFirstTraversal())
{
- parent = fe.Parent;
-
- if (parent == null) parent = fe.TemplatedParent;
- }
- else
- {
- var fce = element as FrameworkContentElement;
-
- if (fce != null)
- {
- parent = fce.Parent;
-
- if (parent == null) parent = fce.TemplatedParent;
- }
+ yield return descendant;
}
}
-
- return parent;
}
- #endregion
+ #endregion Methods
}
}
\ No newline at end of file