Avalonia系列文章之样式与主题

news/2025/2/21 15:49:27/文章来源:https://www.cnblogs.com/hsiang/p/18710783

随着社会的发展,大家对软件的要求,从最初的命令行输入输出,到可视化输入输出,如报表,图表等;从最初的可用性,稳定性为主,到现代软件理念中的便捷易用性转变,在保证稳定可用外,对软件的交互易用要求越来越高,而这些则离不开UI设计以及样式的应用。今天以一些简单的小例子,简述Avalonia UI中样式与主题的应用,仅供学习分享使用,如有不足之处,还请指正。

 

样式概述

 

Avalonia UI中的样式是一种可以在控件之间共享属性设置的机制。与WPF中的样式不同,Avalonia UI中的样式设置借鉴了B/S开发中的CSS样式理念;不过Avalonia UI引入了主题(ControlTheme)和WPF中的样式相对应。当给UI控件设置样式时,样式系统从控件开始沿着逻辑树向上搜索,直到应用程序的最高级别(App.axaml)。如果样式系统匹配到控件设置的样式时,则根据样式中的设置器互进行更改。样式系统沿着逻辑树向上搜索,采用就近原则,所以如果有多个匹配项,则离控件更近的地方定义的样式可以覆盖离控件较远的地方定义的样式。

 

样式定义

 

样式的定义包含两部分:选择器属性(Selector)和一个或多个设置器元素(Setter)。选择器的值包含使用Avalonia UI“样式选择器语法”的字符串。每个设置器元素通过名称标识将被更改的属性和将被替换的新值。语法如下:

<Style Selector="selector syntax"><Setter Property="property name" Value="new value"/>...
</Style>

说明:Avalonia UI 样式选择器语法 类似于 CSS(层叠样式表)中使用的语法。

样式放置在UserControl或Window或者Application上的Styles集合中,如下所示:

<UserControl.Styles><Style Selector="Button"><Setter Property="Background" Value="Red"></Setter><Setter Property="Margin" Value="10"></Setter></Style> 
</UserControl.Styles>
<StackPanel><Button Width="100" Height="100" Content="按钮"></Button><Button Width="100" Height="100" Content="按钮"></Button>
</StackPanel>

上述样式示例,定义了一个Button按钮的样式(背景色为红色,边距为10px),选择器属性为Button,表示在UserControl范围内的Button都会应用此样式,如StackPanel中的Button,示例效果如下所示:

选择器定义样式将作用于哪些控件,定义选择器的格式有很多种,类型选择器是比较常用的一种方式。设置器描述了当选择器与控件匹配时会发生什么,设置器主要设置控件的属性Property和值Value。当样式与控件匹配时,样式中所有的设置器都将应用于控件。

 

嵌套样式

 

在实际应用用,除了可以定义单独的样式,还可以定义嵌套样式,而嵌套样式只需要将子样式作为Style元素的子元素包含,并在子选择器的开头加上“嵌套选择器标识符^”。如下所示:

<UserControl xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:vm="clr-namespace:FirstAvalonia.ViewModels"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"x:Class="FirstAvalonia.Views.MainView"><UserControl.Styles><Style Selector="TextBlock.h1"><Setter Property="FontSize" Value="24"/><Setter Property="FontWeight" Value="Bold"/><Style Selector="^:pointerover"><Setter Property="Foreground" Value="Red"/></Style></Style></UserControl.Styles><StackPanel><TextBlock Classes="h1" Text="字号24,加粗,鼠标放上变红色"></TextBlock></StackPanel>
</UserControl>

在上述示例中,子样式继承了父样式的属性设置,当鼠标悬停在TextBlock.h1设置的样式时,子样式才会生效。如下:

 

注意,"嵌套选择器标识符^"必须存在,并且必须出现在子选择器的开头

 

样式键

 

样式选择器匹配的对象的类型并不是由控件的具体类型决定的,而是通过检查器StyleKey属性来确定。默认情况下,StyleKey属性返回当前实例的类型。示例:当你自定义一个控件,且它继承自Button,如果你希望它被样式化一个按钮,可以重写StyleKeyOverride属性,并让它返回typeof(Button)。如下所示:

public class MyButton : Button
{// MyButton 将会被作为标准的 Button 控件样式化。protected override Type StyleKeyOverride => typeof(Button);
}

在WPF/UWP中,当你派生一个新的控件时,它将被样式化为其基础控件,除非你覆盖了DefaultStyleKey属性。在Avalonia UI中,控件将使用其具体类型进行样式化,除非提供了相同的样式键。

 

