Avalonia系列文章之样式与主题2-牛翰网

Avalonia系列文章之样式与主题2

在前一篇文章中,简述了Avalonia UI中样式和主题的简单用法,今天继续深入讲解样式的选择器语法以及内置主题等相关内容,仅供学习分享使用,如有不足之处,还请指正。

 

样式选择器语法

 

样式选择器定义样式将作用于哪些控件。选择器使用多种格式,接下来将分别介绍。

 

按控件类型选择

 

Avalonia UI中的样式可以按照控件类进行定义,在选择器中输入控件类型即可,示例如下所示:

<Style Selector="Button">
    <Setter Property="Background" Value="Red"></Setter>
    <Setter Property="Margin" Value="10"></Setter>
</Style>

在上述代码中,定义的样式将应用于所有的Button,如果在选择器中需要加入命名空间,则将类型和命名空间以竖线隔开即可,如下所示:

<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"
             xmlns:xx="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
             x:DataType="vm:MainViewModel">
	<UserControl.Styles>
		<Style Selector="xx|Button">
			<Setter Property="Background" Value="Red"></Setter>
			<Setter Property="Margin" Value="10"></Setter>
		</Style>
	</UserControl.Styles>
</UserControl>

其中 命名空间必须先以xmlns:xx=”clr-namespace:命名控件;assembly=程序集”的方式声明,才能在选择器进行引用,而不能直接引用。选择器不会匹配派送类型,若要匹配派送类型,需要使用:is选择器。

对象的类型,是通过查看器StyleKey属性来来确定的,通常它返回当前实例的类型,所以,如果希望Button的派生类也被视为Button样式,则需要重写StyleKeyOverride属性以返回typeof(Button)。关于StyleKeyOverride说明如下所示:

此方法为virtual修饰的虚,重写示例如下所示:

namespace FirstAvalonia.OkControls
{
    public class OkButton:Button
    {
        protected override Type StyleKeyOverride => base.StyleKeyOverride;

    }
}

 

按名称选择

 

如果定义的样式只需要应用于特定的控件,则可以按名称进行定义选择器。在定义选择器时,以Selector=”类型#控件名称”的格式进行定义,如下所示:

<Style Selector="Button#btnOk">
	<Setter Property="Background" Value="Red"></Setter>
	<Setter Property="Margin" Value="10"></Setter>
</Style>

在上述示例中,样式将应用于x:Name=”btnOk”的按钮。如下所示:

<Button x:Name="btnOk" Content="Ok"></Button>

注意,按名称选择中,必须在#前加上控件类型前缀才可以,否则无法识别要应用的控件类型。

 

按样式类选择

 

样式类是按照在选择器中定义类别,并在控件中通过Classes属性进行引用。样式类以“控件类型.样式类名1.样式类名2”的形式进行命名,格式如下所示:

<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"
             x:DataType="vm:MainViewModel">
	<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 Orientation="Horizontal">
		<Button Classes="h1 blue" Width="100" Height="100" Content="按钮" Theme="{StaticResource EllipseButton}"></Button>
	</StackPanel>
</UserControl>

在上述示例中,定义了h1,blue两个样式类,分别定义控件字体大小,和背景色。通过Classes=”h1 blue”的方式进行引用,多个样式类用空格隔开。且选择器可以定义多个样式类,多个类用点号分隔(如:Selector=Button.large.red),如果选择器中指定了多个类,则控件必须同时拥有所有请求的类定义才能匹配。

 

按伪类选择

 

使用当前伪类选择控件进行匹配样式,伪类在选择器中以英文冒号为标识符,且选择器中只能定义一个伪类,与其他样式类一起使用时,伪类必须在选择器定义的最后一个。伪类定义格式为“控件类型:伪类名称”或“控件类型.样式类:伪类名称”示例为:

<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"
             x:DataType="vm:MainViewModel">
	<UserControl.Styles>
		<Style Selector="Button#btnOk">
			<Setter Property="Background" Value="Red"></Setter>
			<Setter Property="Margin" Value="10"></Setter>
		</Style>
		<Style Selector="Button:pointerover">
			<Setter Property="FontWeight" Value="Bold"> </Setter>
		</Style>
	</UserControl.Styles>
	<StackPanel Orientation="Horizontal">
		<Button x:Name="btnOk" Content="Ok"></Button>
		<Button Width="100" Height="100" Content="按钮" ></Button>
	</StackPanel>
</UserControl>

在上述示例中,Selector=”Button:pointerover”表示当鼠标放在按钮上时应用样式。

 常用的伪类主要有以下几种:

  1. :disabled    禁用控件。
  2. :pointerover    鼠标放置在控件之上。
  3. :focus   控件聚焦。
  4. :focus-within    控件处于获取焦点状态,或者其子控件中存在处于获取焦点状态的控件。
  5. :focus-visible    该控件已获得焦点,应当显示一个视觉指示器。

 

子操作符

 

如果想让样式应用于某些控件内的子控件,则可以使用子操作符。子选择符使用大于号(>)来表示。如Selector=StackPanel > Button” 表示StackPanel直接包含的Button才会匹配样式。子操作符定义的选择器仅匹配逻辑控件树的中的直接子项。

<StackPanel>
   <Button>Save</Button>
   <DockPanel Width="300" Height="300">
       <Button DockPanel.Dock="Top">Top</Button>
       <TextBlock>Some text</TextBlock>
    </DockPanel>
</StackPanel>

