using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; public static class AdornerHelper { /// /// 为一个控件的模板“根”元素外围包装一个装饰层 /// /// 要进行包装的控件 /// 是否包装成功 public static bool WrapDecorator_To_TemplateRoot(this Control control) { // 如果控件为空或控件模板为空则退出 if (control == null || control.Template == null) return false; // 如果这个控件本身有装饰层则不需要再进行包装处理 if (AdornerLayer.GetAdornerLayer(control) != null) return true; // 应用模板(如果尚未应用) if (control.Template != null && control.IsInitialized) control.ApplyTemplate(); // 获取模板的根视觉元素 DependencyObject child = VisualTreeHelper.GetChild(control, 0); FrameworkElement? templateRoot = child as FrameworkElement; if (templateRoot == null) return false; // 获取模板根元素的父元素 DependencyObject parent = VisualTreeHelper.GetParent(templateRoot); if (parent == null) return false; // 1. 创建新的 AdornerDecorator AdornerDecorator decorator = new AdornerDecorator(); // 2. 从原父元素中移除原根元素 if (parent is Panel panel) { int childIndex = panel.Children.IndexOf(templateRoot); panel.Children.RemoveAt(childIndex); // 3. 将原根元素添加到 AdornerDecorator 的 Child 中 decorator.Child = templateRoot; // 4. 将 AdornerDecorator 添加回原父元素的相同位置 panel.Children.Insert(childIndex, decorator); return true; } else if (parent is Decorator decoratorParent) { // 如果父元素是 Decorator(如 Border) decoratorParent.Child = null; decorator.Child = templateRoot; decoratorParent.Child = decorator; return true; } else if (parent is ContentControl contentControl) { // 如果父元素是 ContentControl contentControl.Content = null; decorator.Child = templateRoot; contentControl.Content = decorator; return true; } // 其他类型的父元素可能需要特殊处理 return false; } /// /// 为一个FrameworkElemelt对象外围包裹一个包装器 /// /// 要包装的对象 /// 是否包装成功 public static bool WrapDecorator_To_UIElement(this UIElement element) { if (element == null) return false; // 如果这个控件本身有装饰层则不需要再进行包装处理 if (AdornerLayer.GetAdornerLayer(element) != null) return true; // 获取模板根元素的父元素 DependencyObject parent = VisualTreeHelper.GetParent(element); if (parent == null) return false; // 1. 创建新的 AdornerDecorator AdornerDecorator decorator = new AdornerDecorator(); // 2. 从原父元素中移除原根元素 if (parent is Panel panel) { int childIndex = panel.Children.IndexOf(element); panel.Children.RemoveAt(childIndex); // 3. 将原根元素添加到 AdornerDecorator 的 Child 中 decorator.Child = element; // 4. 将 AdornerDecorator 添加回原父元素的相同位置 panel.Children.Insert(childIndex, decorator); return true; } else if (parent is Decorator decoratorParent) { // 如果父元素是 Decorator(如 Border) decoratorParent.Child = null; decorator.Child = element; decoratorParent.Child = decorator; return true; } else if (parent is ContentControl contentControl) { // 如果父元素是 ContentControl contentControl.Content = null; decorator.Child = element; contentControl.Content = decorator; return true; } // 其他类型的父元素可能需要特殊处理 return false; } /// /// 在可视化树中查找指定类型的祖先元素,支持指定层级 /// /// 要查找的祖先元素类型 /// 起始子元素 /// 要查找的祖先层级(1=父级,2=祖父级等) /// 找到的祖先元素,若未找到则返回null public static T? FindAncestor(this DependencyObject @object, int level = 1) where T : DependencyObject { if (@object == null || level < 1) return null; DependencyObject parent = @object; int currentLevel = 0; while (parent != null && currentLevel < level) { parent = VisualTreeHelper.GetParent(parent); if (parent is T foundParent) { // 每次找到一个约定类型的袓辈节点计数需要加1 currentLevel++; if (currentLevel == level) return foundParent; } } return null; } /// /// 查找祖辈的装饰层,并根据尺寸偏差决定是否要返回(若祖辈装饰器尺寸过大可能不适用) /// /// 要查找的对象 /// 绝对偏差,像素偏差;必须大于等于0 /// 相对偏差,百分比偏差;必须大于等于1 /// 是否两者都需要满足?「null」表示不需要考虑祖辈装饰器的尺寸与自身尺寸的差异 /// 苦找不到则返回null public static AdornerLayer? GetAncestorAdornerLayer(this Visual visual, double absoluteDeviation = 0, double relativeDeviation = 1, bool? isAllSizeDiffToBeMeet = null) { absoluteDeviation = absoluteDeviation < 0 ? 0 : absoluteDeviation; // 限制绝对偏差不能小于0; relativeDeviation = relativeDeviation < 1 ? 1 : relativeDeviation; // 限制相对偏差不能小于1; var adornerLayer = AdornerLayer.GetAdornerLayer(visual); if (adornerLayer == null) adornerLayer = AdornerLayer.GetAdornerLayer(visual.FindAncestor()); if (adornerLayer != null) { if (isAllSizeDiffToBeMeet == null) return adornerLayer; else { if (visual is FrameworkElement element) { bool ad = (adornerLayer.ActualHeight - element.ActualHeight) <= absoluteDeviation & (adornerLayer.ActualWidth - element.ActualWidth) <= absoluteDeviation; bool rd = (adornerLayer.ActualHeight <= element.ActualHeight * relativeDeviation & adornerLayer.ActualWidth <= element.ActualWidth * relativeDeviation); if (isAllSizeDiffToBeMeet == true) { if (ad & rd) return adornerLayer; } else { if (ad | rd) return adornerLayer; } } } } return null; } /// /// 尝试所有可能的方法去获取一个可视元素的装饰器 /// /// 要获取装饰器的可视元素 /// 如果找不到则返回空 public static AdornerLayer? TryGetAdornerLayerExhaustively(this Visual visual) { var adornerLayer = AdornerLayer.GetAdornerLayer(visual); if (adornerLayer != null) return adornerLayer; // 获取祖辈装饰器,要求尺寸偏差不能超过4个像素;即,四个边均可留有2个像素的边 adornerLayer = visual.GetAncestorAdornerLayer(4, 1, false); if (adornerLayer != null) return adornerLayer; if (visual is Control control) { control.WrapDecorator_To_TemplateRoot(); adornerLayer = AdornerLayer.GetAdornerLayer(control); if (adornerLayer != null) return adornerLayer; } else if (visual is UIElement element) { element.WrapDecorator_To_UIElement(); adornerLayer = AdornerLayer.GetAdornerLayer(element); if (adornerLayer != null) return adornerLayer; } else return null; return null; } }