StateContainer

Wyświetlanie określonego widoku, gdy aplikacja jest w określonym stanie, jest typowym wzorcem w każdej aplikacji mobilnej. Przykłady obejmują tworzenie widoków ładowania wyświetlanych jako nakładka na ekranie lub na części ekranu. Puste widoki stanu można utworzyć, gdy nie ma danych do wyświetlenia, a widoki stanu błędu mogą być wyświetlane po wystąpieniu błędu.

Wprowadzenie

Dołączone właściwości StateContainer pozwalają użytkownikowi przekształcić dowolny element układu, taki jak VerticalStackLayout, HorizontalStackLayout lub Grid, w układ reagujący na stan. Każdy układ uwzględniający stan zawiera zestaw elementów dziedziczących po klasie View. Te elementy mogą być używane jako szablony dla różnych stanów zdefiniowanych przez użytkownika. CurrentState Za każdym razem, gdy właściwość string jest ustawiona na wartość zgodną StateKey z właściwością jednego z elementów Widoku, jego zawartość będzie wyświetlana zamiast zawartości głównej. Gdy CurrentState jest ustawione na null lub pusty ciąg, wyświetlana jest główna treść.

Note

Podczas używania StateContainer z elementem Grid wszystkie zdefiniowane w nim stany będą automatycznie rozciągać się na wszystkie wiersze i kolumny Grid.

Syntax

StateContainer właściwości można używać w języku XAML lub C#.

XAML

Dołączanie przestrzeni nazw XAML

Aby można było używać zestawu narzędzi w języku XAML, należy dodać następujące xmlns elementy do strony lub widoku:

xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

Zatem następujące:

<ContentPage
    x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

</ContentPage>

Zostanie zmodyfikowana w celu uwzględnienia xmlns w następujący sposób:

<ContentPage
    x:Class="CommunityToolkit.Maui.Sample.Pages.MyPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">

</ContentPage>

Korzystanie z elementu StateContainer

Poniżej przedstawiono przykładowy interfejs użytkownika utworzony przy użyciu języka XAML. Ten przykładowy interfejs jest połączony z poniższym obiektem ViewModel, StateContainerViewModel.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="MyProject.MyStatePage"
             BindingContext="StateContainerViewModel">

    <VerticalStackLayout 
        toolkit:StateContainer.CurrentState="{Binding CurrentState}"
        toolkit:StateContainer.CanStateChange="{Binding CanStateChange}">

        <toolkit:StateContainer.StateViews>
            <VerticalStackLayout toolkit:StateView.StateKey="Loading">
                <ActivityIndicator IsRunning="True" />
                <Label Text="Loading Content..." />
            </VerticalStackLayout>
            <Label toolkit:StateView.StateKey="Success" Text="Success!" />
        </toolkit:StateContainer.StateViews>

        <Label Text="Default Content" />
        <Button Text="Change State" Command="{Binding ChangeStateCommand}" />

    </VerticalStackLayout>

</ContentPage>

Znaczniki języka C#

Poniżej znajduje się ten sam interfejs użytkownika co powyższy kod XAML utworzony przy użyciu znaczników języka C#.

Ten przykładowy interfejs użytkownika jest połączony z poniższym obiektem ViewModel, StateContainerViewModel.

using CommunityToolkit.Maui.Layouts;
using CommunityToolkit.Maui.Markup;

BindingContext = new StateContainerViewModel();

Content = new VerticalStackLayout()
{
    new Label()
        .Text("Default Content"),
    
    new Button()
        .Text("Change State")
        .Bind(
            Button.CommandProperty,
            static (StateContainerViewModel vm) => vm.ChangeStateCommand,
            mode: BindingMode.OneTime)
}.Bind(
    StateContainer.CurrentStateProperty,
    static (StateContainerViewModel vm) => vm.CurrentState,
    static (StateContainerViewModel vm, string currentState) => vm.CurrentState = currentState)
 .Bind(
    StateContainer.CanStateChangeProperty,
    static (StateContainerViewModel vm) => vm.CanStateChange,
    static (StateContainerViewModel vm, bool canStateChange) => vm.CanStateChange = canStateChange)
 .Assign(out VerticalStackLayout layout);

