从 WPF 到 Avalonia 的迁移系列实战篇3:ResourceDictionary资源与样式的差异与迁移技巧

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目。
文中主要示例代码均可在仓库中查看,涵盖核心功能实现与优化方案。
点击链接即可直接访问,建议结合代码注释逐步调试。

在 WPF 开发中,我们习惯了用 ResourceDictionary 作为统一的资源容器,里面既可以放普通资源(画刷、字符串、模板),也可以放样式(Style)。
但是当你迁移到 Avalonia 时,会发现它把 资源样式 分成了两块:ResourcesStyles。这一点如果不注意,很容易踩坑。本文将结合learningAvalonia仓库的示例,详细对比一下两者的差异,并给出迁移技巧。


一、WPF 中的 ResourceDictionary

在 WPF 中,ResourceDictionary 是一个“万能容器”,里面可以存放一切资源,包括:

  • 普通资源(颜色、画刷、模板等)
  • 控件样式(Style

1. WPF资源字典的典型结构

以仓库中WPF项目的资源文件为例:

  • 颜色与字体资源(ColorAndFomts.xaml):定义了颜色、画笔、字体样式等基础资源
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:system="clr-namespace:System;assembly=System.Runtime"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><!--  定义颜色  --><Color x:Key="PrimaryColor">#FF4CAF50</Color><SolidColorBrush Color="{StaticResource PrimaryColor}" x:Key="PrimaryColorBrush" /><Color x:Key="SecondaryColor">#FFC107</Color><SolidColorBrush Color="{StaticResource SecondaryColor}" x:Key="SecondaryColorBrush" /><Color x:Key="AccentColor">#FFEB3B</Color><SolidColorBrush Color="{StaticResource AccentColor}" x:Key="AccentColorBrush" /><!--  定义字体  --><FontWeight x:Key="BoldFontWeight">Bold</FontWeight><system:Double x:Key="DefaultFontSize">30</system:Double></ResourceDictionary>
  • 样式资源(blinkingButtonStyle.xaml):定义了控件样式,与其他资源存储在同类型的ResourceDictionary
<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:control="clr-namespace:WpfDemo.control"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Style TargetType="{x:Type control:BlinkingButton}"><Setter Property="Background"><Setter.Value><LinearGradientBrush EndPoint="1,1" StartPoint="0,0"><GradientStop Color="#00C3FF" Offset="0" /><GradientStop Color="#FF61A6" Offset="1" /></LinearGradientBrush></Setter.Value></Setter><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 control:BlinkingButton}"><Border Background="{TemplateBinding Background}" CornerRadius="20"><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter></Style><!--  新增的 Button 样式  --><Style TargetType="{x:Type Button}" x:Key="RoundedButtonStyle"><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="20"><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter></Style></ResourceDictionary>

2. WPF中资源的合并与引用

<ApplicationStartupUri="MainWindow.xaml"x:Class="WpfDemo.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Themes/blinkingButtonStyle.xaml" /><ResourceDictionary Source="Themes/ColorAndFomts.xaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources>
</Application>

在界面中引用时,无论是基础资源还是样式,都通过{StaticResource}

<ButtonBackground="{StaticResource SecondaryColorBrush}"Content="我是一个圆角按钮"FontSize="{StaticResource DefaultFontSize}"FontWeight="{StaticResource BoldFontWeight}"Grid.Row="2"Height="80"HorizontalAlignment="Center"Style="{StaticResource RoundedButtonStyle}"VerticalAlignment="Center"Width="300" />

3. WPF资源管理的特点

  • 资源与样式混合存储:颜色、画笔、样式等所有资源都在ResourceDictionary根节点下,仅通过x:Key区分。
  • 样式即资源Style是一种特殊的资源,必须通过x:Key(或TargetType隐式Key)标识,引用方式与其他资源一致。
  • 缺乏结构区分:大型项目中资源字典可能包含成百上千个对象,混合存储会导致维护困难。

在这种模式下,WPF 查找资源的规则是:
控件本地 → 上级容器 → 窗口 → 应用程序 → 系统/主题。

所以,WPF 开发者习惯了把所有资源都丢到一个字典里。


二、Avalonia中的ResourceDictionary:资源与样式的分离设计

Avalonia作为WPF的跨平台继承者,在资源管理上进行了针对性优化。其核心变化是:ResourceDictionary明确划分为Resources(基础资源)和Styles(样式集合)两个独立区域,使资源结构更清晰。

1. Avalonia资源字典的典型结构

Avalonia的ResourceDictionary通过两个子节点分离资源类型:

  • <Resources>:存储非样式资源(颜色、画笔、字体、数据等),与WPF中的基础资源对应。
  • <Styles>:专门存储Style对象,支持通过Selector(选择器)更灵活地定位目标控件。

