惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
J
Java Code Geeks
Vercel News
Vercel News
A
About on SuperTechFans
G
Google Developers Blog
C
Check Point Blog
腾讯CDC
N
Netflix TechBlog - Medium
博客园 - 司徒正美
S
SegmentFault 最新的问题
D
DataBreaches.Net
博客园_首页
美团技术团队
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
量子位
雷峰网
雷峰网
IT之家
IT之家
小众软件
小众软件
Blog — PlanetScale
Blog — PlanetScale
博客园 - 三生石上(FineUI控件)
H
Help Net Security
宝玉的分享
宝玉的分享
博客园 - 叶小钗

博客园 - 丹心石

数据字节位改变 锁定鼠标光标到指定屏幕 WPF 访问WebAPI Avalonia 避坑经验总结 Avalonia 窗口与配置 Avalonia 程序打包成Linux平台的运行程序 数据处理与转换 信号与槽 Qt 串口通信 Avalonia 设计时DataContext数据山下文和WPF设计时DataContext数据上下文 Avalonia Ursa 使用 Avalonia-消息对话框 Avalonia-数据绑定 阿里图标库iconfont 在Avalonia 中的使用 Avalonia MVVM Avlonia 自定义控件 Sqlite EF For ConsoleCore Sqlite EF CodeFirst For WPF win10 环境变量不可编辑 WCF-双工通讯 MahMetro 框架学习 由于缺少调试目标“xxx”Visual Studio 无法开始调试。或者响应地设置outputpath和AssemblyName 属性 WPF 应用程序本地化-资源文件方式 FastReport 行高设置实现行高随内容自动变化
Avalonia-样式
丹心石 · 2026-02-03 · via 博客园 - 丹心石

样式选择器

  • 在Avalonia中样式的使用与WPF中的区别是用样式选择器Selector 替代WPF 中的TargetType,这里简单说明一下样式选择器


样式选择器 描述
Button 选择所有Button(类)的控件
Button.red 选择所有带有red样式类的Button控件
Button.red.large 选择所有同时带有red和large样式类的Button 控件
Button:focus 选择带有:focus 伪类激活的Button 控件
Button.red.focus 选择所有同时带有red样式类和 :focus 伪类激活的Button 控件
Button#myButton 选择Name(属性)为"myButton"的Button 控件
StackPanel Button.x1 选择所有带有x1样式类的Button(类)控件,同时他们是StackPanel(类)控件的后代,可以位于任何级别
StackPanel>Button.x1 选择所有带有x1样式的Button(类控件),同时他们是StackPanel (类)控件的直接后代
Button/template/ContentPresenter 选择所有在Button(类)控件的模板内的ContentPresenter(类)控件

Selector

在Avalonia 中可以在定义样式时,通过样式选择器Selector直接指定到对应的控件,并通过classes进行区分应用不同的样式,和CSS样式类似。在所有控件中增加了一个属性 Classes 用来设置当前控件使用的样式类

<Grid>
  <Grid.Styles>
	<!--让带有h1样式类的TextBlock具有24点字体大小-->
	<Style Selector="TextBlock.h1">
		<Setter Property="FontSize" Value="24" />
	</Style>
</Grid.Styles>

<TextBlock Classes="h1" Text="&#xe665;" Foreground="SkyBlue" FontFamily="{StaticResource iconfont}"  Width="100" Height="35" />
</Grid>


如果Selector 中只复制了控件类型,而没有“.”向下细分,则样式会应用到所有内部的同类型控件上

嵌套样式

样式可以嵌套在其它样式中。要使用嵌套样式,只需将资阳市作为父 Style 元素的子元素包含,并在子选择器的开头加上嵌套选择器^ 即可。pointerover 鼠标悬停触发

<Style Selector="TextBlock.h1">
  <Setter Property="FontSize" Value="24" />
  <Setter Property="FontWight" Value="Bold" />
  <Style Selector="^:pointerover">
    <Setter Property="Background" Value="Red" />
  <Style>
</Style>

多样是

可以为Avalonia UI 控件分配一个或多个样式类,并使用他们来指导样式选择。样式类通过在控件元素中使用Classes属性进行分配,如果使用多个类,则使用空格分隔

<Button Classes="h1 blue" />

也可以通过CS 代码实现:

control.Classes.Add("blue");
control.Classes.Add("red");

如果把样式应用于不同控件,可以用逗号分隔

<Style Selector="TextBlock,Button">

伪类选择器

