当前位置: 首页 > news >正文

从 WPF 到 Avalonia 的迁移系列实战篇6:ControlTheme 和 Style区别

从 WPF 到 Avalonia 的迁移系列实战篇6:ControlTheme 和 Style区别

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目。

前言

在之前的文章中,我们介绍了 Avalonia 的基础样式系统。本文将结合实际示例,展示 Avalonia 11 新引入的 ControlTheme 与传统 Style 的区别,帮助大家更直观地理解两者的适用场景。


ControlTheme 与 Style 的差异回顾

  • ControlTheme

    • 定义控件外观主题。
    • 通过 Theme 属性应用到控件。
    • 支持 BasedOn 继承,可重用。
    • 一次只能应用一个主题(互斥)。
  • Style

    • 通过选择器和 Classes 应用。
    • 不支持 BasedOn,容易重复代码。
    • 可以叠加多个样式(更灵活)。

实战对比示例

我们通过定义 两种按钮样式(白字按钮 和 黑字按钮) 来对比 ControlTheme 与 Style 的使用效果。

使用 ControlTheme

<ControlTheme TargetType="{x:Type Button}" x:Key="WhiteForegroundButtonStyle"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="White" /><Setter Property="FontWeight" Value="Bold" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Padding" Value="12,6" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Border Background="{TemplateBinding Background}" CornerRadius="0"><ContentPresenterContent="{TemplateBinding Content}"HorizontalAlignment="Center"VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter><Style Selector="^:pointerover"><Setter Property="Foreground" Value="DodgerBlue" /></Style>
</ControlTheme><ControlThemeBasedOn="{StaticResource WhiteForegroundButtonStyle}"TargetType="{x:Type Button}"x:Key="BlackForegroundButtonStyle"><Setter Property="Foreground" Value="Black" />
</ControlTheme>
使用方式
<Button Theme="{StaticResource WhiteForegroundButtonStyle}">白字按钮</Button>
<Button Theme="{StaticResource BlackForegroundButtonStyle}">黑字按钮</Button>

👉 优点:

  • 只需定义一次基础主题,通过 BasedOn 即可派生新主题。
  • 适合 可切换的控件外观,比如深色/浅色主题按钮。

使用 Style

<Style Selector="Button.squareWhiteForeground"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="White" /><Setter Property="FontWeight" Value="Bold" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Padding" Value="12,6" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Border Background="{TemplateBinding Background}" CornerRadius="0"><ContentPresenterContent="{TemplateBinding Content}"HorizontalAlignment="Center"VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter>
</Style>
<Style Selector="Button.squareWhiteForeground:pointerover"><Setter Property="Foreground" Value="DodgerBlue" />
</Style><Style Selector="Button.squareBlackForeground"><Setter Property="Background" Value="LightBlue" /><Setter Property="Foreground" Value="Black" /><Setter Property="FontWeight" Value="Bold" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Padding" Value="12,6" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Border Background="{TemplateBinding Background}" CornerRadius="0"><ContentPresenterContent="{TemplateBinding Content}"HorizontalAlignment="Center"VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter>
</Style>
<Style Selector="Button.squareBlackForeground:pointerover"><Setter Property="Foreground" Value="DodgerBlue" />
</Style>
使用方式
<Button Classes="squareWhiteForeground">白字按钮</Button>
<Button Classes="squareBlackForeground">黑字按钮</Button>

👉 缺点:

  • 黑白两套样式几乎完全重复,无法 BasedOn 继承。
  • 如果需要维护多个按钮风格,样式代码会迅速膨胀。

对比总结

特性StyleControlTheme
目标通过 Selector(选择器)匹配控件通过 TargetType 明确目标控件类型
应用方式控件通过 Class 或 Selector 应用控件通过 Theme 属性应用(替换而不是叠加)
存储位置通常放在 <Styles>通常放在 ResourceDictionary
继承支持不支持 BasedOn支持 BasedOn
多主题支持需手动切换样式集合支持 ThemeVariant,可全局或局部切换 Light/Dark 等

控件主题的查找规则

