首页 > 其他分享 >Avalonia UI 中 Styles 与 ControlTheme 的区别

Avalonia UI 中 Styles 与 ControlTheme 的区别

时间:2024-04-25 15:47:24浏览次数:44  
标签:Styles 控件 Style 样式 ControlTheme Theme UI

目录

介绍

在 Avalonia UI 中有几种概念 Theme Style ControlTheme,从WPF转过来的时候对于 ControlTheme 跟 Theme 的区别是什么呢? 为什么Style跟我们的WPF的Style的效果不太一样? Trigger 也没了?

首选需要说的是, ThemeStyleControlTheme 都是继承自 IStyle 也就是说他们都是 样式(Style), 但是他们之间有一些差异.

这里介绍一下我个人如何理解这三种 IStyle

  1. Theme 暂且理解为 全局主题(Global Theme)
  2. Style 暂且理解为 局部主题(Local Theme)
  3. ControlTheme 暂且理解为 控件样式 (Control Style, 类似WPF中定义控件Style以及Template)

使用方式

全局主题 (Global Theme)

// App.xaml
<Application xmlns="https://github.com/avaloniaui"
             RequestedThemeVariant="Default">
             <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
    <Application.Styles>
        <FluentTheme />     // 这里的Theme 其实也是Style
    </Application.Styles>
</Application>

局部主题 (Local Theme)

如果将 Style 方式在 Window或者UserControl或者Control下即为局部主题

<Window>
    <Window.Styles>
        <!-- Common button properties -->
        <Style Selector="Button">
            <Setter Property="Margin" Value="10" />
            <Setter Property="MinWidth" Value="200" />
            <Setter Property="Height" Value="50" />
			<Setter Property="HorizontalContentAlignment" Value="Right" />
			<Setter Property="VerticalContentAlignment" Value="Bottom" />
			<Style Selector="^:pointerover /template/ ContentPresenter">
				<Setter Property="Background" Value="Green" />
			</Style>
        </Style>
    </Window.Styles>

    // ...
</Window>

控件主题 (ControlTheme)

注意: 这里的 ControlTheme 是放置在 Window.Resource

<Window.Resource>
    <ControlTheme x:Key="{x:Type Button}" TargetType="Button">
        <Setter Property="Background" Value="#C3C3C3" />
        <Setter Property="FontFamily" Value="Arial" />
        <Setter Property="FontSize" Value="14" />
        <Setter Property="Height" Value="100" />
        <Setter Property="Template">
            <ControlTemplate>
                // ... 
            </ControlTemplate>
        </Setter>
        <Style Selector="^:pointerover">
            <Setter Property="Background" Value="red" />
        </Style>
    </ControlTheme>
</Window.Resource>

问题描述

从使用方式上看 Global ThemeLocal Theme 是一样的, 都是放置在 Styles 属性下. 问题的关键是:

  1. Styles 下的 ThemeResource下的ControlTheme有什么区别?

  2. StylesControlTheme 同样可以重写 Template, 那我要选哪个来重写 Template?

问题分析

在下文我将 Styles下的ThemeStyle称为 Styles, 将Resources下的ControlTheme成为ControlTheme, 方便大家理解.

问题1 区别

按我个人的理解来看,这是属于两种UI设计模式.

  • Styles 类似于 CSS 样式表操作,针对在应用范围内的所有选择的元素的 Style 都将被应用.

  • ControlTheme 是类似与 WPF 的 Style, 除了默认ControlTheme, 其他ControlTheme都需要指定Key,相对独立。

问题2 重写TemplateStyles 还是 ControlTheme?

两种模式都可以写, ControlTheme 是从 v11 版本引入的. 主要是为了解决 Styles 之间的隔离性. 如:

 <Style Selector="Button">   // Default Style
    <Setter Property="HorizontalContentAlignment" Value="Right" />
    <Setter Property="VerticalContentAlignment" Value="Bottom" />
 </Style>
 // 两个Button的Style有关联关系
 <Style Selector="Button.NewStyle"> // 对 Default Style 的修改都有可能影响其他Style
    <Setter Property="HorizontalContentAlignment" Value="Left" /> 
    // <Setter Property="VerticalAlignment" Value="Bottom" />    // 来此Default Style
 </Style>