Avalonia 中的伪类,类似与CSS,是由Control(控件)暴露出的关键字,用于方便地知识控件的特定状态,以便于样式选择器使用。这些状态被用于条件性地样式化控件。例如一个Button 在被按下时可以有不同的外观,一个TextBox在被禁用时也是如此。

<StackPanel>
   <StackPanel.Styles>
      <Style Selector="Button:pressed">
	     <Settor Property="Foreground" Value="Red" />
      </Style>
   </StackPanel.Styles>
</StackPanel>

常用伪类

伪类 描述
:disabled 控件失效,无法交互
:pointerover 鼠标悬停
:focus 获得焦点
:focus-within 获得焦点或子元素获得焦点
:focus-Visible 获得焦点并可见

自定义伪类:[PseudoClasses(":left",":right",":middle")]

模板选择器

通过 /template/ 可以找到非自定义的控件的内部元素,并更改其样式。

<StackPanel>
  <StackPanel.Styles>
      <Style Selector="Button:pressed /template/ContentPresenter">
         <Setter Property="TextBlock.Foreground" Value="Red" />
	  </Style> 
  </StackPanel.Styles>
  <Button>Test </Button>
</StackPanel>

引用样式文件

  <Window>
    <Window.Styles>
	   <StyleInclude Source="/Styles/AppStyle.axaml" />
	</Window.Styles>
  </Window>

引用其他程序集的样式 avares://

<Application>
   <Application.Styles>
      <FluentTheme Mode="Light" />
	  <StyleInclude Source="avares://MyApp.Shared/Styles/CommonAppStyle.axaml" />
   </Application.Styles>
</Application>

主题资源

通过主题字典可以添加多个资源字典,设置不同的键值:Light/Dark
<Application ....
RequestedThemeVariant="Dark">
<Application.Styles>

</Application.Styles>

绑定

1.绑定到控件

通过关键字 #TargetControlName.TargetProperty ,而不是WPF中的ElementName="" Path=""

<TextBox Name="other">
<!--绑定到名称伪other控件的Text属性-->
<TextBlock Text="{Binding #other.Text}" />

2.绑定到父级

通过关键字: $parent:TargetProperty 而WPF是通过{Binding RelativeResource={RelativeResource Mode.Self},Path=""} 来实现的

<Border Tag="Hello World">
  <TextBlock Text="{Biding $parent.Tag}" />
</Border>

任意父级:$parent[Grade].TargetProperty

  <Border Tag="Hello">
     <Border>
	    <TextBlock Text="{Binding $parent[1].Tag}" />
	 </Border>
  </Border>

指定父级类型
$parent[ParentControlType].TargetProperty

 <Border Tag="Hello World!">
    <Decorator>
	   <TextBlock Text="{Binding $parent[Border].Tag}" />
	</Decorator>
 </Border>

指定类别和级别:$parent[ParentControlType;Grade].TargetProperty

<Border Tag="Hello World">
  <Border>
    <Decorator>
	   <TextBlock Text="Binding $parent[Border;1].Tag" />
	</Decorator>
  </Border>
</Border>

第三方控件:$parent[AssemblyName:ParentControlType].TargetProperty

<local:MyControl Tag="Hello World!">
  <Decorator>
     <TextBlock Text="{Binding $parent[local:MyControl].Tag}" />
  </Decorator>
</local:MyControl>

绑定到方法

Avalonia UI 数据绑定提供了一种使用命名约定来实现“能否执行”功能的简单方法。
如果你需要根据命令参数或视图模型属性的值来决定是否执行,那么你可以编写一个第二个布尔方法来检查操作方法是否可以执行
为了使其工作,Avalonia UI使用了布尔方法与操作方法相同的根方法名,但加上了前缀Can的命名约定。

public class MainViewModel
{
  publci void PerformAction(object msg)
  {
     Debug.WriteLine("$The action was called.{msg}");
  }
}

AXAML

  <StackPanel Margin="20">
     <TextBlock Margin="0 5" x:Name="message" WaterMark="添加一条消息" />
	 <Button Command="{Binding PerformAction}" CommandParameter="{Binding #message.Text}" >
	   Run the  example
	 </Button>
  </StackPanel>

绑定到任务结果

如果需要进行一些繁重的工作来加载属性内容,可以绑定到async Task的结果

  public Task<string> MyAsyncText=GetTextAsync();
  private async Task<string> GetTextasync()
  {
     await Task.Delay(1000);
	 return "Hello from async operation";
  }

