增加了动画以及用Style重写了样式。
FlipPanel.cs控制逻辑
using Avalonia; using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using System; namespace AvaloniaUI { [TemplatePart("PART_FrontHost", typeof(Border))] [TemplatePart("PART_BackHost", typeof(Border))] [TemplatePart("PART_FlipButton", typeof(ToggleButton))] public class FlipPanel2 : TemplatedControl { // ========== 依赖属性 ========== public static readonly StyledProperty<Control?> FrontContentProperty = AvaloniaProperty.Register<FlipPanel2, Control?>(nameof(FrontContent)); public static readonly StyledProperty<Control?> BackContentProperty = AvaloniaProperty.Register<FlipPanel2, Control?>(nameof(BackContent)); public static readonly StyledProperty<bool> IsFlippedProperty = AvaloniaProperty.Register<FlipPanel2, bool>(nameof(IsFlipped)); public static readonly StyledProperty<double> FlipAngleProperty = AvaloniaProperty.Register<FlipPanel2, double>(nameof(FlipAngle), 0d); // ========== CLR 包装 ========== public Control? FrontContent { get => GetValue(FrontContentProperty); set => SetValue(FrontContentProperty, value); } public Control? BackContent { get => GetValue(BackContentProperty); set => SetValue(BackContentProperty, value); } public bool IsFlipped { get => GetValue(IsFlippedProperty); set => SetValue(IsFlippedProperty, value); } public double FlipAngle { get => GetValue(FlipAngleProperty); set => SetValue(FlipAngleProperty, value); } // ========== 模板部件 ========== private ToggleButton? flipButton; public FlipPanel2() { // 监听属性变化 this.GetObservable(IsFlippedProperty).Subscribe(_ => { UpdatePseudoClasses(); }); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); flipButton = e.NameScope.Find<ToggleButton>("PART_FlipButton"); if (flipButton != null) flipButton.Click += (_, _) => ToggleFlipped(); UpdatePseudoClasses(); } private void ToggleFlipped() { IsFlipped = !IsFlipped; } private void UpdatePseudoClasses() { PseudoClasses.Set(":flipped", IsFlipped); } } }
FlipPanelAlternateTemplate.axaml代码
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AvaloniaUI" x:Class="AvaloniaUI.FlipPanelAlternateTemplate" Width="350" Height="300"> <Window.Resources> <ControlTemplate x:Key="FancyFlipPanel" TargetType="local:FlipPanel2"> <Grid> <!-- FRONT --> <Border x:Name="PART_FrontHost" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Background="#E3F2FD" RenderTransformOrigin="0.5,0.5"> <ContentPresenter Content="{TemplateBinding FrontContent}" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Border.Styles> <!-- 翻转到背面 --> <Style Selector="local|FlipPanel2:flipped /template/ Border#PART_FrontHost"> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="ScaleTransform.ScaleY" Value="1"/> <Setter Property="BlurEffect.Radius" Value="0"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="ScaleTransform.ScaleY" Value="0"/> <Setter Property="BlurEffect.Radius" Value="30"/> </KeyFrame> </Animation> </Style.Animations> </Style> <!-- 回到正面 --> <Style Selector="local|FlipPanel2:not(:flipped) /template/ Border#PART_FrontHost"> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="ScaleTransform.ScaleY" Value="0"/> <Setter Property="BlurEffect.Radius" Value="30"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="ScaleTransform.ScaleY" Value="1"/> <Setter Property="BlurEffect.Radius" Value="0"/> </KeyFrame> </Animation> </Style.Animations> </Style> </Border.Styles> </Border> <!-- BACK --> <Border x:Name="PART_BackHost" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Background="#FFF3E0" RenderTransformOrigin="0.5,0.5"> <ContentPresenter Content="{TemplateBinding BackContent}" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Border.Styles> <Style Selector="local|FlipPanel2:flipped /template/ Border#PART_BackHost"> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="ScaleTransform.ScaleY" Value="0"/> <Setter Property="BlurEffect.Radius" Value="30"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="ScaleTransform.ScaleY" Value="1"/> <Setter Property="BlurEffect.Radius" Value="0"/> </KeyFrame> </Animation> </Style.Animations> </Style> <Style Selector="local|FlipPanel2:not(:flipped) /template/ Border#PART_BackHost"> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="ScaleTransform.ScaleY" Value="1"/> <Setter Property="BlurEffect.Radius" Value="0"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="ScaleTransform.ScaleY" Value="0"/> <Setter Property="BlurEffect.Radius" Value="30"/> </KeyFrame> </Animation> </Style.Animations> </Style> </Border.Styles> </Border> <!-- 按钮 --> <ToggleButton x:Name="PART_FlipButton" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="5" Padding="10,0" FontSize="14" Content="˄"> <ToggleButton.Styles> <Style Selector="local|FlipPanel2:flipped /template/ ToggleButton#PART_FlipButton"> <Setter Property="Content" Value="˅"/> <Setter Property="VerticalAlignment" Value="Top"/> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="TranslateTransform.Y" Value="150"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="TranslateTransform.Y" Value="0"/> </KeyFrame> </Animation> </Style.Animations> </Style> <Style Selector="local|FlipPanel2:not(:flipped) ToggleButton#PART_FlipButton"> <Setter Property="Content" Value="˄"/> <Setter Property="VerticalAlignment" Value="Bottom"/> <Style.Animations> <Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"> <KeyFrame Cue="0%"> <Setter Property="TranslateTransform.Y" Value="-150"/> </KeyFrame> <KeyFrame Cue="100%"> <Setter Property="TranslateTransform.Y" Value="0"/> </KeyFrame> </Animation> </Style.Animations> </Style> </ToggleButton.Styles> </ToggleButton> </Grid> </ControlTemplate> </Window.Resources> <Grid> <local:FlipPanel2 Template="{StaticResource FancyFlipPanel}" Width="300" Height="200" BorderBrush="DarkOrange" BorderThickness="3" CornerRadius="6" Margin="20"> <local:FlipPanel2.FrontContent> <TextBlock Text="Front Side" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center"/> </local:FlipPanel2.FrontContent> <local:FlipPanel2.BackContent> <TextBlock Text="Back Side" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center"/> </local:FlipPanel2.BackContent> </local:FlipPanel2> </Grid> </Window>
FlipPanelAlternateTemplate.axaml.cs代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Shares.Avalonia;
namespace AvaloniaUI;
public partial class FlipPanelAlternateTemplate : Window
{
public FlipPanelAlternateTemplate()
{
InitializeComponent();
}
}
运行效果

浙公网安备 33010602011771号