StateContainer
Mostrar una vista específica cuando la aplicación está en un estado específico es un patrón común en cualquier aplicación móvil. Algunos ejemplos van desde la creación de vistas de carga para superponer en la pantalla o en una subsección de la pantalla. Se pueden crear vistas de estado vacías para cuando no hay datos que mostrar y las vistas de estado de error se pueden mostrar cuando se produce un error.
Introducción
Las propiedades adjuntas StateContainer
permiten al usuario convertir cualquier elemento de diseño como VerticalStackLayout
, HorizontalStackLayout
, o Grid
en un diseño con reconocimiento de estado. Cada diseño con reconocimiento de estado contiene una colección de elementos derivados de View. Estos elementos se pueden usar como plantillas para diferentes estados definidos por el usuario. Siempre que la propiedad de cadena CurrentState
se establece en un valor que coincida con la propiedad StateKey
de uno de los elementos View, su contenido se mostrará en lugar del contenido principal. Cuando CurrentState
se establece en null
o en una cadena vacía, se muestra el contenido principal.
Nota:
Cuando se usa StateContainer
con un Grid
, los estados definidos dentro de él abarcarán automáticamente todas las filas y columnas de Grid
.
Sintaxis
Las propiedades StateContainer
se pueden usar en XAML o C#.
XAML
Incluir el espacio de nombres XAML
Para usar el kit de herramientas en XAML, es necesario agregar el siguiente xmlns
a la página o vista:
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
Por lo tanto, el siguiente:
<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>
Se modificaría para incluir el xmlns
de la siguiente manera:
<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 de StateContainer
A continuación se muestra un ejemplo de interfaz de usuario creada con XAML. Esta interfaz de usuario de ejemplo está conectada al siguiente 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>
Marcado de C#
A continuación se muestra la misma interfaz de usuario que el XAML anterior, creada con marcado de C#.
Esta interfaz de usuario de ejemplo está conectada al siguiente 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.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);
}
Modelo de vista
Al usar un ICommand
para cambiar CurrentState
(por ejemplo, al usar Button.Command
para cambiar los estados), se recomienda usar CanStateBeChanged
para ICommand.CanExecute()
.
A continuación se muestra un ejemplo de MVVM mediante el Kit de herramientas de la comunidad de 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;
}
}
De forma predeterminada, StateContainer
cambia el estado sin animación. Para agregar una animación personalizada, puede usar el 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);
}
}
Así es como funciona en iOS:
Propiedades
StateContainer
Las propiedades StateContainer se pueden usar en cualquier elemento Layout
heredado.
Propiedad | Tipo | Descripción |
---|---|---|
StateViews | IList<View> |
Los elementos View disponibles que se usarán como plantillas de estado. |
CurrentState | string |
Determina qué elemento View con el correspondiente StateKey se debe mostrar. Advertencia: CurrentState no se puede cambiar mientras un cambio de estado está en curso |
CanStateChange | bool |
Cuando true , se puede cambiar la propiedad CurrentState . Cuando false , no se puede cambiar porque está cambiando actualmente. Advertencia: si CurrentState se cambia cuando CanStateChanged es false , se produce una excepción StateContainerException . |
StateView
Las propiedades StateView se pueden usar en cualquier elemento View
heredado.
Propiedad | Tipo | Descripción |
---|---|---|
StateKey | string |
Nombre del estado. |
Métodos
StateContainer
Método | Argumentos | Descripción |
---|---|---|
ChangeStateWithAnimation (static) | BindableObject bindable, string? state, Animation? beforeStateChange, Animation? afterStateChange, CancellationToken token | Cambiar el estado con una animación personalizada. |
ChangeStateWithAnimation (static) | BindableObject bindable, string? state, Func<VisualElement, CancellationToken, Task>? beforeStateChange, Func<VisualElement, CancellationToken, Task>? afterStateChange, CancellationToken cancellationToken | Cambiar el estado con una animación personalizada. |
ChangeStateWithAnimation (static) | BindableObject bindable, string? state, CancellationToken token | Cambie el estado mediante la animación de atenuación predeterminada. |
Ejemplos
Puede encontrar un ejemplo de esta característica en acción en la Aplicación de muestra del kit de herramientas de la comunidad de .NET MAUI.
API
Puede encontrar el código fuente de StateContainer
en el repositorio de GitHub del Kit de herramientas de la comunidad de .NET MAUI.
.NET MAUI Community Toolkit