mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 15:19:12 +08:00
12 KiB
12 KiB
主题文件结构规范
本文档规定 AtomUI 控件的 Theme 文件夹布局、ControlTheme AXAML 结构、以及 Theme 注册方式。
1. 文件夹结构
每个 Platform 层控件的 Theme 文件遵循以下标准目录结构:
AtomUI.Desktop.Controls/
└── ControlName/
├── ControlName.cs # 具体控件类
├── ControlNameToken.cs # 组件 Token 定义
└── Themes/
├── ControlNameTheme.axaml # ControlTheme AXAML 模板
├── ControlNameTheme.cs # Theme 代码后台
└── ControlNameThemes.axaml # ResourceDictionary 注册
实际示例 —— Button:
Buttons/
├── Button.cs
├── ButtonToken.cs
├── IconButton.cs
├── DropdownButton.cs
└── Themes/
├── ButtonTheme.axaml
├── ButtonTheme.cs
├── ButtonThemes.axaml
├── DropdownButtonTheme.axaml
├── DropdownButtonTheme.cs
├── IconButtonTheme.axaml
├── IconButtonTheme.cs
└── ...
实际示例 —— Tag:
Tag/
├── Tag.cs
├── TagToken.cs
└── Themes/
├── TagTheme.axaml
├── TagTheme.cs
└── TagThemes.axaml
2. ControlTheme AXAML(ControlNameTheme.axaml)
2.1 基本结构
<ControlTheme xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
xmlns:antdicons="https://atomui.net/icons/antdesign"
x:ClassModifier="internal"
x:Class="AtomUI.Desktop.Controls.Themes.TagTheme"
TargetType="atom:Tag">
<!-- 模板定义 -->
<Setter Property="Template">
<ControlTemplate TargetType="atom:Tag">
<!-- 控件可视化树 -->
</ControlTemplate>
</Setter>
<!-- 样式定义 -->
<Style Selector="^:is(atom|Tag)">
<Setter Property="Background" Value="{atom:TagTokenResource DefaultBg}" />
<!-- ... -->
</Style>
</ControlTheme>
2.2 强制规则
| 规则 | 说明 |
|---|---|
xmlns:atom="https://atomui.net" |
AtomUI 控件命名空间,必须 使用 atom: 前缀 |
xmlns:antdicons="https://atomui.net/icons/antdesign" |
图标命名空间(如果使用图标) |
x:Class 指向代码后台 |
AtomUI.Desktop.Controls.Themes.XxxTheme |
TargetType 使用 atom:Xxx |
指向 AtomUI 的具体控件类型 |
| 禁止 硬编码颜色、尺寸、画刷 | 必须使用 Token 资源引用 |
模板部件使用 PART_ 前缀命名 |
如 Name="PART_WaveSpirit" |
2.3 Token 资源引用
在 AXAML 中引用 Token 的两种方式:
<!-- 组件 Token:使用组件专属标记扩展 -->
<Setter Property="Background" Value="{atom:TagTokenResource DefaultBg}" />
<Setter Property="Foreground" Value="{atom:TagTokenResource DefaultColor}" />
<Setter Property="FontSize" Value="{atom:TagTokenResource TagFontSize}" />
<Setter Property="Padding" Value="{atom:TagTokenResource TagPadding}" />
<!-- 全局共享 Token:使用 SharedTokenResource -->
<Setter Property="BorderBrush" Value="{atom:SharedTokenResource ColorBorder}" />
<Setter Property="CornerRadius" Value="{atom:SharedTokenResource BorderRadiusSM}" />
<Setter Property="BorderThickness" Value="{atom:SharedTokenResource BorderThickness}" />
2.4 模板部件命名
模板部件的 Name 属性 必须 使用 PART_ 前缀的字符串:
<atom:WaveSpiritDecorator Name="PART_WaveSpirit" />
<ContentPresenter Name="PART_ContentPresenter" />
2.5 样式选择器语法
使用 ^:is(atom|ControlName) 选择器语法实现样式继承:
<!-- 基础样式 -->
<Style Selector="^:is(atom|Tag)">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Background" Value="{atom:TagTokenResource DefaultBg}" />
</Style>
<!-- 伪类样式 -->
<Style Selector="^:is(atom|Tag)">
<Style Selector="^:custom-color">
<Setter Property="Foreground" Value="{atom:SharedTokenResource ColorTextLightSolid}" />
</Style>
<Style Selector="^:pointerover">
<Setter Property="Background" Value="{atom:TokenResource HoverBg}" />
</Style>
</Style>
<!-- 属性值匹配 -->
<Style Selector="^[ButtonType=Default], ^[ButtonType=Link]">
<Setter Property="Template">
<!-- ... -->
</Setter>
</Style>
2.6 TemplateBinding 使用
在 ControlTemplate 内部,使用 TemplateBinding 绑定控件属性:
<ControlTemplate TargetType="atom:Tag">
<Panel>
<Border Name="Frame"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="{TemplateBinding CornerRadius}"
BorderThickness="{TemplateBinding BorderThickness}" />
<DockPanel Margin="{TemplateBinding Padding}">
<atom:IconPresenter Icon="{TemplateBinding Icon}" />
<atom:TextBlock Text="{TemplateBinding TagText}" />
</DockPanel>
</Panel>
</ControlTemplate>
2.7 完整示例
以下是 TagTheme.axaml 的核心结构:
<ControlTheme xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
x:ClassModifier="internal"
x:Class="AtomUI.Desktop.Controls.Themes.TagTheme"
TargetType="atom:Tag">
<Setter Property="Template">
<ControlTemplate TargetType="atom:Tag">
<Panel>
<Border Name="Frame"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="{TemplateBinding CornerRadius}"
BorderThickness="{TemplateBinding BorderThickness}" />
<DockPanel LastChildFill="True" Margin="{TemplateBinding Padding}">
<atom:IconPresenter Name="IconPresenter"
DockPanel.Dock="Left"
Icon="{TemplateBinding Icon}" />
<atom:IconButton Name="PART_CloseButton"
DockPanel.Dock="Right"
IsVisible="{TemplateBinding IsClosable}"
Icon="{TemplateBinding CloseIcon}" />
<atom:TextBlock Name="TagTextLabel"
Text="{TemplateBinding TagText}"
Padding="{TemplateBinding TagTextPaddingInline}" />
</DockPanel>
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^:is(atom|Tag)">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Background" Value="{atom:TagTokenResource DefaultBg}" />
<Setter Property="Foreground" Value="{atom:TagTokenResource DefaultColor}" />
<Setter Property="FontSize" Value="{atom:TagTokenResource TagFontSize}" />
<Setter Property="Padding" Value="{atom:TagTokenResource TagPadding}" />
<Setter Property="BorderBrush" Value="{atom:SharedTokenResource ColorBorder}" />
<Setter Property="CornerRadius" Value="{atom:SharedTokenResource BorderRadiusSM}" />
<Style Selector="^:custom-color">
<Setter Property="Foreground"
Value="{atom:SharedTokenResource ColorTextLightSolid}" />
</Style>
</Style>
</ControlTheme>
3. Theme 代码后台(ControlNameTheme.cs)
3.1 最简形式
using Avalonia.Styling;
namespace AtomUI.Desktop.Controls.Themes;
internal class TagTheme : ControlTheme
{
}
3.2 包含静态资源的形式
当 Theme 需要提供转换器或其他静态资源时:
using AtomUI.Controls.Converters;
using Avalonia.Styling;
namespace AtomUI.Desktop.Controls.Themes;
public class ButtonTheme : ControlTheme
{
public static readonly ButtonIconVisibleConverter IconVisibleConverter = new();
public static IList<double> DashedStyle = [4, 2];
}
3.3 规则
| 规则 | 说明 |
|---|---|
继承 ControlTheme(来自 Avalonia.Styling) |
Avalonia 的主题基类 |
命名空间 AtomUI.Desktop.Controls.Themes |
所有 Theme 代码后台使用此命名空间 |
| 访问修饰符视需要而定 | 如果 AXAML 中 x:ClassModifier="internal" 则为 internal;如果 AXAML 中引用了静态成员则可为 public |
4. Theme 注册(ControlNameThemes.axaml)
5.1 基本结构
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
x:ClassModifier="internal">
<atom:TagTheme x:Key="{x:Type atom:Tag}" TargetType="atom:Tag"/>
</ResourceDictionary>
5.2 带合并字典的形式
当一个控件组包含多个子控件 Theme 时:
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
x:ClassModifier="internal">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="SplitButtonTheme.axaml"/>
<ResourceInclude Source="HyperLinkButtonTheme.axaml"/>
</ResourceDictionary.MergedDictionaries>
<atom:ButtonTheme x:Key="{x:Type atom:Button}" TargetType="atom:Button"/>
<atom:DropdownButtonTheme x:Key="{x:Type atom:DropdownButton}" TargetType="atom:DropdownButton"/>
<atom:IconButtonTheme x:Key="{x:Type atom:IconButton}" TargetType="atom:IconButton"/>
</ResourceDictionary>
5.3 规则
| 规则 | 说明 |
|---|---|
x:Key="{x:Type atom:Xxx}" |
使用 x:Type 将 Theme 与控件类型关联 |
TargetType="atom:Xxx" |
指定目标控件类型 |
同一组控件的 Theme 可合并到一个 Themes.axaml |
如 Button 组 |
x:ClassModifier="internal" |
资源字典为内部可见 |
5. Theme 注册到 Provider
所有控件的 Theme 最终需要在 DesktopControlThemesProvider 中注册。这通过 ThemeManagerBuilderExtensions 的 UseDesktopControls() 扩展方法完成。
新增控件时,需要将 ControlNameThemes.axaml 添加到 Provider 的资源列表中。
6. 常见 AXAML 模式
6.1 WaveSpiritDecorator 集成
<Panel>
<atom:WaveSpiritDecorator
Name="PART_WaveSpirit"
CornerRadius="{TemplateBinding EffectiveCornerRadius}"
WaveType="{TemplateBinding WaveSpiritType}" />
<!-- 控件主体 -->
<Border Name="Frame" ... />
</Panel>
6.2 图标显示
<atom:IconPresenter
Name="PART_ButtonIcon"
Icon="{TemplateBinding Icon}"
DockPanel.Dock="Left" />
6.3 尺寸变体样式
<Style Selector="^:is(atom|Button)">
<!-- 默认 Middle 尺寸 -->
<Setter Property="Padding" Value="{atom:ButtonTokenResource Padding}" />
<Setter Property="FontSize" Value="{atom:ButtonTokenResource ContentFontSize}" />
<Style Selector="^[SizeType=Small]">
<Setter Property="Padding" Value="{atom:ButtonTokenResource PaddingSM}" />
<Setter Property="FontSize" Value="{atom:ButtonTokenResource ContentFontSizeSM}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Setter Property="Padding" Value="{atom:ButtonTokenResource PaddingLG}" />
<Setter Property="FontSize" Value="{atom:ButtonTokenResource ContentFontSizeLG}" />
</Style>
</Style>
6.4 焦点视觉
<Border Name="FocusVisual"
IsVisible="False"
IsHitTestVisible="False"
BorderThickness="{atom:SharedTokenResource FocusVisualBorderThickness}"
BorderBrush="{atom:SharedTokenResource ColorFocusBorder}"
CornerRadius="{TemplateBinding EffectiveCornerRadius}" />
7. 禁止事项
| 禁止事项 | 原因 |
|---|---|
❌ AXAML 中硬编码 Color、Thickness、FontSize 等值 |
必须使用 Token 资源引用 |
❌ 模板部件 Name 不使用 PART_ 前缀 |
必须遵循 Avalonia 模板部件命名约定 |
❌ 遗漏 Themes.axaml 注册 |
控件无法找到 Theme |
❌ Theme 文件放在 Themes/ 目录之外 |
违反标准目录结构 |
❌ 在 AXAML 中使用 Avalonia 原生控件命名空间替代 atom: |
应使用 atom: 前缀引用 AtomUI 控件 |