【笔记】在WPF中Decorator是什么以及何时优先考虑 Decorator 派生类

一、Decorator 是什么

  • 定义:Decorator 是一个只包含"单个子元素"的轻量级布局基类,用于在不改变子元素类型的前提下,为其增加额外外观或布局行为(如边框、内边距、缩放、装饰层等)。
  • 特点:
    • 仅一个子元素(Child)。
    • 常用于控件模板或项模板中精简视觉树与成本。
    • 常见派生类:Border、Viewbox、BulletDecorator、AdornerDecorator。

二、常见派生类与典型功能

  • Border:为单个子元素提供背景、边框、圆角和 Padding。
  • Viewbox:对单个子元素进行整体缩放(Uniform/Fill/UniformToFill)。
  • BulletDecorator:在一行内排布"子弹元素(Bullet)+ 内容元素(Child)",常见于 CheckBox/RadioButton 模板。
  • AdornerDecorator:在可视树中插入一个 AdornerLayer,便于在其子树上的元素之上绘制装饰(验证标记、拖拽手柄、选择框等)。

三、使用方式(Active Document)

  • 在当前文件演示 Border/Viewbox/BulletDecorator/AdornerDecorator 的典型用法
xml 复制代码
<UserControl x:Class="H.Test.DataGrid.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel Margin="12" Orientation="Vertical" >
        <!-- Border:单子元素 + 背景/边框/圆角/内边距 -->
        <Border Background="#FFF7F9FC"
                BorderBrush="#FF6AA0E8"
                BorderThickness="1"
                CornerRadius="6"
                Padding="12">
            <TextBlock Text="使用 Border 包裹单个内容(圆角 + 内边距 + 边框)" TextWrapping="Wrap"/>
        </Border>

        <!-- Viewbox:整体缩放子内容 -->
        <Viewbox Stretch="Uniform" Height="80" Margin="0,8,0,0">
            <Grid Width="160" Height="40" Background="#FFEFF3FA">
                <TextBlock Text="会整体等比缩放" VerticalAlignment="Center" HorizontalAlignment="Center"/>
            </Grid>
        </Viewbox>

        <!-- BulletDecorator:子弹(图标) + 文本 -->
        <BulletDecorator Background="Transparent" Margin="0,8,0,0">
            <BulletDecorator.Bullet>
                <Ellipse Width="14" Height="14" Fill="#4090F0" Stroke="#2E6CB8"/>
            </BulletDecorator.Bullet>
            <TextBlock Text="图标 + 文本的轻量横排" Margin="8,0,0,0" VerticalAlignment="Center"/>
        </BulletDecorator>

        <!-- AdornerDecorator:为其子树提供 AdornerLayer -->
        <AdornerDecorator Margin="0,8,0,0">
            <Grid x:Name="AdornTarget" Width="220" Height="80" Background="#FFFDF7E7">
                <TextBlock Text="运行时给我加一个红色装饰框" VerticalAlignment="Center" HorizontalAlignment="Center"/>
            </Grid>
        </AdornerDecorator>
    </StackPanel>
</UserControl>
csharp 复制代码
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace H.Test.DataGrid
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();

            // 在 Loaded 后给 AdornTarget 加一层简单的矩形 Adorner
            Loaded += (_, __) =>
            {
                var layer = AdornerLayer.GetAdornerLayer(AdornTarget);
                if (layer != null)
                {
                    layer.Add(new SimpleRectAdorner(AdornTarget));
                }
            };
        }
    }

    // 一个最小 Adorner:在目标元素边界上绘制红色虚线框
    internal sealed class SimpleRectAdorner : Adorner
    {
        public SimpleRectAdorner(UIElement adornedElement) : base(adornedElement) { }

        protected override void OnRender(DrawingContext dc)
        {
            var rect = new Rect(this.AdornedElement.RenderSize);
            var pen = new Pen(Brushes.Red, 1) { DashStyle = DashStyles.Dash };
            dc.DrawRectangle(null, pen, rect);
        }
    }
}

四、何时优先考虑 Decorator 派生类

  • 只有一个子元素,且需要附加外观或行为:优先用 Border/Viewbox/BulletDecorator 等,避免为单子元素使用通用 Panel,能减小视觉树、降低测量/排列成本。
  • 需要在元素上方绘制装饰层:用 AdornerDecorator 包起需要被装饰的区域。

五、文档链接

了解更多

System.Windows.Controls 命名空间 | Microsoft Learn

控件库 - WPF .NET Framework | Microsoft Learn

WPF 介绍 | Microsoft Learn

使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn

https://github.com/HeBianGu

HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频

GitHub - HeBianGu/WPF-Control: WPF轻量控件和皮肤库

GitHub - HeBianGu/WPF-ControlBase: Wpf封装的自定义控件资源库

相关推荐
箓维4 小时前
TCP Socket的进阶实现
网络·笔记·tcp/ip
二哈赛车手4 小时前
新人笔记---hermes定时功能设计,具体讲解以及可优化点
java·人工智能·笔记·spring·ai·typescript
星恒随风5 小时前
Linux网络编程:应用层协议究竟是什么?从网络计算器到TCP Socket抽象基类完整实现
linux·网络·笔记·tcp/ip
智学AI7 小时前
AI博主写作素材管理方法分享:资料归集、笔记关联与文档归档
人工智能·笔记
叼烟扛炮7 小时前
[LangChain] 学习笔记(02):LCEL 链式调用与动态模型配置实战
服务器·开发语言·网络·笔记·学习·langchain
weixin_448119947 小时前
Datawhale Jev Cookbook 202610 笔记5
笔记
一木 之林8 小时前
Dify学习笔记 04 · 检索底座:Embedding、Rerank与向量数据库(第46-54集)
笔记·学习·embedding·dify
ljt27249606618 小时前
Python笔记(十一)--Numpy(一)
笔记·python·numpy
芯思路8 小时前
STM32开发学习笔记之十【AI部署】
笔记·stm32·学习
江屿风9 小时前
【Plain Language Large Model】【从浏览器到全栈:一课精通Node.js三剑客】流食般投喂
笔记·前端框架·npm·node.js·js·npx