AXAML

  <TextBlock Text="{Binding MyAsyncText^,FallbackValue='wait a second'}" />

对于需要延迟返回的任务结果需要加绑定后缀:^

动画

1.样式中的关键帧动画

Iteration可设置伪指定次数或无限循环

<Window 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"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="AvaloniaMVVMDemo.Window1"
        Title="动画" WindowStartupLocation="CenterScreen">
	<Window.Styles>
		<!--在样式中使用动画,Avalonia中动画是通过关键帧来设置的,样式中的关键帧Style.Animations 可设置多个动画-->
		<Style Selector="Rectangle.red">
			<Setter Property="Fill" Value="Red" />
			<Style.Animations>
				<Animation Duration="0:0:3" IterationCount="INFINITE">
					<KeyFrame Cue="0%">
						<Setter Property="Opacity" Value="0.0" />
					</KeyFrame>
					<KeyFrame Cue="100%">
						<Setter Property="Opacity" Value="1.0"/>
						<Setter Property="RotateTransform.Angle" Value="90.0" />
					</KeyFrame>
				</Animation>
			</Style.Animations>
		</Style>
	</Window.Styles>
	<TabControl>
		<TabItem Header="动画1">
			<Grid RowDefinitions="Auto,*">
				<StackPanel Orientation="Horizontal">
					<TextBlock Text="样式中的关键帧动画,IterationCount 可设置伪指定次数或无限循环" />
				</StackPanel>
				<Rectangle Classes="red" Height="50" Width="50" Grid.Row="1" />
			</Grid>
		</TabItem>
	</TabControl>
</Window>

2.PlaybackDirection 可指定动画方向,相当于WPF 中AutoReverse="true"

PlaybackDirection="AlternateReverse"
描述
Normal (默认)正向播放动画
Reverse 反向播放动画
Alternate 先正向播放动画,然后反向播放
AlternateReverse 先反向播放动画,然后正向播放

3.填充模式

描述
None 动画运行后,值不会保留,也不会在动画延迟时应用第一个值
Forward 最后的插值值将持续保留到目标属性
Backward 在动画延迟时,第一个插值值将显示
Both 将同时应用Forward和Backward行为
<Window 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"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="AvaloniaMVVMDemo.Window1"
        Title="动画" WindowStartupLocation="CenterScreen">
	<Window.Styles>
		<!--在样式中使用动画,Avalonia中动画是通过关键帧来设置的,样式中的关键帧Style.Animations 可设置多个动画-->
		<Style Selector="Rectangle.red">
			<Setter Property="Fill" Value="Red" />
			<Style.Animations>
				<Animation Duration="0:0:3" IterationCount="INFINITE" PlaybackDirection="Reverse">
					<KeyFrame Cue="0%">
						<Setter Property="Opacity" Value="0.0" />
					</KeyFrame>
					<KeyFrame Cue="100%">
						<Setter Property="Opacity" Value="1.0"/>
						<Setter Property="RotateTransform.Angle" Value="90.0" />
					</KeyFrame>
				</Animation>
			</Style.Animations>
		</Style>
	</Window.Styles>
	<TabControl>
		<TabItem Header="动画1">
			<Grid RowDefinitions="Auto,*">
				<StackPanel Orientation="Horizontal">
					<TextBlock Text="样式中的关键帧动画,IterationCount 可设置伪指定次数或无限循环" />
				</StackPanel>
				<Rectangle Classes="red" Height="50" Width="50" Grid.Row="1" />
				
			</Grid>
		</TabItem>
		<TabItem Header="填充模式">
			<Grid RowDefinitions="*,*,*">
				<TextBlock Text="None" HorizontalAlignment="Center" VerticalAlignment="Center"/>
				<TextBlock Text="Forward" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
				<TextBlock Text="Backward/Delay" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
				<Rectangle Grid.Row="0" Height="100" Width="5">
					<Rectangle.Styles>
						<Style Selector="Rectangle">
						   <Setter Property="Fill" Value="Red" />
							<Style.Animations>
								<Animation Duration="0:0:5" IterationCount="Infinite" FillMode="None">
								<KeyFrame Cue="0%">
									<Setter Property="RotateTransform.Angle" Value="0.0" />
								</KeyFrame>
								<KeyFrame Cue="100%">
									<Setter Property="RotateTransform.Angle" Value="360.0" />
								</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
				<Rectangle Grid.Row="1" Height="100" Width="5" >
					<Rectangle.Styles>
						<Style Selector="Rectangle">
							<Setter Property="Fill" Value="Blue" />
							<Style.Animations>
								<Animation Duration="0:0:5" IterationCount="Infinite" FillMode="Forward">
									<KeyFrame Cue="0%">
										<Setter Property="RotateTransform.Angle" Value="0" />
									</KeyFrame>
									<KeyFrame Cue="100%">
										<Setter Property="RotateTransform.Angle" Value="360" />
									</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
				<Rectangle Grid.Row="2" Height="100" Width="5">
					<Rectangle.Styles>
						<Style Selector="Rectangle">
							<Setter Property="Fill" Value="Green" />
							<Style.Animations>
								<Animation Duration="0:0:5" IterationCount="Infinite" FillMode="Backward" Delay="0:0:3">
									<KeyFrame Cue="0%">
										<Setter Property="RotateTransform.Angle" Value="0" />
									</KeyFrame>
									<KeyFrame Cue="100%">
										<Setter Property="RotateTransform.Angle" Value="360" />
									</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
			</Grid>
		</TabItem>
	</TabControl>