以仓库中Avalonia项目的资源文件为例:

  • 颜色与字体资源(ColorAndFomts.xaml):定义了颜色、画笔、字体样式等基础资源,依然使用ResourceDictionary
<ResourceDictionaryxmlns="https://github.com/avaloniaui"xmlns:system="clr-namespace:System;assembly=System.Runtime"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><!--  Add Resources Here  --><!--  定义颜色  --><Color x:Key="PrimaryColor">#FF4CAF50</Color><SolidColorBrush Color="{StaticResource PrimaryColor}" x:Key="PrimaryColorBrush" /><Color x:Key="SecondaryColor">#FFC107</Color><SolidColorBrush Color="{StaticResource SecondaryColor}" x:Key="SecondaryColorBrush" /><Color x:Key="AccentColor">#FFEB3B</Color><SolidColorBrush Color="{StaticResource AccentColor}" x:Key="AccentColorBrush" /><!--  定义字体  --><FontWeight x:Key="BoldFontWeight">Bold</FontWeight><system:Double x:Key="DefaultFontSize">30</system:Double>
</ResourceDictionary>

样式资源(blinkingButtonStyles.xaml):定义了控件样式,必须放在 Styles 节点下,不能混在 Resources 中。

<Stylesxmlns="https://github.com/avaloniaui"xmlns:local="clr-namespace:AvaloniaDemo.Controls"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Style Selector="local|BlinkingButton"><Setter Property="Background"><Setter.Value><LinearGradientBrush EndPoint="100%,100%" StartPoint="0%,0%"><GradientStop Color="#00C3FF" Offset="0" /><GradientStop Color="#FF61A6" Offset="1" /></LinearGradientBrush></Setter.Value></Setter><Setter Property="Foreground" Value="White" /><Setter Property="FontWeight" Value="Bold" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Padding" Value="12,6" /><Setter Property="Template"><ControlTemplate><Border Background="{TemplateBinding Background}" CornerRadius="20"><ContentPresenterContent="{TemplateBinding Content}"ContentTemplate="{TemplateBinding ContentTemplate}"Foreground="{TemplateBinding Foreground}"HorizontalAlignment="Center"VerticalAlignment="Center" /></Border></ControlTemplate></Setter></Style><!--  新增的 Button 样式  --><Style Selector="Button.rounded"><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="20"><ContentPresenterContent="{TemplateBinding Content}"HorizontalAlignment="Center"VerticalAlignment="Center" /></Border></ControlTemplate></Setter.Value></Setter></Style></Styles>

2. Avalonia中资源的合并与引用

Avalonia合并资源字典的方式与WPF类似,但内部会区分ResourcesStyles的合并:

<!-- AvaloniaDemo/App.axaml -->
<ApplicationRequestedThemeVariant="Default"x:Class="AvaloniaDemo.App"xmlns="https://github.com/avaloniaui"xmlns:local="using:AvaloniaDemo"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><!--  "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options.  --><Application.DataTemplates><local:ViewLocator /></Application.DataTemplates><!--  Styles:只能放 控件样式(Setter、ControlTemplate 等)  --><Application.Styles><FluentTheme /><StyleInclude Source="avares://AvaloniaDemo/Themes/BlinkingButtonStyles.axaml" /></Application.Styles><!--  Resources:只能放 非样式资源(Brush、字符串、数值等)。  --><Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceInclude Source="avares://AvaloniaDemo/Themes/ColorAndFonts.axaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources>
</Application>

引用时,基础资源仍通过{StaticResource},而样式可*使用 CSS-like 选择器,例如:

样式的特点

  • 必须放在 Styles 节点下,不能混在 Resources 中。

  • 使用 CSS-like 选择器,例如:

     <ButtonBackground="{StaticResource SecondaryColorBrush}"Classes="rounded"Content="我是一个圆角按钮"FontFamily="{StaticResource DefaultFontFamily}"FontSize="{StaticResource DefaultFontSize}"FontWeight="{StaticResource BoldFontWeight}"Grid.Row="2"Height="80"HorizontalAlignment="Center"VerticalAlignment="Center"Width="300" />
    

三、迁移时的对比总结

功能WPF (ResourceDictionary)Avalonia (Resources & Styles)
普通资源存放ResourceDictionaryResources
样式存放ResourceDictionaryStyles
样式语法基于 TargetType / BasedOn基于 CSS-like Selector
动态资源引用{DynamicResource}{DynamicResource}(不常用)
合并资源字典<ResourceDictionary.MergedDictionaries><StyleInclude> / <ResourceInclude>