var stateViews = new List<View>()
{
    //States.Loading
    new VerticalStackLayout()
    {
        new ActivityIndicator() { IsRunning = true },
        new Label().Text("Loading Content")
    },

    //States.Success
    new Label().Text("Success!")
};

StateView.SetStateKey(stateViews[0], States.Loading);
StateView.SetStateKey(stateViews[1], States.Success);

StateContainer.SetStateViews(layout, stateViews);

static class States
{
    public const string Loading = nameof(Loading);
    public const string Success = nameof(Success);
}

Model widoku

W przypadku używania ICommand do zmiany CurrentState (np. przy użyciu Button.Command do zmiany stanów), zalecamy użycie CanStateBeChanged dla ICommand.CanExecute().

Poniżej znajduje się przykład MVVM korzystający z zestawu narzędzi MVVM Community Toolkit:

[INotifyPropertyChanged]
public partial class StateContainerViewModel
{
    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(ChangeStateCommand))]
    bool canStateChange;

    [ObservableProperty]
    string currentState = States.Loading;

    [RelayCommand(CanExecute = nameof(CanStateChange))]
    void ChangeState()
    {
        CurrentState = States.Success;
    }
}

Domyślnie StateContainer zmienia stan bez animacji. Aby dodać animację niestandardową, możesz użyć ChangeStateWithAnimation metody :

async Task ChangeStateWithCustomAnimation()
{
    var targetState = "TargetState";
    var currentState = StateContainer.GetCurrentState(MyBindableObject);
    if (currentState == targetState)
    {
        await StateContainer.ChangeStateWithAnimation(
            MyBindableObject,
            null,
            (element, token) => element.ScaleTo(0, 100, Easing.SpringIn).WaitAsync(token),
            (element, token) => element.ScaleTo(1, 250, Easing.SpringOut).WaitAsync(token),
            CancellationToken.None);
    }
    else
    {
        await StateContainer.ChangeStateWithAnimation(
            MyBindableObject,
            targetState,
            (element, token) => element.ScaleTo(0, 100, Easing.SpringIn).WaitAsync(token),
            (element, token) => element.ScaleTo(1, 250, Easing.SpringOut).WaitAsync(token),
            CancellationToken.None);
    }
}

W ten sposób działa w systemie iOS:

Animacja StateContainer

Właściwości

StateContainer

Właściwości StateContainer mogą być używane w dowolnym Layout dziedziczącym elemenie.

Majątek Typ Description
StateViews IList<View> Dostępne elementy View używane jako szablony stanów.
Bieżący stan string Określa, który View element z odpowiednim elementem StateKey powinien być wyświetlany.

Ostrzeżenie: CurrentState nie można zmienić, gdy zmiana stanu jest w toku
CanStateChange bool Gdy true, można zmienić właściwość CurrentState. false nie można zmienić, ponieważ jest obecnie zmieniany.

Ostrzeżenie: jeśli parametr CurrentState zostanie zmieniony, gdy parametr CanStateChanged ma wartość false, zgłaszany jest wyjątek StateContainerException.

Widok stanu

Właściwości StateView można używać w dowolnym View dziedziczącym elemecie.

Majątek Typ Description
StateKey string Nazwa stanu.

Methods

StateContainer

Metoda Arguments Description
ChangeStateWithAnimation (statyczna) BindableObject bindable, string? stan, animacja? beforeStateChange, Animacja? afterStateChange, token CancellationToken Zmień stan za pomocą animacji niestandardowej.
ChangeStateWithAnimation (statyczna) BindableObject bindable, string? state, Func<VisualElement, CancellationToken, Task>? beforeStateChange, Func<VisualElement, CancellationToken, Task>? afterStateChange, CancellationToken cancellationToken Zmień stan za pomocą animacji niestandardowej.
ChangeStateWithAnimation (statyczna) BindableObject bindable, string? state, CancellationToken token Zmień stan przy użyciu domyślnej animacji zanikania.

Examples

Przykład tej funkcji można znaleźć w przykładzie przykładowej aplikacji .NET MAUI Community Toolkit Sample Application.

API

Kod źródłowy StateContainer można znaleźć w repozytorium .NET MAUI Community Toolkit GitHub.