Maui
Maui copied to clipboard
[Proposal] StateLayout
StateLayout
- [x] Proposed
- [ ] Prototype: Not Started
- [ ] Implementation: Not Started
- [ ] iOS Support
- [ ] Android Support
- [ ] macOS Support
- [ ] Windows Support
- [ ] Unit Tests: Not Started
- [ ] Sample: Not Started
- [ ] Documentation: Not Started
Summary
Displaying a specific view when your app is in a specific state is a common pattern throughout any mobile app. Examples range from creating loading views to overlay on the screen, or on a subsection of the screen. Empty state views can be created for when there's no data to display, and error state views can be displayed when an error occurs.
Detailed Design
StateLayout.shared.cs
public static class StateLayout
{
public static readonly BindableProperty StateViewsProperty;
public static readonly BindableProperty CurrentStateProperty;
public static readonly BindableProperty CurrentCustomStateKeyProperty;
public static readonly BindableProperty AnimateStateChangesProperty;
public static IList<StateView>? GetStateViews(BindableObject b);
public static void SetCurrentState(BindableObject b, LayoutState value);
public static LayoutState GetCurrentState(BindableObject b);
public static void SetCurrentCustomStateKey(BindableObject b, string value);
public static string? GetCurrentCustomStateKey(BindableObject b);
public static void SetAnimateStateChanges(BindableObject b, bool value);
public static bool GetAnimateStateChanges(BindableObject b);
}
Usage Syntax
XAML Usage
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="MyLittleApp.MainPage">
<Grid xct:StateLayout.CurrentState="{Binding CurrentState}">
<xct:StateLayout.StateViews>
<xct:StateView StateKey="Loading">
<Grid BackgroundColor="White">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<ActivityIndicator Color="#1abc9c" />
<Label Text="Loading..." HorizontalOptions="Center" />
</StackLayout>
</Grid>
</xct:StateView>
</xct:StateLayout.StateViews>
...
</Grid>
</ContentPage>
What would be the difference with using a ContentTemplate in conbination with Style data triggers binding to a state model?
@peirens-bart do you have a mini prototype of this using MVVM?
@aherrick yes i can, the content off the page will change from red header to blue header based on a property in the viewmodel my viewmodel would be somthing like
public class MainPageViewModel : INotifyPropertyChanged
{
private string _titel;
public string Title
{
get { return _titel; }
set { SetProperty(ref _titel, value); }
}
private int _state = 0;
public int State
{
get { return _state; }
set { SetProperty(ref _state , value); }
}
public ICommand SwitStateCommand { get; }
private void SwitchState()
{
State = State == 0 ? 1 : 0;
}
public MainPageViewModel()
{
Title = "State layout demo";
State = 0;
SwitStateCommand = new Command(SwitchState);
}
}
then in my view I can do
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StateLayoutDemo.MainPage">
<ContentPage.Resources>
<ControlTemplate x:Key="Alert">
<StackLayout>
<Frame BackgroundColor="Red" Padding="24" CornerRadius="0">
<Label Text="{TemplateBinding BindingContext.Title}" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
</Frame>
<Label Text="Alert state" FontSize="Title" Padding="30,10,30,10" HorizontalOptions="CenterAndExpand"/>
<Button Command="{TemplateBinding BindingContext.SwitStateCommand}" Text="To Info"/>
</StackLayout>
</ControlTemplate>
<ControlTemplate x:Key="Info">
<StackLayout>
<Frame BackgroundColor="Blue" Padding="24" CornerRadius="0">
<Label Text="{TemplateBinding BindingContext.Title}" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
</Frame>
<Label Text="Info state" FontSize="Title" Padding="30,10,30,10" HorizontalOptions="CenterAndExpand"/>
<Button Command="{TemplateBinding BindingContext.SwitStateCommand}" Text="To Alert"/>
</StackLayout>
</ControlTemplate>
</ContentPage.Resources>
<ContentView >
<ContentView.Style>
<Style TargetType="ContentView">
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="1" TargetType="ContentView">
<Setter Property="ControlTemplate" Value="{StaticResource Alert}"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="ControlTemplate" Value="{StaticResource Info}"/>
</Style>
</ContentView.Style>
</ContentView>
</ContentPage>
I'm doing it with a slightly modified version if it helps someone in the future!
<ContentPage.BindingContext>
<viewmodels:MainPageViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ContentView x:Key="Alert">
<StackLayout>
<tab:SfTabView
IndicatorBackground="#6200EE"
SelectionChanged="TabBar_SelectedIndexChanged"
TabWidthMode="SizeToContent">
<tab:SfTabItem Header="Calls" TextColor="White">
<tab:SfTabItem.Content>
<Label Text="hall" />
</tab:SfTabItem.Content>
</tab:SfTabItem>
<tab:SfTabItem Header="of" TextColor="White">
<tab:SfTabItem.Content>
<Label Text="of" />
</tab:SfTabItem.Content>
</tab:SfTabItem>
<tab:SfTabItem Header="Halls" TextColor="White">
<tab:SfTabItem.Content>
<Label Text="calls" />
</tab:SfTabItem.Content>
</tab:SfTabItem>
</tab:SfTabView>
</StackLayout>
</ContentView>
<ContentView x:Key="Info">
<StackLayout>
<Label Text="bye" />
</StackLayout>
</ContentView>
</ContentPage.Resources>
<StackLayout>
<Button Command="{Binding SwitStateCommand}" Text="Switch" />
<ContentView x:Name="Body">
<ContentView.Content>
<ContentView />
</ContentView.Content>
<ContentView.Triggers>
<DataTrigger
Binding="{Binding Source={x:Reference Body}, Path=BindingContext.LayoutState}"
TargetType="{x:Type ContentView}"
Value="{x:Static models:LayoutState.Empty}">
<Setter Property="Content" Value="{StaticResource Info}" />
</DataTrigger>
<DataTrigger
Binding="{Binding Source={x:Reference Body}, Path=BindingContext.LayoutState}"
TargetType="{x:Type ContentView}"
Value="{x:Static models:LayoutState.Error}">
<Setter Property="Content" Value="{StaticResource Alert}" />
</DataTrigger>
</ContentView.Triggers>
</ContentView>
</StackLayout>
public partial class MainPageViewModel : ObservableObject
{
[ObservableProperty]
private string title;
[ObservableProperty]
private LayoutState layoutState = LayoutState.Empty;
[ICommand]
private void SwitState()
{
LayoutState = LayoutState == LayoutState.Empty ? LayoutState.Error : LayoutState.Empty;
}
public MainPageViewModel()
{
Title = "State layout demo";
}
}
@aherrick Thank you for the input.
Do you currently have an implementation in your own codebase? If so is this something you would be willing to contribute to the toolkit?
This is not going to be implemented as in Xamarin?
This is not going to be implemented as in Xamarin?
It will be implemented at some point.
We would love your help writing the code! The Community Toolkit contains features for, and created by, the .NET MAUI Community. We are all volunteers, contributing code in our spare time on nights and weekends. If you'd like to contribute, you can learn more here: https://devblogs.microsoft.com/dotnet/contributing-to-net-maui-community-toolkit/
@bijington i dont mind looking at implementing this, is the implementation pretty much the same as whats in the xamarin toolkit?
@IeuanWalker you are a star! If you are up for the challenge that would be fantastic!
I believe the implementation would be similar but of course feel free to investigate whether there are better ways of achieving this either from the old approach or if .NET MAUI offers alternative ways of doing things. I usually like to start by looking at the open issues on the XCT to see if there are any obvious things we need to consider. I'm not sure there is much there that should effect the implementation though.
If you are ever unsure then please feel free to reach out and someone of the team can offer as much guidance as you need.
@bijington great, thanks.
Will take a look into it soon.
@bijington where should the code be placed, Maui project or Maui.Core?
@IeuanWalker, if you need to use anything from the namespace Maui.Controls it should be on Maui project. I would say, since this is a Layout, you can implement it inside the Maui project
Also, be aware that we don't use anything from the Compatibility layer.
@pictos no prob, im getting this error, only suggestion in VS is to add using Microsoft.Maui.Controls.Compatibility;
Do you know what i could change it too?

