目录

介绍

在 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

===

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

Avalonia UI 中 Styles 与 ControlTheme 的区别的更多相关文章

  1. material UI中withStyles和makeStyles的区别

      在material UI中,withStyles和makeStyles是经常使用的两个用于封装样式的函数.对于刚使用material UI的开发者而言,可能不太清楚这两者的区别.   本文简要探究 ...

  2. 树莓派 Raspberry Pi 4,.net core 3.0 ,Avalonia UI 开发

    虽说.net core3.0已经可以用于开发wpf和winform程序,可是遗憾的时目前这core下的wpf还是只能运行在windows下,想要在linux下运行wpf估计还要等一段时间. Avalo ...

  3. jsp中两种include的区别【转】

    引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...

  4. (转)asp.net中Literal与label的区别

    asp.net中Literal与label的区别 一.Literal Web 服务器控件概述(摘于MSDN) 可以使用 Literal Web 服务器控件作为页面上其他内容的容器.Literal 最常 ...

  5. html中submit和button的区别(总结) [ 转自欣步同学 ]

    html中submit和button的区别(总结) submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证 ...

  6. Android中style和theme的区别

    在学习Xamarin android的过程中,最先开始学习的还是熟练掌握android的六大布局-LinearLayout .RelativeLayout.TableLayout.FrameLayou ...

  7. 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

    [分析]浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang) 今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间 ...

  8. .NET 跨平台框架Avalonia UI: 填坑指北(二):在Linux上跑起来了

    上一章回顾:  .NET 跨平台框架Avalonia UI: 填坑指北(一):熟悉UI操作 本篇将要阐述 包括但不仅限于Avalonia及所有Windows到Linux跨平台开发 的一些注意事项: 一 ...

  9. .NET跨平台框架选择之一 - Avalonia UI

    本文阅读目录 1. Avalonia UI简介 Avalonia UI文档教程:https://docs.avaloniaui.net/docs/getting-started 随着跨平台越来越流行, ...

  10. 【转】为什么我们都理解错了HTTP中GET与POST的区别

    GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...

随机推荐

  1. Spark - Pandas UDF

    spark 本身对 dataframe 的操作支持没有像pandas 那样强大,所有我们可以把spark dataframe 转化成 pandas dataframe 来利用pandas datafr ...

  2. 游戏AI行为决策——Behavior Tree(行为树)

    游戏AI行为决策--行为树 前言 行为树,是目前游戏中应用较为广泛的一种行为决策模型.这离不开它成熟的可视化编辑工具,例如Unity商城中的「Behaviour Designer」,甚至是虚幻引擎也自 ...

  3. VS Code – Keyboard Shortcuts

    前言 记入一些自己常用到的 Keyboard Shortcuts 和 Extensions. Keyboard Shortcuts undo redo 鼠标坐标:shift + left/right ...

  4. 《Neo4j 图数据库扩展指南:APOC和ALGO》

    https://detail.tmall.com/item.htm?spm=a2e2i.11532906.0.d2960ced2.f27a6abbrEMtHp&id=622478213458 ...

  5. 《Vue.js 设计与实现》读书笔记 - 第12章、组件的实现原理

    第12章.组件的实现原理 12.1 渲染组件 在渲染器内部的实现看,一个组件是一个特殊类型的虚拟 DOM 节点.之前在 patch 我们判断了 VNode 的 type 值来处理,现在来处理类型为对象 ...

  6. 专题 求数列的前n项和

    \(\mathbf{{\large {\color{Red} {欢迎到学科网下载资料学习}} } }\)[[高分突破系列]高二数学下学期同步知识点剖析精品讲义! \(\mathbf{{\large { ...

  7. 2024年8月中国数据库排行榜:OceanBase攀升再夺冠,达梦跃入三甲关

    在这个炽热的季节,随着巴黎奥运会的盛大开幕,全球将目光聚集在了体育的无限魅力和竞技的巅峰对决上.如同奥运赛场上的激烈角逐,中国数据库界也上演着一场技术与创新的较量,各个数据库产品正在中国乃至全球舞台上 ...

  8. 墨天轮访谈 | SelectDB 衣国垒:Apache Doris(incubating)1.0版本特性解析与未来规划

    分享嘉宾:衣国垒 Apache Doris Committer.SelectDB 联合创始人&CTO 整理:墨天轮社区 导读 大家好,我是来自Apache Doris社区的衣国垒,也是Sele ...

  9. ChallengeMobile

    解题思路 获取到输入的字符串保存到s,调用Jformat方法对s进行验证,返回true则代表输入字符串正确反之错误. Jformat方法分析: 首先看到使用了LoadData加载了"ming ...

  10. 元素偏移量offset 与 style 区别 ?

    offset 可以得到任意样式表中的样式值offset 系列获得的数值是没有单位的数字offsetWidth 包含padding+border+width offsetWidth 等属性是只读属性,只 ...