Avalonia系列文章之樣式與主題
隨著社會的發展,大家對軟件的要求,從最初的命令行輸入輸出,到可視化輸入輸出,如報表,圖表等;從最初的可用性,穩定性為主,到現代軟件理念中的便捷易用性轉變,在保證穩定可用外,對軟件的交互易用要求越來越高,而這些則離不開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資源。所以就有兩種方式來定義控件主題:
- 如果希望控件主題應用于控件的所有實例,則將主題資源的x:Key屬性設置為{x:Type}作為資源的標識,如:<ControlTheme x:Key="{x:Type Button}" TargetType="Button">。
- 如果希望控件主題應用于選定的控件實例,則需要使用普通文本內容作為資源鍵,并使用StaticResource查找資源。
ControlTheme中的TargetType屬性指定適用于Setter屬性的類型。如果沒有指定TargetType,則必須使用類名限定Setter對象中的屬性,使用Property="ClassName.Property" 的語法。
以上就是《Avalonia系列文章之樣式與主題》的全部內容,旨在拋磚引玉,一起學習,共同進步。
作者:老碼識途
出處:http://www.rzrgm.cn/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關注個人公眾號,定時同步更新技術及職場文章

浙公網安備 33010602011771號