StateView.Maui
1.0.0
See the version list below for details.
dotnet add package StateView.Maui --version 1.0.0
NuGet\Install-Package StateView.Maui -Version 1.0.0
<PackageReference Include="StateView.Maui" Version="1.0.0" />
<PackageVersion Include="StateView.Maui" Version="1.0.0" />
<PackageReference Include="StateView.Maui" />
paket add StateView.Maui --version 1.0.0
#r "nuget: StateView.Maui, 1.0.0"
#:package StateView.Maui@1.0.0
#addin nuget:?package=StateView.Maui&version=1.0.0
#tool nuget:?package=StateView.Maui&version=1.0.0
StateView.Maui
Description
StateView.Maui is a .NET MAUI control for showing loading, saving, success, error, empty, and custom UI states around normal page content.
The main control, StateView, keeps your regular content in place and swaps in templated state content when CurrentState changes. State UI is defined with DataTemplate instances, so state views are created fresh when rendered.
Features
- Built-in states:
None,Loading,Saving,Success,Error,Empty, andCustom. - Template-based state UI through
StateTemplate. - Custom state matching with
CurrentCustomStateKeyandCustomStateKey. - Repeated skeleton rows with
RepeatCountandRepeatTemplate. - Lightweight pulsing
SkeletonViewfor loading placeholders. - Optional fade transitions through
AnimateStateChangesandAnimationDuration. StateToBooleanConverterfor binding state values to boolean UI properties.
Installation
dotnet add package StateView.Maui --version 1.0.0
Use the XAML namespace in pages that render StateView.Maui controls:
xmlns:state="clr-namespace:StateView.Maui;assembly=StateView.Maui"
Usage
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:state="clr-namespace:StateView.Maui;assembly=StateView.Maui">
<state:StateView CurrentState="{Binding CurrentState}">
<state:StateView.StateTemplates>
<state:StateTemplate StateKey="Loading">
<state:StateTemplate.Template>
<DataTemplate>
<VerticalStackLayout Padding="24" Spacing="12" HorizontalOptions="Center" VerticalOptions="Center">
<ActivityIndicator IsRunning="True" />
<Label Text="Loading..." HorizontalTextAlignment="Center" />
</VerticalStackLayout>
</DataTemplate>
</state:StateTemplate.Template>
</state:StateTemplate>
<state:StateTemplate StateKey="Empty">
<state:StateTemplate.Template>
<DataTemplate>
<Label
Padding="24"
Text="No items found."
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</DataTemplate>
</state:StateTemplate.Template>
</state:StateTemplate>
</state:StateView.StateTemplates>
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="12">
<Label Text="{Binding Title}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</state:StateView>
</ContentPage>
State.None shows the normal content. Any other state looks for the first matching StateTemplate. If no template matches, the normal content remains visible.
ViewModel
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using StateView.Maui;
public sealed class ItemsViewModel : INotifyPropertyChanged
{
private State _currentState = State.Loading;
public event PropertyChangedEventHandler? PropertyChanged;
public ObservableCollection<Item> Items { get; } = [];
public State CurrentState
{
get => _currentState;
set => SetProperty(ref _currentState, value);
}
public async Task LoadAsync()
{
CurrentState = State.Loading;
await Task.Delay(500);
Items.Clear();
CurrentState = Items.Count == 0 ? State.Empty : State.None;
}
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
{
return;
}
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public sealed record Item(string Title);
Custom States
Use State.Custom when one state slot needs multiple named templates. Set CurrentCustomStateKey on StateView, then match it with CustomStateKey on a StateTemplate.
<state:StateView
CurrentState="{Binding CurrentState}"
CurrentCustomStateKey="{Binding CurrentCustomStateKey}">
<state:StateView.StateTemplates>
<state:StateTemplate StateKey="Custom" CustomStateKey="Offline">
<state:StateTemplate.Template>
<DataTemplate>
<Border Padding="20">
<Label Text="Offline mode is active." />
</Border>
</DataTemplate>
</state:StateTemplate.Template>
</state:StateTemplate>
</state:StateView.StateTemplates>
<CollectionView ItemsSource="{Binding Items}" />
</state:StateView>
CurrentCustomStateKey = "Offline";
CurrentState = State.Custom;
Skeleton And Repeat Templates
SkeletonView is a pulsing BoxView placeholder. For repeated loading rows, set RepeatCount and provide a RepeatTemplate.
<state:StateTemplate StateKey="Loading" RepeatCount="5">
<state:StateTemplate.RepeatTemplate>
<DataTemplate>
<Grid Padding="16" RowDefinitions="20,14" RowSpacing="10">
<state:SkeletonView />
<state:SkeletonView Grid.Row="1" WidthRequest="190" HorizontalOptions="Start" />
</Grid>
</DataTemplate>
</state:StateTemplate.RepeatTemplate>
</state:StateTemplate>
When RepeatCount is greater than 1, repeated content is created from RepeatTemplate. If RepeatTemplate is missing, no repeated placeholder content is created.
Animated Transitions
State changes fade by default. Use AnimateStateChanges to enable or disable transitions and AnimationDuration to control the fade duration in milliseconds.
<state:StateView
AnimateStateChanges="True"
AnimationDuration="250"
CurrentState="{Binding CurrentState}">
<CollectionView ItemsSource="{Binding Items}" />
</state:StateView>
Rapid state changes are coordinated so obsolete transitions are cancelled before the latest state is applied.
Why
State-heavy screens often need loading, empty, error, success, and custom overlays without scattering conditional UI across the page. StateView.Maui keeps that logic in one control while leaving each state fully templated and app-specific.
Sample App
The sample app is in SAMPLE/StateView.Maui.Sample.
It demonstrates Loading, Empty, Error, Success, Custom/Offline, skeleton placeholders, animated transitions, and rapid state changes.
Build
dotnet restore StateView.Maui.sln
dotnet build StateView.Maui/StateView.Maui.csproj -f net10.0-android
dotnet build StateView.Maui/StateView.Maui.csproj -f net10.0-ios
dotnet build StateView.Maui/StateView.Maui.csproj -f net10.0-maccatalyst
Requirements
- .NET MAUI with .NET 10.
- Supported target frameworks:
net10.0-android,net10.0-ios, andnet10.0-maccatalyst. - Android API level 23 or later.
- iOS 15.0 or later.
- Mac Catalyst 15.0 or later.
Known Limitations
- The attached property compatibility layer is not included in v1.
- This is not a drop-in replacement for Xamarin.Forms.StateSquid.
- Windows is not included.
- Advanced theme and preset skeleton APIs are not included.
License
StateView.Maui is released under the MIT License. See the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-android36.0 is compatible. net10.0-ios26.0 is compatible. net10.0-maccatalyst26.0 is compatible. |
-
net10.0-android36.0
- Microsoft.Maui.Controls (>= 10.0.0)
-
net10.0-ios26.0
- Microsoft.Maui.Controls (>= 10.0.0)
-
net10.0-maccatalyst26.0
- Microsoft.Maui.Controls (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.