该选择器将匹配第一个按钮,但不会匹配第二个按钮。这是因为第二个按钮不是堆栈面板的直接子项(它在停靠面板中)。 

 

任意后代操作符

 

子操作符仅匹配逻辑树中的直接子项,而如果想匹配逻辑树中的所有子项,则可以使用任意后代操作符。任意后代操作符为空格,当两个选择器由空格分隔时,选择器将匹配逻辑树中的任意后代,父级在左边,后代在右边。示例如下所示:

<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"
             x:DataType="vm:MainViewModel">
	<UserControl.Styles>
		<Style Selector="StackPanel Button">
			<Setter Property="BorderThickness" Value="2"></Setter>
			<Setter Property="BorderBrush" Value="Yellow"></Setter>
		</Style>
	</UserControl.Styles>
	<StackPanel Orientation="Horizontal">
		<Button x:Name="btnOk" Content="Ok"></Button>
		<Button Width="100" Height="100" Content="按钮" ></Button>
	</StackPanel>
</UserControl>

上述示例中,StackPanel下的Button都将匹配样式,具备“2像素的黄色边框”。

 

按属性匹配

 

在Avalonia UI中,可以根据控件包含某些属性来应用样式,这就可以细化选择器,在选择器中包含属性的值,格式为“控件类型[属性=值]”,这将匹配具有指定属性设置为指定值的控件。如下所示:

<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"
             x:DataType="vm:MainViewModel">
	<UserControl.Styles>
		<Style Selector="Button[IsDefault=true]">
			<Setter Property="FontStyle" Value="Italic"></Setter>
		</Style>
	</UserControl.Styles>
	<StackPanel Orientation="Horizontal">
		<Button Width="100" Height="100" Content="按钮" IsDefault="True"></Button>
		<Button Width="100" Height="100" Content="按钮" ></Button>
	</StackPanel>
</UserControl>

在上面的XAML中,第一个按钮将被选择,但第二个按钮不会被选择,因为第二个按钮没有设置IsDefault=”True”属性。

注意,如果要将附加属性用作属性匹配,则属性名必须用括号括起来。如:Selector=TextBlock[(Grid.Row)=0]“。

 

Not函数

 

如果选择器中想要不包含某些条件来定义,则可以使用Not函数,即否定选择器。示例代码如下所示:

<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"
             x:DataType="vm:MainViewModel">
	<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>
		<Style Selector="TextBlock:not(.h1)">
			<Setter Property="FontStyle" Value="Italic"></Setter>
		</Style>
	</UserControl.Styles>
	
	<StackPanel>
		<TextBlock Classes="h1" Text="字号24,加粗,鼠标放上变红色"></TextBlock>
		<TextBlock Text="普通文本,斜体"></TextBlock>
	</StackPanel>
</UserControl>

在上述示例中,h1的样式将匹配第一个TextBlock,不包含h1样式的TextBlock将匹配第二个样式。

以上只是列举了一些常用的样式,关于更多内容,请参考官网:

https://docs.avaloniaui.net/zh-Hans/docs/reference/styles/style-selector-syntax

 

主题

 

在Avalonia UI中,官方提供了两个内置主题:

  • Fluent主题,Fluent主题是受Microsoft的Fluent Design System启发的现代主题。
  • Simple主题,是一个简约且轻量的主题,具有有限的内置样式。

 

Fluent主题

 

Fluent主题受到微软的Fluent Design System启发,该系统是一组用于创建视觉吸引力和交互式用户界面的设计指南和组件。Fluent Design System强调现代,清晰的美学,平滑的动画和直观的交互。它在不同平台上提供了一致而精致的外观和感觉,同时为开发人员提供了样式系统的灵活性。

默认创建的Avalonia项目,已经通过Nuget包管理器安装了Fluent组件库,当前版本号为11.2.4,如下图所示:

且默认情况下,已经在App.xaml中包含了Fluent主题,如下所示:

<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"/>
		</ControlTheme>
	</Application.Resources>
</Application>

虽然 FluentTheme 有内置的暗色和浅色变体资源,但仍然可以重写这些变体的基础调色板。 这在开发人员想要使用相同的基本主题但具有不同颜色时非常有用。

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="AvaloniaApplication.App">
  <Application.Styles>
    <FluentTheme>
      <FluentTheme.Palettes>
        <!-- 适用于浅色主题变体的调色板 -->
        <ColorPaletteResources x:Key="Light" Accent="Green" RegionColor="White" ErrorText="Red" />
        <!-- 适用于暗色主题变体的调色板 -->
        <ColorPaletteResources x:Key="Dark" Accent="DarkGreen" RegionColor="Black" ErrorText="Yellow" />
      </FluentTheme.Palettes>
    </FluentTheme>
  </Application.Styles>
</Application>

 

Simple主题

 

Avalonia Simple 主题专门设计为简约且轻量,具有有限的内置样式。它为构建自定义样式提供了简单干净的基础。低视觉和结构复杂性使其成为在嵌入式设备上运行的应用程序的理想选择。

若要使用Simple主题,首先需要安装 Avalonia.Themes.Simple NuGet 包。如下图所示:

然后在App.xaml中包含主题,如下所示:

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="AvaloniaApplication.App">
  <Application.Styles>
    <SimpleTheme />
  </Application.Styles>
</Application>

关于主题的更多内容,请参考官网:

https://docs.avaloniaui.net/zh-Hans/docs/basics/user-interface/styling/themes/

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

来源链接:https://www.cnblogs.com/hsiang/p/18731695

请登录后发表评论

    没有回复内容