</Window>

3.缓动函数

Easing="BounceEaseIn"

<Window 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"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="AvaloniaMVVMDemo.Window1"
        Title="动画" WindowStartupLocation="CenterScreen">
	<Window.Styles>
		<!--在样式中使用动画,Avalonia中动画是通过关键帧来设置的,样式中的关键帧Style.Animations 可设置多个动画-->
		<Style Selector="Rectangle.red">
			<Setter Property="Fill" Value="Red" />
			<Style.Animations>
				<Animation Duration="0:0:3" IterationCount="INFINITE" PlaybackDirection="Reverse">
					<KeyFrame Cue="0%">
						<Setter Property="Opacity" Value="0.0" />
					</KeyFrame>
					<KeyFrame Cue="100%">
						<Setter Property="Opacity" Value="1.0"/>
						<Setter Property="RotateTransform.Angle" Value="90.0" />
					</KeyFrame>
				</Animation>
			</Style.Animations>
		</Style>
	</Window.Styles>
	<TabControl>
		<TabItem Header="动画1">
			<Grid RowDefinitions="Auto,*">
				<StackPanel Orientation="Horizontal">
					<TextBlock Text="样式中的关键帧动画,IterationCount 可设置伪指定次数或无限循环" />
				</StackPanel>
				<Rectangle Classes="red" Height="50" Width="50" Grid.Row="1" />
				
			</Grid>
		</TabItem>
		<TabItem Header="填充模式">
			<Grid RowDefinitions="*,*,*" ColumnDefinitions="*,*">
				<TextBlock Text="None" HorizontalAlignment="Center" VerticalAlignment="Center"/>
				<TextBlock Text="Forward" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
				<TextBlock Text="Backward/Delay" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
				<Rectangle Grid.Row="0" Height="100" Width="5">
					<Rectangle.Styles>
						<Style Selector="Rectangle">
						   <Setter Property="Fill" Value="Red" />
							<Style.Animations>
								<Animation Duration="0:0:5" IterationCount="Infinite" FillMode="None">
								<KeyFrame Cue="0%">
									<Setter Property="RotateTransform.Angle" Value="0.0" />
								</KeyFrame>
								<KeyFrame Cue="100%">
									<Setter Property="RotateTransform.Angle" Value="360.0" />
								</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
				<Rectangle Grid.Row="1" Height="100" Width="5" >
					<Rectangle.Styles>
						<Style Selector="Rectangle">
							<Setter Property="Fill" Value="Blue" />
							<Style.Animations>
								<Animation Duration="0:0:5" IterationCount="Infinite" FillMode="Forward">
									<KeyFrame Cue="0%">
										<Setter Property="RotateTransform.Angle" Value="0" />
									</KeyFrame>
									<KeyFrame Cue="100%">
										<Setter Property="RotateTransform.Angle" Value="360" />
									</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
				<Rectangle Grid.Row="2" Height="100" Width="5">
					<Rectangle.Styles>
						<Style Selector="Rectangle">
							<Setter Property="Fill" Value="Green" />
							<Style.Animations>
								<Animation Duration="0:0:5"  IterationCount="Infinite" FillMode="Backward" Delay="0:0:3">
									<KeyFrame Cue="0%">
										<Setter Property="RotateTransform.Angle" Value="0" />
									</KeyFrame>
									<KeyFrame Cue="100%">
										<Setter Property="RotateTransform.Angle" Value="360" />
									</KeyFrame>
								</Animation>
							</Style.Animations>
						</Style>
					</Rectangle.Styles>
				</Rectangle>
				<Border Grid.Row="0" Grid.Column="1" Width="35" BorderBrush="AliceBlue" BorderThickness="1">
					<Rectangle VerticalAlignment="Bottom">
						<Rectangle.Styles>
							<Style Selector="Rectangle">
									<Setter Property="Fill" Value="Blue" />
									<Setter Property="Height" Value="0" />
								<Style.Animations>
									<Animation Duration="0:0:5" IterationCount="Infinite" Easing="BounceEaseOut">
										<KeyFrame Cue="0%">
											<Setter Property="Height" Value="0" />
										</KeyFrame>
										<KeyFrame Cue="100%">
											<Setter Property="Height" Value="150" />
										</KeyFrame>
									</Animation>
								</Style.Animations>
								
							</Style>
						</Rectangle.Styles>
					</Rectangle>
				</Border>
			</Grid>
		</TabItem>
	</TabControl>