样式类

 

在Avalonia UI中,可以为控件分配一个或多个样式类,并使用它们来指导样式选择。样式类通过在控件元素中使用Classes属性进行分配。多个样式类之间用空格进行分隔。示例如下所示:

<UserControl xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:vm="clr-namespace:FirstAvalonia.ViewModels"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"x:Class="FirstAvalonia.Views.MainView"><UserControl.Styles><Style Selector="Button.h1"><Setter Property="FontSize" Value="24"></Setter></Style><Style Selector="Button.blue"><Setter Property="Background" Value="Blue"></Setter></Style></UserControl.Styles><StackPanel><Button Classes="h1 blue" Width="100" Height="100" Content="按钮"></Button><Button Width="100" Height="100" Content="按钮"></Button></StackPanel>
</UserControl>

在上述示例中,第一个Button应用了h1,blue两个样式,第二个按钮没有应用样式,差别如下:

 注意,选择器中样式类的定义必须以“控件类型.样式类名称”的格式进行定义。多个样式类定义必须用点号分隔,如“Button.larger.blue”等。如果选择器指定了多个类,则控件必须同时拥有所有请求的类定义才能匹配。

 

伪类(Pseudo Classes)

 

伪类(Pseudo Classes)与CSS类似,控件可以拥有伪类,这些类是控件本身而不是用户定义的。伪类在选择器中的名称,始终以“冒号”开头。如:pointerover伪类表示鼠标悬停在控件上,pressed伪类表示鼠标在按钮上按下,checked表示复选框选中时。示例如下所示:

<StackPanel><StackPanel.Styles><Style Selector="Border:pointerover"><Setter Property="Background" Value="Red"/></Style></StackPanel.Styles><Border><TextBlock>I will have red background when hovered.</TextBlock></Border>
</StackPanel>

 

控件主题

 

控件主题是在样式的基础上构建的,用于为控件创建可切换的主题。控件主题本质是样式,但和样式有一些区别:

  • 控件主题没有选择器,它们有一个TargetType属性,用于描述它们要针对的控件。
  • 控件主题存储在ResourceDictionary中,而不是Styles集合中。
  • 控件主题通过设置Theme属性来分配给控件,通常使用StaticResource标记扩展。

控件主题通常用于模板化控件,对于非模板化的控件,通常使用标准样式更方便。

定义主题,控件主题作为资源的形式出现,一般可以在窗口(Window),用户控件(UserControl),应用程序(Application)的Resources中进行定义,如下所示:

<Application xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"x:Class="FirstAvalonia.App"RequestedThemeVariant="Default"><Application.Styles><FluentTheme /></Application.Styles><Application.Resources><ControlTheme x:Key="EllipseButton" TargetType="Button"><Setter Property="Background" Value="Blue"/><Setter Property="Foreground" Value="Yellow"/><Setter Property="Padding" Value="8"/><Setter Property="Template"><ControlTemplate><Panel><Ellipse Fill="{TemplateBinding Background}"HorizontalAlignment="Stretch"VerticalAlignment="Stretch"/><ContentPresenter x:Name="PART_ContentPresenter"Content="{TemplateBinding Content}"Margin="{TemplateBinding Padding}"VerticalAlignment="Center" HorizontalAlignment="Center" /></Panel></ControlTemplate></Setter></ControlTheme></Application.Resources>
</Application>

在上述示例中,ControlTheme作为Resources的子元素,x:Key表示资源的唯一标识,TargetType表示主题要应用的控件类型。

应用主题,主题定义完成后,可以在控件上通过Theme="{StaticResource ResourceKey}"的形式进行引用,如下所示:

<StackPanel Orientation="Horizontal"><Button Classes="h1 blue" Width="100" Height="100" Content="按钮" Theme="{StaticResource EllipseButton}"></Button><Button Width="100" Height="100" Content="按钮" ></Button>
</StackPanel>

应用主题后的效果如下所示:

 

控件主题查找

 

控件主题有两种查找方式:

如果控件的Theme属性被设置,则应用该控件主题;如果没有指定控件的Theme属性,Avalonia UI会从逻辑树向上搜索控件,查找一个x:Key与控件的样式键匹配的ControlTheme资源。所以就有两种方式来定义控件主题:

  1. 如果希望控件主题应用于控件的所有实例,则将主题资源的x:Key属性设置为{x:Type}作为资源的标识,如:<ControlTheme x:Key="{x:Type Button}" TargetType="Button">。
  2. 如果希望控件主题应用于选定的控件实例,则需要使用普通文本内容作为资源键,并使用StaticResource查找资源。