So, the layout system has changed on MAUI, you need to look and see what Layout<View> become. I think is no more generic layouts on MAUI. Maybe ILayout?
@bijington where should the code be placed,
Mauiproject orMaui.Core?
You can see UniformItemsLayout as example.
@IeuanWalker sorry from reading the comments it looks like I was wrong to suggest that the implementation wouldn't be too different from XCT. Thanks @pictos and @VladislavAntonyuk for helping out there.
@bijington ahh no prob
any news about this?
Hi guys - this is a fantastic component - will it make it Maui toolkit? any news?
@angelru , @developer9969 would you like to implement it?
@VladislavAntonyuk Hi there I really appreciate the time you guys give up to give us this wonderful library. I dont feel like I could do a as a good job as you guys!!
One thing I noticed that the Xamarin toolkit was a huge massive success!! And Microsoft at the time was keen for this library to be a success so that they could offload some components that the public contributors had spend months to build and all of sudden "BOOM" they were dropped!.
Some outstanding developers have contributed to the xamarin toolkit but noticed that they have all dropped now. Pity . And they prefer write components in their own space rather than contribute here . Why do you think??
Again - I could hardly demand as A) I am not a contributor B) you do it for free!!!! VERY GRATEFUL! but seems that the emphasis is to publish quick wins rather than the components that made the xamarin toolkit great!.
Do you think that you could streamline the pull request process - Champion concept and so on... In some social media , honestly dont remember which one they were some couple of well know devs that complained about the all process. I might as well talk nonsense here and apologies but all I am saying here is that I want this to be a huge success , and avoid picking up nugets here there and everywhere..
I will look and see if I can contribute and try to build in .net maui in isolation and when done and if done I will publish for review. Anyway Great job guys.. Give us some cool stuff
Hey @developer9969, Addressing your comments...
I dont feel like I could do a as a good job as you guys!!
I'm 10000000% sure that you can do a great job! I mean, if my code pass the review process anyone can do it as well, and better!
Some outstanding developers have contributed to the xamarin toolkit but noticed that they have all dropped now. Pity . And they prefer write components in their own space rather than contribute here . Why do you think??
Devs that contributed to this project (during the Xamarin era and now) are still contributing. Devs that donate their feature to us will not create new ones, and still, give us some help improving those features. I've no idea why devs want to create their own libs instead of adding those here, maybe they want to rule their releases and how the project goes (?). IMHO this isn't a bad thing, I really love to see that we aren't the only lib that provides great components for .NET MAUI.
Do you think that you could streamline the pull request process - Champion concept and so on... In some social media , honestly dont remember which one they were some couple of well know devs that complained about the all process. I might as well talk nonsense here and apologies but all I am saying here is that I want this to be a huge success , and avoid picking up nugets here there and everywhere..
I agree with this, but this is just part of the picture. So let me expand this a little bit... Yeah, our process now is slower and "bureaucratic" (not sure if this is the best word to describe it), but with this process, we could improve our quality at the highest level. On XCT our docs suck, just a few of our features have docs and that is terrible for new users. Now we make sure to write docs before merging any PR, we demand unit tests (when it's possible), we have just a few bugs opened and we can track and fix them much more quickly than before. And as you mentioned we do this in our free time (as core team members) and we have soo much responsibility. So we need to review PRs, guide new contributors, review/write docs, triage issues, and do the Standup. And after all, we need to fix bugs and port the features from XCT to here. I mean, we love what we do, but it's a lot of work and if we don't have the community helping us we will take a lot of time to port everything from XCT with the most high quality. So at the end of the day, having this process helps us to keep track of all features and make sure everything is in place to provide an amazing package to everyone in the community.
I will look and see if I can contribute and try to build in .net maui in isolation and when done and if done I will publish for review. Anyway Great job guys.. Give us some cool stuff
Please do that, and help us to improve this package!
@VladislavAntonyuk I have not created StateLayout, I do not know if it is ethical for me to include it.
@angelru we appreciate if you would implement it. If the person who initially implemented it have any improvements he will add them in PR comments or open a new PR.
Hi all, I poked at this a bit and managed to port a version working well in MAUI. I'd be happy to take on this issue and submit a PR later this week.
Usage is pretty much identical to the XCT StateLayout. I switched references from Layout<View> to Layout (from Microsoft.Maui.Controls) that seemed like the right move, and a number of other tweaks and small refactors.
https://user-images.githubusercontent.com/5668079/193946437-590819b9-0ab8-4ce8-837d-5870d4beb1eb.mp4
@nicjay that's great, is the code open source? Are you able to open a PR on our repo, that way we can review it?
Reopening Proposal.
Only Proposals moved to the Closed Project Column and Completed Project Column can be closed.