四、迁移技巧

  1. 把样式移到 Styles

    • WPF 中写在 ResourceDictionary 里的 Style,要迁移到 Avalonia 的 <Styles> 中。
    <!-- WPF -->
    <ResourceDictionary><Style TargetType="Button"><Setter Property="Background" Value="Red"/></Style>
    </ResourceDictionary><!-- Avalonia -->
    <Styles><Style Selector="Button"><Setter Property="Background" Value="Red"/></Style>
    </Styles>
    
  2. 普通资源依旧放在 Resources
    画刷、模板、字符串等写在 <Resources> 中,然后用 {StaticResource}{DynamicResource} 引用。

  3. 合并资源字典

    • WPF:

      <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Dictionary1.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary>
      </Application.Resources>
      
    • Avalonia:

      <Application.Styles><FluentTheme Mode="Light"/><StyleInclude Source="avares://MyApp/Styles/Button.axaml"/>
      </Application.Styles>
      
  4. 利用 CSS-like Selector 提升可维护性
    Avalonia 的 :hover:checked 等伪类可以取代 WPF 的触发器,更直观。


五、结语

WPF 中的 ResourceDictionary 是一个“万能大容器”,而 Avalonia 则通过把 ResourcesStyles 分离,让资源管理更清晰,结构更接近 Web 开发思路。

