From 9dd3d8e7851be34c93498f6c059952535e12d974 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 15 Feb 2022 12:59:21 +0000 Subject: [PATCH] add transitioning content control. --- .../TransitioningContentControl.cs | 70 +++++++++++++++++++ .../Controls/TransitioningContentControl.xaml | 20 ++++++ src/Avalonia.Themes.Default/DefaultTheme.xaml | 1 + .../Controls/FluentControls.xaml | 1 + .../Controls/TransitioningContentControl.xaml | 20 ++++++ 5 files changed, 112 insertions(+) create mode 100644 src/Avalonia.Controls/TransitioningContentControl.cs create mode 100644 src/Avalonia.Themes.Default/Controls/TransitioningContentControl.xaml create mode 100644 src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs new file mode 100644 index 0000000000..d71fb2b90c --- /dev/null +++ b/src/Avalonia.Controls/TransitioningContentControl.cs @@ -0,0 +1,70 @@ +using System; +using System.Threading; +using Avalonia.Animation; + +namespace Avalonia.Controls; + +public class TransitioningContentControl : ContentControl +{ + private CancellationTokenSource? _lastTransitionCts; + + /// + /// Defines the property. + /// + public static readonly StyledProperty PageTransitionProperty = + AvaloniaProperty.Register(nameof(PageTransition), + new CrossFade(TimeSpan.FromSeconds(0.5))); + + + /// + /// Defines the property. + /// + public static readonly StyledProperty DisplayedContentProperty = + AvaloniaProperty.Register(nameof(DisplayedContent)); + + /// + /// Gets or sets the animation played when content appears and disappears. + /// + public IPageTransition? PageTransition + { + get => GetValue(PageTransitionProperty); + set => SetValue(PageTransitionProperty, value); + } + + /// + /// Gets or sets the content displayed whenever there is no page currently routed. + /// + public object? DisplayedContent + { + get => GetValue(DisplayedContentProperty); + set => SetValue(DisplayedContentProperty, value); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == ContentProperty) + { + UpdateContentWithTransition(change.NewValue.GetValueOrDefault()); + } + } + + /// + /// Updates the content with transitions. + /// + /// New content to set. + private async void UpdateContentWithTransition(object? content) + { + _lastTransitionCts?.Cancel(); + _lastTransitionCts = new CancellationTokenSource(); + + if (PageTransition != null) + await PageTransition.Start(this, null, true, _lastTransitionCts.Token); + + DisplayedContent = content; + + if (PageTransition != null) + await PageTransition.Start(null, this, true, _lastTransitionCts.Token); + } +} diff --git a/src/Avalonia.Themes.Default/Controls/TransitioningContentControl.xaml b/src/Avalonia.Themes.Default/Controls/TransitioningContentControl.xaml new file mode 100644 index 0000000000..a1bd660527 --- /dev/null +++ b/src/Avalonia.Themes.Default/Controls/TransitioningContentControl.xaml @@ -0,0 +1,20 @@ + + + diff --git a/src/Avalonia.Themes.Default/DefaultTheme.xaml b/src/Avalonia.Themes.Default/DefaultTheme.xaml index 009b56852a..6d2af1de57 100644 --- a/src/Avalonia.Themes.Default/DefaultTheme.xaml +++ b/src/Avalonia.Themes.Default/DefaultTheme.xaml @@ -38,6 +38,7 @@ + diff --git a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml index 065278521e..16a6cc9c14 100644 --- a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml @@ -37,6 +37,7 @@ + diff --git a/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml b/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml new file mode 100644 index 0000000000..a1bd660527 --- /dev/null +++ b/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml @@ -0,0 +1,20 @@ + + +