ControlTheme中的TargetType属性指定适用于Setter属性的类型。如果没有指定TargetType,则必须使用类名限定Setter对象中的属性,使用Property="ClassName.Property" 的语法。

以上就是《Avalonia系列文章之样式与主题》的全部内容,旨在抛砖引玉,一起学习,共同进步。

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

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

相关文章

SynchronousQueue的put方法底层源码

一、SynchronousQueue的put方法底层源码 SynchronousQueue 的 put 方法用于将元素插入队列。由于 SynchronousQueue 没有实际的存储空间,put 方法会阻塞,直到有消费者线程调用 take 方法移除元素 1、put 方法的作用将元素插入队列。如果没有消费者线程等待,当前线程会阻塞,…

【Tomcat文件上传】绕WAF姿势深入研究

环境 本地环境tomcat8.5.93,无黑白名单限制getSubmittedFileName()函数 tomcat可以通过filePart.getSubmittedFileName();获取上传文件的原始名filename获取Content-Disposition头后,判断值是否form-data或attachment开头 然后112行将form-data; name="file"; file…

关于一个手机控制电脑执行特定任务的解决方案探索【1】

【前言】 说来话长,关于这个手机控制电脑执行特定任务的想法早在几年前就有,但因为对安卓平台开发经验实在不足,就一直拖到了现在。不过好在没有忘记初衷,接下来我们一起来看我的思路和方法。 【思路】 想要通过手机作为控制端,来发送指令给同一网络下的电脑端,执行特定任…

如何升级 PowerShell 到最新版本

前言最近,需要大量使用PowerShell,然后有需要PowerShell 7正文升级的步骤也比较简单,按照下面的步骤就好了文字版本的,方便大家复制粘贴。PS C:\WINDOWS\system32> $PSVersionTable.PSVersionMajor Minor Build Revision ----- ----- ----- -------- 5 1 …

百万架构师第四十课:RabbitMq:RabbitMq-工作模型与JAVA编程|JavaGuide

来源:https://javaguide.net RabbitMQ 1-工作模型与Java编程 课前准备 预习资料 Windows安装步骤 Linux安装步骤 官网文章中文翻译系列 环境说明 操作系统:CentOS 7 JDK:1.8 Erlang:19.0.4或最新版 RabbitMQ:3.6.12或最新版 版本对应关系 典型应用场景跨系统的异步通信。人…

1月16日java假期学习读书笔记

一、学习目标 掌握HTML的基本结构和常用标签。 了解CSS的基本选择器和样式规则。 通过实际代码练习,构建一个简单的网页。 二、学习内容 (一)HTML基础 HTML简介 HTML(HyperText Markup Language,超文本标记语言)是用于构建网页的标准标记语言。 它通过一系列的标签(如、…

MapStruct使用指南并结合Lombok

MapStruct使用指南并结合Lombokhttps://juejin.cn/post/6956190395319451679#heading-1 2024-01-11 18:34:06如何结合 lombok 也就说说如果代码中使用了 lombok 注解来生成代码,mapstruct 的 getter/setter 方法也使用了 lombok 的 api,那就需要额外的配置,因为这两个工具都是使…

史上最全桌面级CPU天梯图-2024年10月更新(包含13/14代Intel/7000系列锐龙)

史上最全桌面级CPU天梯图-2024年10月更新(包含13/14代Intel/7000系列锐龙) 原文:https://www.zhihu.com/tardis/bd/art/499783467?source_id=1001

large_bin_attack

large_bin的结构如下 /*This struct declaration is misleading (but accurate and necessary).It declares a "view" into memory allowing access to necessaryfields at known offsets from a given base. See explanation below. */ struct malloc_chunk {INTERN…

体验用ai做了个python小游戏

写在前面:最近ai确实比较火。各种生成式AI,包括文字、图片、视频。之前听说ai生产代码能力比较强,一直想试试。所以及就有了本问。使用的工具deepinseek :用来生成python代码即梦:用来生成图片素材Remove.bg:用来对生成的图片素材去除背景pixabay.com:用来下载音乐素材游…

2.1.5 节省内存

首先来介绍一下可变对象和不可变对象可变对象:整数,浮点数,字符串,元组等 不可变对象:列表,字典,集合等然后看一下Python中内存分配的方式 执行x=1会发生什么?此时,内存会分配一个地址给1,1是一个整型对象,而x是一个引用(不是对象!),指向1所在的位置,并不占用实…