Condividi tramite


StateContainer

La visualizzazione di una visualizzazione specifica quando l'app è in uno stato specifico è un modello comune in qualsiasi app per dispositivi mobili. Gli esempi variano dalla creazione di visualizzazioni di caricamento alla sovrimpressione sullo schermo o da una sottosezione dello schermo. È possibile creare visualizzazioni di stato vuote per quando non sono presenti dati da visualizzare e visualizzare le visualizzazioni dello stato degli errori quando si verifica un errore.

Introduzione

Le StateContainer proprietà associate consentono all'utente di trasformare qualsiasi elemento di layout come VerticalStackLayout, HorizontalStackLayouto Grid in un layout compatibile con lo stato. Ogni layout compatibile con stato contiene una raccolta di elementi derivati di View. Questi elementi possono essere usati come modelli per stati diversi definiti dall'utente. Ogni volta che la CurrentState proprietà stringa viene impostata su un valore corrispondente alla StateKey proprietà di uno degli elementi View, il relativo contenuto verrà visualizzato anziché il contenuto principale. Quando CurrentState è impostata su null o una stringa vuota, viene visualizzato il contenuto principale.

Nota

Quando si usa StateContainer con , Gridtutti gli stati definiti all'interno si estenderanno automaticamente a ogni riga e colonna dell'oggetto Grid.

Sintassi

StateContainer le proprietà possono essere usate in XAML o C#.

XAML

Inclusione dello spazio dei nomi XAML

Per usare il toolkit in XAML, è necessario aggiungere le informazioni seguenti xmlns nella pagina o nella visualizzazione:

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

Di conseguenza:

<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>

Verrà modificato in modo da includere l'oggetto xmlns come indicato di seguito:

<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>

Uso di StateContainer

Di seguito è riportato un esempio di interfaccia utente creata con XAML. Questa interfaccia utente di esempio è connessa all'oggetto ViewModel seguente, 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>

C# Markup

Di seguito è riportata la stessa interfaccia utente del codice XAML, precedentemente creata con markup C#.

Questa interfaccia utente di esempio è connessa all'oggetto ViewModel seguente, 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.CanStateChange,
    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);
}

Modello di visualizzazione

Quando si usa un ICommand oggetto per modificare CurrentState (ad esempio, quando si usa Button.Command per modificare gli stati), è consigliabile usare CanStateBeChanged per ICommand.CanExecute().

Di seguito è riportato un esempio di MVVM che usa 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;
    }
}

Per impostazione predefinita StateContainer cambia lo stato senza animazione. Per aggiungere un'animazione personalizzata, è possibile usare il ChangeStateWithAnimation metodo :

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);
    }
}

Ecco come funziona in iOS:

StateContainer Animation

Proprietà

StateContainer

Le proprietà StateContainer possono essere usate in qualsiasi Layout elemento che eredita.

Proprietà Type Descrizione
StateViews IList<View> Elementi disponibili View da utilizzare come modelli di stato.
Currentstate string Determina quale View elemento con l'oggetto corrispondente StateKey deve essere visualizzato.

Avviso: CurrentState non può essere modificato mentre è in corso una modifica dello stato
CanStateChange bool Quando true, la CurrentState proprietà può essere modificata. Quando false, non può essere modificato perché è attualmente in fase di modifica.

Avviso: se CurrentState viene modificato quando CanStateChanged è false, viene generata un'eccezione StateContainerException .

StateView

Le proprietà StateView possono essere usate in qualsiasi View elemento che eredita.

Proprietà Type Descrizione
StateKey string Nome dello stato.

Metodi

StateContainer

metodo Argomenti Descrizione
ChangeStateWithAnimation (statico) BindableObject associabile, stringa? state, Animation? beforeStateChange, Animazione? afterStateChange, token CancellationToken Modificare lo stato con l'animazione personalizzata.
ChangeStateWithAnimation (statico) BindableObject associabile, stringa? state, Func<VisualElement, CancellationToken, Task>? beforeStateChange, Func<VisualElement, CancellationToken, Task>? afterStateChange, CancellationToken cancellationToken Modificare lo stato con l'animazione personalizzata.
ChangeStateWithAnimation (statico) BindableObject associabile, stringa? state, cancellationToken token Modificare lo stato usando l'animazione di dissolvenza predefinita.

Esempi

È possibile trovare un esempio di questa funzionalità in azione nell'applicazione di esempio .NET MAUI Community Toolkit.

API

È possibile trovare il codice sorgente per StateContainer over nel repository GitHub di .NET MAUI Community Toolkit.