如果你正在从 WPF 迁移到 Avalonia,建议你先把样式统一放到 <Styles>,资源放到 <Resources>,这样能避免很多“为什么样式不起作用”的坑。

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目。
文中主要示例代码均可在仓库中查看,涵盖核心功能实现与优化方案。
点击链接即可直接访问,建议结合代码注释逐步调试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97649.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97649.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97649.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot的音乐媒体播放及周边产品运营平台(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的音乐媒体播放及周边产品运营平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

【项目思维】嵌入式产业链与技术生态

这篇文章深入解析嵌入式产业链与技术生态上下游关系&#xff0c;辅助建立嵌入式工程师职业发展认知。嵌入式行业并不是“写单片机程序”那么简单&#xff0c;而是一个 从芯片设计到系统集成再到最终产品落地 的复杂生态链。理解上下游价值链&#xff0c;有助于你成为系统型工程…

机器学习(讲解)

一、引言&#xff1a;什么是监督学习&#xff1f;监督学习&#xff08;Supervised Learning&#xff09;是机器学习中最基础且应用最广泛的范式之一。其核心思想是利用已标记的数据&#xff08;即输入-输出对&#xff09;训练模型&#xff0c;使其能够对新的、未标记的数据进行…

使用 Bright Data Web Scraper API + Python 高效抓取 Glassdoor 数据:从配置到结构化输出全流程实战

使用 Bright Data Web Scraper API Python 高效抓取 Glassdoor 数据&#xff1a;从配置到结构化输出全流程实战 摘要 本文详细介绍了如何使用 Bright Data 的 Web Scraper API 搭配 Python&#xff0c;实现对 Glassdoor 平台信息的高效抓取。通过 API 请求构建器、反爬机制集成…

Burgan Bank Türkiye 如何借助 Elastic 改造可观测性和安全性

作者&#xff1a;来自 Elastic Jon Ashley, Ido Friedman, Burak Dz Burgan Bank Trkiye Burgan Bank K.P.S.C. 是科威特项目公司 (KIPCO) 集团的子公司&#xff0c;成立于 1977 年&#xff0c;是中东和北非 (MENA) 地区最大的控股集团和重要银行集团之一。 该银行作为客户的解…

LeetCode 165. 比较版本号 - 优雅Java解决方案

文章目录LeetCode 165. 比较版本号 - 优雅Java解决方案题目描述示例分析示例 1示例 2示例 3算法思路Java实现方案方案一&#xff1a;双指针法&#xff08;推荐&#xff09;方案二&#xff1a;优化的单次遍历法可视化执行过程示例&#xff1a;compareVersion("1.2", &…

基于Kubernetes StatefulSet的有状态微服务部署与持久化存储实践经验分享

基于Kubernetes StatefulSet的有状态微服务部署与持久化存储实践经验分享 在传统微服务架构中&#xff0c;大多数服务都是无状态的&#xff08;Stateless&#xff09;&#xff0c;可以通过 Deployment、ReplicaSet 等控制器实现水平自动扩缩容。但在生产环境中&#xff0c;仍有…

MySQL编程开发

变量系统变量&#xff1a;MySQL内置变量#查看所有系统变量show variables \G;#通过模糊查询筛选变量show variables like “%path%”;全局变量&#xff1a;在所有终端中都生效&#xff1b;会话变量&#xff1a;在当前会话&#xff08;本次登录&#xff09;&#xff1b;#可以通过…

20250830_Oracle 19c CDB+PDB(QMS)默认表空间、临时表空间、归档日志、闪回恢复区巡检手册

PDB 关业务,CDB 管底层;每天紧盯 PDB,必要时看 CDB。 一、CDB 与 PDB 的关系 Oracle 12c 以后引入 多租户架构(Multitenant),分成两类容器: 层级 名称 作用 存储内容 典型操作 CDB CDB$ROOT(容器数据库) 数据库实例的根容器 Oracle 元数据、系统表字典、公共用户、PDB…

什么是MIPS架构?RISC-V架构?有什么区别?【超详细初学者教程】

什么是MIPS架构&#xff1f;RISC-V架构&#xff1f;有什么区别&#xff1f;【超详细初学者教程】 关键词&#xff1a;MIPS架构&#xff0c;RISC-V架构&#xff0c;精简指令集RISC&#xff0c;嵌入式系统&#xff0c;CPU架构对比&#xff0c;指令集架构&#xff0c;开源处理器&…

IDEA Spring属性注解依赖注入的警告 Field injection is not recommended 异常解决方案

一、异常错误 在使用 IntelliJ IDEA 进行 Spring 开发时&#xff0c;当使用 Autowired 注解直接在字段上进行依赖注入时&#xff0c;IDE 会显示黄色警告&#xff1a; Field injection is not recommended这个警告出现在以下代码模式中&#xff1a; Service public class UserSe…

智能核心:机器人芯片的科技革新与未来挑战

在人工智能与机器人技术深度融合的今天&#xff0c;机器人芯片作为驱动智能机器的“大脑”&#xff0c;正成为科技竞争的战略制高点。这一微小却至关重要的硬件&#xff0c;决定了机器人的计算能力、响应速度与智能水平&#xff0c;是机器人从“自动化”迈向“自主化”的关键所…

经典扫雷游戏实现:从零构建HTML5扫雷游戏

一、引言 扫雷是一款经典的单人益智游戏&#xff0c;起源于20世纪60年代&#xff0c;并在90年代随着Windows操作系统的普及而风靡全球。本文将详细介绍如何使用现代网页技术&#xff08;HTML、CSS和JavaScript&#xff09;从零开始构建一个功能完整的扫雷游戏。我们将涵盖游戏逻…

ccache编译加速配置

ccache 介绍 ccache(“compiler cache”的缩写)是一个编译器缓存,该工具会高速缓存编译生成的信息,并在编译的特定部分使用高速缓存的信息, 比如头文件,这样就节省了通常使用 cpp 解析这些信息所需要的时间。 github :https://github.com/ccache/ccache home:https://c…

数据库主键选择策略分析

为什么不推荐使用数据库自增主键&#xff1f;分库分表问题&#xff1a;自增ID在分库分表场景下会导致ID冲突需要额外机制(如步长设置)来保证全局唯一&#xff0c;增加系统复杂度安全性问题&#xff1a;自增ID容易暴露业务量(如订单号连续)可能被恶意爬取数据分布式系统限制&…

线性代数理论——状态空间的相关概念以及由系统的输入输出导出状态空间描述

线性代数理论——状态空间 状态&#xff1a;动态系统的状态就是指系统的过去、现在、将来的运动状况&#xff0c;精确的说就是状态需要一组必要而充分的数据来表明。 状态变量&#xff1a;可以表达系统运动状态的变量都是状态变量。 状态变量组&#xff1a;可以完全表征系统在时…

【GaussDB】排查应用高可用切换出现数据库整体卡顿及报错自治事务无法创建的问题

【GaussDB】排查应用高可用切换出现数据库整体卡顿及报错自治事务无法创建的问题 背景 某客户在做应用程序的高可用切换测试&#xff0c;在应用程序中&#xff0c;收到了来自数据库的报错&#xff0c;不能创建自治事务 ERROR: autonomous transaction failed to create auton…

shell脚本第五阶段---shell函数与正则表达式

学习目标掌握case语句的基本语法结构掌握函数的定义以及调用掌握常用的正则表达式元字符含义一、case语句case语句为多选择语句。可以用case语句匹配一个值与一个模式&#xff0c;如果匹配成功&#xff0c;执行相匹配的命令。case var in 定义变量&#xff1b;var代表变量名…

164.在 Vue3 中使用 OpenLayers 加载 Esri 地图(多种形式)

适配&#xff1a;Vue 3 Vite TypeScript&#xff08;也兼容 JS&#xff09; 地图引擎&#xff1a;OpenLayers v10 目标&#xff1a;一次性学会 多种 Esri 底图加载方式、注记叠加、动态切换、令牌&#xff08;Token&#xff09;鉴权、常见坑位排查。一、效果预览二、为什么选…

深入了解Flink核心:Slot资源管理机制

TaskExecutor、Task 和 Slot 简单来说&#xff0c;它们的关系可以比作&#xff1a;TaskExecutor&#xff1a;一个工厂&#xff0c;拥有固定的生产资源。TaskSlot&#xff1a;工厂里的一个工位。每个工位都预先分配了一份独立的资源&#xff08;主要是内存&#xff09;。Task&am…