Browse Source
add transitioning content control. # Conflicts: # src/Avalonia.Themes.Default/DefaultTheme.xaml # src/Avalonia.Themes.Default/TransitioningContentControl.xamlrelease/0.10.13
committed by
Dan Walmsley
7 changed files with 141 additions and 0 deletions
@ -0,0 +1,96 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using Avalonia.Animation; |
||||
|
using Avalonia.Controls.Templates; |
||||
|
using Avalonia.Threading; |
||||
|
|
||||
|
namespace Avalonia.Controls; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Displays <see cref="ContentControl.Content"/> according to a <see cref="FuncDataTemplate"/>.
|
||||
|
/// Uses <see cref="PageTransition"/> to move between the old and new content values.
|
||||
|
/// </summary>
|
||||
|
public class TransitioningContentControl : ContentControl |
||||
|
{ |
||||
|
private CancellationTokenSource? _lastTransitionCts; |
||||
|
private object? _currentContent; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="PageTransition"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<IPageTransition?> PageTransitionProperty = |
||||
|
AvaloniaProperty.Register<TransitioningContentControl, IPageTransition?>(nameof(PageTransition), |
||||
|
new CrossFade(TimeSpan.FromSeconds(0.125))); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="CurrentContent"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly DirectProperty<TransitioningContentControl, object?> CurrentContentProperty = |
||||
|
AvaloniaProperty.RegisterDirect<TransitioningContentControl, object?>(nameof(CurrentContent), |
||||
|
o => o.CurrentContent); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the animation played when content appears and disappears.
|
||||
|
/// </summary>
|
||||
|
public IPageTransition? PageTransition |
||||
|
{ |
||||
|
get => GetValue(PageTransitionProperty); |
||||
|
set => SetValue(PageTransitionProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the content currently displayed on the screen.
|
||||
|
/// </summary>
|
||||
|
public object? CurrentContent |
||||
|
{ |
||||
|
get => _currentContent; |
||||
|
private set => SetAndRaise(CurrentContentProperty, ref _currentContent, value); |
||||
|
} |
||||
|
|
||||
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
||||
|
{ |
||||
|
base.OnAttachedToVisualTree(e); |
||||
|
|
||||
|
Dispatcher.UIThread.Post(() => UpdateContentWithTransition(Content)); |
||||
|
} |
||||
|
|
||||
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) |
||||
|
{ |
||||
|
base.OnDetachedFromVisualTree(e); |
||||
|
|
||||
|
_lastTransitionCts?.Cancel(); |
||||
|
} |
||||
|
|
||||
|
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) |
||||
|
{ |
||||
|
base.OnPropertyChanged(change); |
||||
|
|
||||
|
if (change.Property == ContentProperty) |
||||
|
{ |
||||
|
Dispatcher.UIThread.Post(() => UpdateContentWithTransition(Content)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Updates the content with transitions.
|
||||
|
/// </summary>
|
||||
|
/// <param name="content">New content to set.</param>
|
||||
|
private async void UpdateContentWithTransition(object? content) |
||||
|
{ |
||||
|
if (VisualRoot is null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_lastTransitionCts?.Cancel(); |
||||
|
_lastTransitionCts = new CancellationTokenSource(); |
||||
|
|
||||
|
if (PageTransition != null) |
||||
|
await PageTransition.Start(this, null, true, _lastTransitionCts.Token); |
||||
|
|
||||
|
CurrentContent = content; |
||||
|
|
||||
|
if (PageTransition != null) |
||||
|
await PageTransition.Start(null, this, true, _lastTransitionCts.Token); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Styles xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
|
<Style Selector="TransitioningContentControl"> |
||||
|
<!-- Set Defaults --> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<ContentPresenter Name="PART_ContentPresenter" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness}" |
||||
|
CornerRadius="{TemplateBinding CornerRadius}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Content="{TemplateBinding CurrentContent}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/> |
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
</Styles> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Styles xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
|
<Style Selector="TransitioningContentControl"> |
||||
|
<!-- Set Defaults --> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<ContentPresenter Name="PART_ContentPresenter" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness}" |
||||
|
CornerRadius="{TemplateBinding CornerRadius}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Content="{TemplateBinding CurrentContent}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/> |
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
</Styles> |
||||
Loading…
Reference in new issue