StateContainer

Att visa en specifik vy när din app är i ett visst tillstånd är ett vanligt mönster i alla mobilappar. Exempel är allt från att skapa inläsningsvyer till överlägg på skärmen eller på ett underavsnitt av skärmen. Tomma tillståndsvyer kan skapas för när det inte finns några data att visa, och feltillståndsvyer kan visas när ett fel inträffar.

Getting Started

Med StateContainer de bifogade egenskaperna kan användaren omvandla alla layoutelement som ett VerticalStackLayout, HorizontalStackLayouteller Grid till en tillståndsmedveten layout. Varje tillståndsberoende layout innehåller en samling med View-härledda element. Dessa element kan användas som mallar för olika tillstånd som definieras av användaren. När strängegenskapen CurrentState är inställd på ett värde som matchar StateKey egenskapen för ett av elementen Visa, visas innehållet i stället för huvudinnehållet. När CurrentState är inställt på null eller tom sträng visas huvudinnehållet.

Note

När du använder StateContainer med en Grid, sträcker sig alla definierade tillstånd inuti automatiskt över varje rad och kolumn i Grid.

Syntax

StateContainer egenskaper kan användas i XAML eller C#.

XAML

Inklusive XAML-namnområdet

För att kunna använda verktygslådan i XAML måste följande xmlns läggas till på sidan eller vyn:

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

Därför följande:

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

Skulle ändras för att inkludera xmlns på följande sätt:

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

Användning av StateContainer

Nedan visas ett exempel på ett användargränssnitt som skapats med XAML. Det här exempelgränssnittet är anslutet till nedanstående 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>

C#-markup

Nedan visas samma användargränssnitt som XAML ovan som skapats med C# Markup.

Det här exempelgränssnittet är anslutet till nedanstående 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);
}

ViewModel

När du använder en ICommand för att ändra CurrentState (t.ex. när du använder Button.Command för att ändra tillstånd) rekommenderar vi att du använder CanStateBeChanged för ICommand.CanExecute().

Nedan visas ett MVVM-exempel med hjälp av 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;
    }
}

Som standard StateContainer ändras tillståndet utan animering. Om du vill lägga till en anpassad animering kan du använda ChangeStateWithAnimation metoden:

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

Så här fungerar det i iOS:

StateContainer-animering

Egenskaper

StateContainer

StateContainer-egenskaperna kan användas för alla Layout ärvande element.

Fastighet Type Description
StateViews IList<View> View Tillgängliga element som ska användas som tillståndsmallar.
NuvarandeTillstånd string Avgör vilket View element med motsvarande StateKey som ska visas.

Varning: CurrentState kan inte ändras när en tillståndsändring pågår
CanStateChange bool När truekan egenskapen CurrentState ändras. När false, kan det inte ändras eftersom det håller på att ändras.

Varning: Om CurrentState ändras när CanStateChanged är false, utlöses en StateContainerException .

StateView

StateView-egenskaperna kan användas för alla View ärvande element.

Fastighet Type Description
StateKey string Namnet på delstaten.

Methods

StateContainer

Metod Arguments Description
ChangeStateWithAnimation (statisk) BindableObject bindable, string? state, Animation? beforeStateChange, Animation? afterStateChange, CancellationToken token Ändra tillstånd med anpassad animering.
ChangeStateWithAnimation (statisk) BindableObject bindable, string? state, Func<VisualElement, CancellationToken, Task>? beforeStateChange, Func<VisualElement, CancellationToken, Task>? afterStateChange, CancellationToken cancellationToken Ändra tillstånd med anpassad animering.
ChangeStateWithAnimation (statisk) BindableObject bindable, string? state, CancellationToken token Byt tillstånd med den förinställda toningsanimeringen.

Exempel

Du hittar ett exempel på den här funktionen i praktiken i .NET MAUI Community Toolkit Sample Application.

API

Källkoden för StateContainer finns på lagringsplatsen .NET MAUI Community Toolkit GitHub.