</Window>

过度效果Transition

1.基本过度动画

Avalonia中的过度效果也受CSS动画的很大启发。它们监听目标属性值的任何变化,并根据其参数对变化进行动画处理。可以通过Transitions属性在任何Control上定义过度效果.

  • 在控件中定义Trasition
<TabItem Header="过度效果Transition">
	<Grid RowDefinitions="*,*" ColumnDefinitions="*,*" ShowGridLines="True">
		<Grid.Styles>
			<Style Selector="Rectangle.h1">
				<Setter Property="Height" Value="200" />
				<Setter Property="Width" Value="100" />
				<Setter Property="Fill" Value="Red" />
				<Setter Property="Opacity" Value="0.5" />
			</Style>
			<Style Selector="Rectangle.h1:pointerover">
				<Setter Property="Opacity" Value="1" />
			</Style>
		</Grid.Styles>
		<Rectangle Classes="h1" >
			<Rectangle.Transitions>
				<Transitions>
					<DoubleTransition Property="Opacity" Duration="0:0:0.5" />
				</Transitions>
			</Rectangle.Transitions>
		</Rectangle>
				   
	</Grid>
</TabItem>

每个过度效果都有Property、Delay、Duration和可选的Easing 属性
Property 表示过度效果的目标属性,用于监听和动画处理值
Delay 表示过度效果应用于目标之前的等待时间
Duration 表示过度效果播放的时间长度
缓动函数于关键帧动画中描述相同

以下是可用的过度效果类型。必须根据要动画处理的属性类型选择正确的类型。

  • BoxShadowsTransition:用于BoxShadows目标属性
  • BrushTransition:用于IBrush目标属性
  • ColorTransition:用于Color目标属性
  • CornerRadiusTransition:用于CornerRadius 目标属性
  • DoubleTransitions:用于double 目标属性
  • FloatTransitions:用于float 目标属性
  • IntegerTransitions:用于int目标属性
  • PointTransition:用于Point目标属性
  • SizeTransition:用于Size目标属性
  • ThicknessTransition:用于Thickness目标属性
  • TransformOperationsTransition:用于ITransform目标属性
  • VectorTransition:用于Vector目标属性

TransformOperationsTransition 示例

在指针悬停其上方时旋转45度

可以使用的过度效果如下:

过度效果 示例 可接受的单位
translate translate(10px),translate(0px,10px) px
translateX translateX(10px) px
translateY translateY(10px) px
scale scale(10),scale(0,10)
scaleX scaleX(10)
scaleY scaleY(10)
skew skew(90deg,skew(0,90deg)) deg,grad,rad,turn
skewX skewX(90deg) deg,grad,rad,turn
skewY skewY(90deg) deg,grad,rad,turn
rotate rotate(90deg) deg,grad,rad,turn
matrix matrix(1,2,3,4,5,6)

页面过度动画

TransitioningContentControl 可以使用页面过度来对内部控件上的内容更改进行动画处理

Content 要在控件中显示的内容
TransitioningContentControl.ContentTemplate 用于显示内容的数据模板
TransitioningContentControl.PageTransition 用于对内容更改进行动画处理的页面过度效果。应用的主题将提供默认页面过渡。要禁用转换,请将此属性设置伪null

页面过度动画
CrossFade(默认):跨但如淡出页面过度通过动画方式改变不透明度,从而使当前页面淡出,新页面淡入。
PageSlid:页面滑动过度将旧页面移除视图,并将新页面视图移入。可以使用Orientation属性指定滑动方向(默认为水平)