试想这样一个场景, 如果我在代码中引入了第三方控件库,它重写了系统默认控件的样式, 这个时候我们又有自己的样式, 如

// 第三方库
 <Style Selector="Button"> 
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="MinWidth" Value="100" />
 </Style>

// 我们自己的 
 <Style Selector="Button">   
    <Setter Property="HorizontalContentAlignment" Value="Left" />
    <Setter Property="VerticalContentAlignment" Value="Bottom" />
    <Setter Property="Width" Value="50" />
 </Style>

引用自官网: 如果你想要修改控件的特定实例的样式Styles,唯一的选项是应用一个新的Styles为控件实例,并希望它能够重写原始的Styles中的设置过的所有属性.

以上的场景 Button 的宽度是多少? 答 100. 这个对于来自WPF的小朋友就感觉就难受了, 第三方库加了个MinWidth,我又没继承,难道我还要在自己的样式中自己给MinWidth或者重新整个样式吗? 也就是Avalonia UI官方说的一旦一个Style被应用到一个控件上,没有办法移除它

坑就来了啊,如果第三方库更新了Styles加了个属性咋办? 我也要跟着加?

使用 ControlTheme

所以 V11 版本后引入了 ControlTheme 对于 特定 ControlControlTheme之间是彼此独立的。

<ControlTheme x:Key="A" TargetType="Button">
   <Setter Property="VerticalContentAlignment" Value="Center" />
   <Setter Property="HorizontalContentAlignment" Value="Center" />
   <Setter Property="MinWidth" Value="100" />
</ControlTheme>
// 两个Button的ControlTheme相互独立
<ControlTheme x:Key="B" TargetType="Button">
   <Setter Property="HorizontalContentAlignment" Value="Left" />
   <Setter Property="VerticalContentAlignment" Value="Bottom" />
   <Setter Property="Width" Value="50" />
</ControlTheme>

问: Button的宽度是多少? 答 50. 这不就跟我们大WPF一样了吗? 如果我还要继承第三方库写的样式咋办? 加上 Baseon 属性即可.

最佳实践

  1. 开发UI框架时最好使用 ControlTheme 定义控件 Template, 这也是官方推荐的。
  2. 利用控件可以应用多个Styles的优点,标准化一些常用样式, 供控件的扩展UI使用
  3. 利用 Styles 应用优先级比 ControlTheme 高的优点,
    1. 标准业务里边的多颜色主题使用Styles
    2. 全局控制应用的主题
  4. 不要写默认的全局Style<Style Selector="Button">, 否则所有Button都将受到影响, 官方全局样式里边的已经都替换成ControlTheme了, 有兴趣参考下面链接。

总结

Style & ControlTheme 的特性

独立性

ControlTheme 彼此之间是独立的
Style 彼此是相互覆盖的

如:

<ControlTheme x:Key="A" TargetType="Button">
   //...
</ControlTheme>
// 两个Button的ControlTheme相互独立
<ControlTheme x:Key="B" TargetType="Button">
   //...
</ControlTheme>
<Style Selector="Button">   // Default Style
   <Setter Property="HorizontalContentAlignment" Value="Right" />
   <Setter Property="VerticalContentAlignment" Value="Bottom" />
</Style>
// 两个Button的Style有关联关系
<Style Selector="Button.NewStyle"> // 对 Default Style 的修改都有可能影响其他Style
   <Setter Property="HorizontalContentAlignment" Value="Left" /> 
   // <Setter Property="VerticalAlignment" Value="Bottom" />    // 来此Default Style
</Style>

继承性

ControlTheme 由于ControlTheme之间相互独立,但是其支持 BaseOn 类似 WPF 的<Style BaseOn="{StaticResource BaseStyle}"
Style 参考上一点独立性, 新增的Style都将继承Default Style

如:

<ControlTheme x:Key="A" TargetType="Button">
   //...
</ControlTheme>
// 两个Button的ControlTheme相互独立
<ControlTheme x:Key="B" TargetType="Button" BaseOn="{StaticResource A}">
   //...
</ControlTheme>

Styles 类似 CSS, 它将所有作用域范围内的StylesSetters都放在一起应用到控件上. 这也就是为什么原始的Style如果新的Style不需要也要设置相同属性进行覆盖

优先级

从应用样式的角度 Style > ControlTheme 即 Default Style(或者设置了Classes的控件) 的 Setter 都将覆盖 ControlThemeSetter

