A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

223 lines
7.9 KiB

using System;
using System.Threading.Tasks;
using Avalonia.Automation;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
namespace Avalonia.Controls
{
/// <summary>
/// Abstract base class for all page types.
/// </summary>
public abstract class Page : TemplatedControl, IHeadered
{
private INavigation? _navigation;
/// <summary>
/// Defines the <see cref="SafeAreaPadding"/> property.
/// </summary>
public static readonly StyledProperty<Thickness> SafeAreaPaddingProperty =
AvaloniaProperty.Register<Page, Thickness>(nameof(SafeAreaPadding), validate: PaddingProperty.ValidateValue);
/// <summary>
/// Defines the <see cref="Header"/> property.
/// </summary>
public static readonly StyledProperty<object?> HeaderProperty =
AvaloniaProperty.Register<Page, object?>(nameof(Header));
/// <summary>
/// Defines the <see cref="Icon"/> property.
/// </summary>
public static readonly StyledProperty<object?> IconProperty =
AvaloniaProperty.Register<Page, object?>(nameof(Icon));
/// <summary>
/// Defines the <see cref="CurrentPage"/> property.
/// </summary>
public static readonly StyledProperty<Page?> CurrentPageProperty =
AvaloniaProperty.Register<Page, Page?>(nameof(CurrentPage));
/// <summary>
/// Defines the <see cref="IsInNavigationPage"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsInNavigationPageProperty =
AvaloniaProperty.Register<Page, bool>(nameof(IsInNavigationPage));
/// <summary>
/// Defines the routed event raised when the system back button is pressed.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> PageNavigationSystemBackButtonPressedEvent =
RoutedEvent.Register<Page, RoutedEventArgs>(
nameof(PageNavigationSystemBackButtonPressed),
RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="Navigation"/> property.
/// </summary>
public static readonly DirectProperty<Page, INavigation?> NavigationProperty =
AvaloniaProperty.RegisterDirect<Page, INavigation?>(
nameof(Navigation),
o => o.Navigation,
(o, v) => o.Navigation = v);
static Page()
{
PageNavigationSystemBackButtonPressedEvent.AddClassHandler<Page>((page, args) =>
{
if (!args.Handled && page.OnSystemBackButtonPressed())
{
args.Handled = true;
return;
}
page.CurrentPage?.RaiseEvent(args);
});
AffectsMeasure<Page>(SafeAreaPaddingProperty);
}
/// <summary>
/// Gets or sets the header content displayed in the navigation bar or tab strip.
/// </summary>
public object? Header
{
get => GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
/// <summary>
/// Gets or sets the icon displayed alongside the page header.
/// </summary>
public object? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
/// <summary>
/// Gets or sets the safe-area padding applied to this page's content.
/// </summary>
public Thickness SafeAreaPadding
{
get => GetValue(SafeAreaPaddingProperty);
set => SetValue(SafeAreaPaddingProperty, value);
}
/// <summary>
/// Gets or sets the currently active child page.
/// </summary>
public Page? CurrentPage
{
get => GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value);
}
/// <summary>
/// Gets or sets the <see cref="INavigation"/> service provided by the parent NavigationPage.
/// </summary>
public INavigation? Navigation
{
get => _navigation;
set => SetAndRaise(NavigationProperty, ref _navigation, value);
}
/// <summary>
/// Gets or sets whether this page is currently hosted inside a NavigationPage.
/// </summary>
public bool IsInNavigationPage
{
get => GetValue(IsInNavigationPageProperty);
set => SetValue(IsInNavigationPageProperty, value);
}
/// <summary>
/// Raised when the system back button is pressed while this page is active.
/// </summary>
public event EventHandler<RoutedEventArgs>? PageNavigationSystemBackButtonPressed
{
add => AddHandler(PageNavigationSystemBackButtonPressedEvent, value);
remove => RemoveHandler(PageNavigationSystemBackButtonPressedEvent, value);
}
/// <summary>
/// Occurs when the page has been navigated to.
/// </summary>
public event EventHandler<NavigatedToEventArgs>? NavigatedTo;
/// <summary>
/// Occurs when the page is about to be navigated from.
/// </summary>
public event Func<NavigatingFromEventArgs, Task>? Navigating;
/// <summary>
/// Occurs when the page has been navigated from.
/// </summary>
public event EventHandler<NavigatedFromEventArgs>? NavigatedFrom;
/// <summary>
/// Called when the page has been navigated to.
/// </summary>
protected virtual void OnNavigatedTo(NavigatedToEventArgs args) => NavigatedTo?.Invoke(this, args);
/// <summary>
/// Called when the page is about to be navigated from.
/// </summary>
protected virtual void OnNavigatingFrom(NavigatingFromEventArgs args) { }
/// <summary>
/// Called when the page has been navigated from.
/// </summary>
protected virtual void OnNavigatedFrom(NavigatedFromEventArgs args) => NavigatedFrom?.Invoke(this, args);
/// <summary>
/// Called when the system back button is pressed.
/// </summary>
/// <returns><see langword="true"/> if the back press was handled.</returns>
protected virtual bool OnSystemBackButtonPressed() => false;
internal void SendNavigatedTo(NavigatedToEventArgs args) => OnNavigatedTo(args);
internal async Task SendNavigatingAsync(NavigatingFromEventArgs args)
{
OnNavigatingFrom(args);
var navigating = Navigating;
if (navigating != null)
{
foreach (Func<NavigatingFromEventArgs, Task> handler in navigating.GetInvocationList())
await handler(args);
}
}
internal void SendNavigatedFrom(NavigatedFromEventArgs args) => OnNavigatedFrom(args);
internal void SetInNavigationPage(bool value) => SetCurrentValue(IsInNavigationPageProperty, value);
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == SafeAreaPaddingProperty || change.Property == PaddingProperty)
UpdateContentSafeAreaPadding();
if (change.Property == HeaderProperty)
AutomationProperties.SetName(this, change.NewValue as string ?? string.Empty);
}
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
UpdateContentSafeAreaPadding();
}
/// <summary>
/// Called when the safe-area padding changes.
/// </summary>
protected virtual void UpdateContentSafeAreaPadding() { }
/// <summary>
/// Called when the active child page changes.
/// </summary>
protected virtual void UpdateActivePage() { }
}
}