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