从定义控件的角度 ControlTheme > Style 即 定义一类新Template(类似WPF的 ControlTemplate) 优先使用ControlTheme, 并且利用 Style 控制上层颜色方案

样式来源

ControlTheme 将遍历 可视树 (Visual Tree), 这种方式也与WPF类似

Style 类似于将所有作用域范围内的所有 Setter 合并并收集起来, 应用到控件实例上.

StylesControlTheme

控件实例可以引用多个Styles, 引用方式为 Classes="H1 Blue"

控件实例只可以引用一个ControlTheme, 引用方式为 Theme="{StaticResources XXXXTheme}"

参考文档

Control Themes

Styles

Button Themes

===

CC BY-NC-SA 4.0

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 0xJins包含此链接),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

标签:Styles,控件,Style,样式,ControlTheme,Theme,UI
From: https://www.cnblogs.com/CLink/p/18157836

相关文章

  • 「案例分享」DevExpress XAF (WinForms UI)赋能医疗管理系统,让操作更自动化!
    DevExpressXAF是一款强大的现代应用程序框架,它采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。获取DevExpress新版正式版下载DevExpress技术交流群10:532598169      欢迎一起进群讨论项目背景Min......
  • dotnet 如何将 Microsoft.Maui.Graphics 对接到 UNO 框架
    本文将和大家介绍如何将Microsoft.Maui.Graphics对接到UNO框架里面。一旦完成Microsoft.Maui.Graphics对接,即可让UNO框架复用现有的许多绘制的基础设施和现有基础库,且可以更进一步与MAUI打通众所周知,在UNO里面有大量的项目类型都是基于Skia作为底层渲染引擎构建出......
  • MAUI IOS如何弹起键盘时调整页面大小
    #ifIOSusingCoreGraphics;usingFoundation;usingMicrosoft.Maui.Platform;usingUIKit;#endifnamespaceYourProject{#nullabledisablepublicclassMainPage{ publicMainPage(){InitializeComponent();#ifIOS......
  • debian12安装使用distrobox来启动gui程序
    1.安装distroboxsudoaptinstalldistrobox这里默认使用的容器管理工具是podman,不是docker2.配置podman的注册表以下载镜像在/etc/containers/registries.conf.d/00-unqualified-search-registries.conf添加unqualified-search-registries=["docker.io"]网速不行的话......
  • 论文笔记-Two-phase flow regime identification based on the liquid-phase velocity
    对象:液相速度信息方法:CNN、LSTM、SVM目标:实现了水平管道内两相流态识别关注特征:从速度时间序列数据中提取的统计特征:均值、均方根和功率谱密度、最大速度比和最大速度差比结果:SVM-93.1%,CNN-94%,LSTM-不佳73.3%LSTM:总共使用了300秒的速度数据,然后将其分为180秒用于训练和......
  • 鸿蒙HarmonyOS实战-ArkUI动画(页面转场动画)
    ......
  • ToStringBuilder与直接toString的区别
    @OverridepublicStringtoString(){returnnewToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE).append("jobId",getJobId()).append("jobName",getJobName()).append("jobGroup&q......
  • WARNING: pip is configured with locations that require TLS/SSL, however the ssl
    pip3安装报错[[email protected]]#pip3install--upgradepipWARNING:pipisconfiguredwithlocationsthatrequireTLS/SSL,howeverthesslmoduleinPythonisnotavailable.Requirementalreadysatisfied:pipin/usr/local/python3/lib/python3.11/s......
  • BurpSuite 激活破解
    1、下载软件关于BurpSuite,它是进行Web应用安全测试的一个集成平台,无缝融合各种安全工具并提供全面的接口适配,支持完整的Web应用测试流程,从最初的映射和应用程序的攻击面分析到发现和利用安全漏洞等领域均适用。本次更次包含多项重大改动并添加了诸多全新功能具有许多新功能,包......
  • Python GUI开发- PyQt5 开发小工具环境入门
    前言常见的python开发gui的库有Tkinter,PyQt5,wxPython等。本教程是选择PyQt5开发桌面小工具。环境准备只需pip安装即可快速准备好开发环境pipinstallpyqt5快速开始创建一个空的window窗口Qapplication():每个GUI都必须包含一个Qapplication,argv表示获取命令行参数,如果......