Avalonia 查找 ControlTheme 的方式有两种:

  1. 如果控件的 Theme 属性被设置,则优先使用该主题;
  2. 否则,Avalonia 会沿逻辑树向上搜索 ControlTheme,查找一个 x:Key 与控件样式键匹配的资源。

两种定义方式

  • 如果希望主题应用于所有实例:

    <ControlTheme x:Key="{x:Type Button}" TargetType="Button">...
    </ControlTheme>
    
  • 如果只想应用于特定实例:

    <ControlTheme x:Key="EllipseButton" TargetType="Button">...
    </ControlTheme>
    

    然后在控件上显式设置 Theme="{StaticResource EllipseButton}"


迁移建议(WPF → Avalonia)

在 WPF 中:

  • 控件外观通过 Style + ControlTemplate 定义;
  • 没有 ThemeDictionary 概念,Light/Dark 主题需要手动维护多份 ResourceDictionary
  • 样式支持 BasedOn,可以复用。

在 Avalonia 中:

  • 默认主题可以通过 ControlTheme 定义在资源字典中;
  • 支持 ThemeVariant,原生支持 Light/Dark 切换;
  • ControlTheme 支持 BasedOn,比普通样式更适合做主题继承;
  • 普通 Style 没有 BasedOn,更多依赖 Classes + Selector。
  • 如果是 控件主题(可切换外观) → 使用 ControlTheme
  • 如果是 局部样式修饰/条件状态 → 使用 Style

总结

本篇我们通过 白字按钮 vs 黑字按钮 的 Demo,直观对比了 ControlTheme 与 Style 的核心区别

  • Style 更适合定义局部样式,通过 Selector 和 Class 应用。
  • ControlTheme 更适合定义可替换的控件外观(尤其是模板控件),支持 ThemeVariantBasedOn,便于多主题切换。
  • WPF 迁移到 Avalonia 时,可以将 generic.xaml 中的默认样式迁移为 ControlTheme,并利用 ThemeVariant 来实现 Light/Dark 主题支持。

这样既能保留 WPF 开发的经验,又能充分利用 Avalonia 11 带来的新特性。

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目。

http://www.dtcms.com/a/362893.html

相关文章:

  • R 语言科研绘图第 71 期 --- 散点图-边际
  • 小白也能看懂!“找不到 msvcp140.dll无法继续执行代码” 的6种简易解决方法,5 分钟快速修复
  • Watt Toolkit下载安装并加速GitHub
  • C# 原型模式(C#中的克隆)
  • 基因表达数据的K-M生存曲线的数据处理及绘制
  • Anaconda安装与使用详细教程
  • 服务器CPU飙高?排查步骤与工具推荐
  • 深入探索 HarmonyOS Stage 模型与 ArkUI:构建现代化、高性能应用
  • 【NestJS】HTTP 接口传参的 5 种方式(含前端调用与后端接收)
  • 面试新纪元:无声胜有声,让AI成为你颈上的智慧伙伴
  • 基于YOLO8的番茄成熟度检测系统(数据集+源码+文章)
  • 利用飞算Java打造电商系统核心功能模块的设计与实现
  • Controller返回CompletableFuture到底是怎么样的
  • 【DSP28335 入门教程】定时器中断:为你的系统注入精准的“心跳”
  • 在windows平台oracle 23ai 数据库上使用bbed
  • zephyr设备树的硬件描述转换为c语言
  • 梳理一下 @types/xxx
  • 【Python语法基础学习笔记】竞赛常用标准库
  • 数据库的锁级别
  • Git在idea中的实战使用经验(一)
  • 深度学习之第五课卷积神经网络 (CNN)如何训练自己的数据集(食物分类)
  • SQLShift 实现Oracle 到 OceanBase 的存储过程转换初体验
  • FlowGPT-GPT提示词分享平台
  • 深入剖析Java设计模式之策略模式:从理论到实战
  • 【音视频】 WebRTC GCC 拥塞控制算法
  • 从Java全栈到前端框架:一场真实的技术面试实录
  • Leetcode二分查找(5)
  • 【算法】哈希表专题
  • 单元测试总结2
  • 【大前端】Vue 和 React 主要区别