StateContainer
Mostrar uma exibição específica quando seu aplicativo está em um estado específico é um padrão comum de qualquer aplicativo móvel. Os exemplos variam da criação de exibições de carregamento à sobreposição na tela ou em uma subseção dela. Exibições de estado vazias podem ser criadas para quando não há dados a serem exibidos e exibições de estado de erro podem ser mostradas quando ocorre um erro.
Introdução
As propriedades anexadas StateContainer
permitem que o usuário transforme qualquer elemento de layout como um VerticalStackLayout
, HorizontalStackLayout
ou Grid
em um layout com reconhecimento de estado. Cada layout com reconhecimento de estado contém uma coleção de elementos derivados de View. Esses elementos podem ser usados como modelos para diferentes estados definidos pelo usuário. Sempre que a propriedade de cadeia de caracteres CurrentState
for definida como um valor que corresponda à propriedade StateKey
de um dos elementos View, o conteúdo dela será exibido em vez do conteúdo principal. Quando CurrentState
é definido como null
ou como uma cadeia de caracteres vazia, o conteúdo principal é exibido.
Observação
Ao usar StateContainer
com uma Grid
, qualquer estados definido nele abrangerá automaticamente todas as linhas e colunas da Grid
.
Sintaxe
As propriedades StateContainer
podem ser usadas em XAML ou C#.
XAML
Incluir o namespace XAML
Para usar o kit de ferramentas no XAML, o xmlns
a seguir precisa ser adicionado à sua página ou exibição:
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
Portanto, o seguinte:
<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>
Seria modificado para incluir o xmlns
conforme o seguinte:
<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>
Como usar o StateContainer
Veja abaixo um exemplo de interface do usuário criado com o XAML. Este exemplo de interface do usuário está conectado ao ViewModel abaixo, 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>
Markup do C#
Abaixo está a mesma interface do usuário que o XAML criou acima usando a Marcação C#.
Este exemplo de interface do usuário está conectado ao ViewModel abaixo, 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);
}
ViewModel
Ao usar um ICommand
para alterar CurrentState
(por exemplo, ao usar Button.Command
para alterar estados), recomendamos usar CanStateBeChanged
para ICommand.CanExecute()
.
Veja abaixo um exemplo do MVVM com o Kit de Ferramentas da Comunidade do MVVM:
[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;
}
}
Por padrão, StateContainer
altera o estado sem animação. Para adicionar uma animação personalizada, use o método ChangeStateWithAnimation
:
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);
}
}
É assim que ele funciona no iOS:
Propriedades
StateContainer
As propriedades StateContainer podem ser usadas em qualquer elemento herdado Layout
.
Propriedade | Type | Descrição |
---|---|---|
StateViews | IList<View> |
Os elementos View disponíveis a serem usados como modelos de estado. |
CurrentState | string |
Determina qual elemento View com a StateKey correspondente deve ser exibido. Aviso: CurrentState não pode ser alterado enquanto uma alteração de estado está em andamento |
CanStateChange | bool |
Quando ele for true , a propriedade CurrentState poderá ser alterada. Quando ele for false , ela não poderá ser alterada porque ela está sendo alterada no momento. Aviso: se CurrentState for alterado quando CanStateChanged for false , uma StateContainerException será gerada. |
StateView
As propriedades StateView podem ser usadas em qualquer elemento herdado View
.
Propriedade | Type | Descrição |
---|---|---|
StateKey | string |
Nome do estado. |
Métodos
StateContainer
Método | Argumentos | Descrição |
---|---|---|
ChangeStateWithAnimation (estático) | BindableObject bindable, string? state, Animation? beforeStateChange, Animation? afterStateChange, CancellationToken token | Altera o estado com uma animação personalizada. |
ChangeStateWithAnimation (estático) | BindableObject bindable, string? state, Func<VisualElement, CancellationToken, Task>? beforeStateChange, Func<VisualElement, CancellationToken, Task>? afterStateChange, CancellationToken cancellationToken | Altera o estado com uma animação personalizada. |
ChangeStateWithAnimation (estático) | BindableObject bindable, string? state, CancellationToken token | Altera o estado usando a animação de abertura gradual padrão. |
Exemplos
Encontre um exemplo desse recurso em ação no Aplicativo de exemplo do Kit de Ferramentas da Comunidade do .NET MAUI.
API
O código-fonte do StateContainer
pode ser encontrado no repositório GitHub do .NET MAUI Community Toolkit.
.NET MAUI Community Toolkit