{"id":469,"date":"2022-12-11T19:24:28","date_gmt":"2022-12-11T19:24:28","guid":{"rendered":"https:\/\/learnmobiledevelopment.com\/?p=469"},"modified":"2023-01-18T16:37:50","modified_gmt":"2023-01-18T16:37:50","slug":"statecontainer-in-maui","status":"publish","type":"post","link":"https:\/\/learnmobiledevelopment.com\/index.php\/2022\/12\/11\/statecontainer-in-maui\/","title":{"rendered":"How to use StateContainer in MAUI"},"content":{"rendered":"\n<p>The Xamarin.CommunityToolkit&nbsp;<strong><strong><strong>StateContainer<\/strong>&nbsp;in MAUI<\/strong><\/strong>&nbsp;is a layout which displaying a specific view when your app is in a specific state. <strong><strong><strong>StateContainer<\/strong><\/strong><\/strong> is an attached properties which enables the user to turn any layout into a <strong>state-aware<\/strong> layout. In this article, I\u2019m going to show you how to use&nbsp;<strong>StateContainer&nbsp;in MAUI<\/strong>&nbsp;<strong>Community Toolkit<\/strong>.<\/p>\n\n\n\n<p>In this sample demo i will take three different custom states like &#8216;<strong>Loading<\/strong>&#8216;, &#8216;<strong>Empty<\/strong>&#8216; and &#8216;<strong>Success<\/strong>&#8216;<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Loading<\/strong> : Will show before loading users.<br><strong>Empty<\/strong> : Will show when user not available.<br><strong>Success<\/strong> : Will show when user available.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p style=\"font-size:25px\"><strong>Let\u2019s Start<\/strong><\/p>\n\n\n\n<p>In this sample demo we will use&nbsp;<strong><a href=\"https:\/\/www.nuget.org\/packages\/CommunityToolkit.Maui\/\" target=\"_blank\" rel=\"noreferrer noopener\">CommunityToolkit.Maui<\/a><\/strong>&nbsp;nuget package.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>CommunityToolkit.Maui<\/strong><\/p>\n\n\n\n<p>CommunityToolkit.Maui&nbsp;is a collection of Converters, Behaviours, Animations, Custom Views, Effects, Helpers etc. It simplifies the developers task when building Android, iOS, macOS and WinUI applications using MAUI.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>1 \u2013 Install CommunityToolkit.Maui&nbsp;nuget package<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"606\" src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-1024x606.png\" alt=\"Expander in MAUI\" class=\"wp-image-422\" srcset=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-1024x606.png 1024w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-300x178.png 300w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-768x455.png 768w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-1536x909.png 1536w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529-850x503.png 850w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/ExpanderinMAUI-e1670421322529.png 1802w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"><strong>2 &#8211; In order to use the .NET MAUI Community Toolkit you need to call the extension method in your MauiProgram.cs&nbsp;file as follows:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using CommunityToolkit.Maui;\nusing Microsoft.Extensions.Logging;\n\nnamespace MAUIStateContainerLayoutSample;\n\npublic static class MauiProgram\n{\n    public static MauiApp CreateMauiApp()\n    {\n        var builder = MauiApp.CreateBuilder();\n        builder\n            .UseMauiApp&lt;App>()\n            .UseMauiCommunityToolkit()\n            .ConfigureFonts(fonts =>\n            {\n                fonts.AddFont(\"OpenSans-Regular.ttf\", \"OpenSansRegular\");\n                fonts.AddFont(\"OpenSans-Semibold.ttf\", \"OpenSansSemibold\");\n            });\n\n#if DEBUG\n        builder.Logging.AddDebug();\n#endif\n\n        return builder.Build();\n    }\n}<\/pre>\n\n\n\n<p class=\"has-medium-font-size\"><strong>3 \u2013 Setting up the UI<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>3.1 \u2013 Create a MainPage.xaml<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?xml version=\"1.0\" encoding=\"utf-8\" ?>\n&lt;ContentPage\n    x:Class=\"MAUIStateContainerLayoutSample.MainPage\"\n    xmlns=\"http:\/\/schemas.microsoft.com\/dotnet\/2021\/maui\"\n    xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\"\n    xmlns:toolkit=\"http:\/\/schemas.microsoft.com\/dotnet\/2022\/maui\/toolkit\"\n    x:Name=\"MainPageContainer\">\n\n    &lt;ScrollView>\n        &lt;StackLayout Padding=\"20\" Spacing=\"10\">\n\n            &lt;Image\n                HeightRequest=\"150\"\n                HorizontalOptions=\"Center\"\n                SemanticProperties.Description=\"Cute dot net bot waving hi to you!\"\n                Source=\"dotnet_bot.png\">\n\n                &lt;Image.Behaviors>\n                    &lt;toolkit:IconTintColorBehavior TintColor=\"Red\" \/>\n                &lt;\/Image.Behaviors>\n            &lt;\/Image>\n\n            &lt;VerticalStackLayout\n                toolkit:StateContainer.CurrentState=\"{Binding CurrentState}\"\n                toolkit:StateContainer.ShouldAnimateOnStateChange=\"True\"\n                Spacing=\"25\"\n                VerticalOptions=\"CenterAndExpand\">\n\n                &lt;toolkit:StateContainer.StateViews>\n\n                    &lt;!--  Loading State  -->\n                    &lt;VerticalStackLayout toolkit:StateView.StateKey=\"Loading\">\n                        &lt;ActivityIndicator\n                            HeightRequest=\"25\"\n                            HorizontalOptions=\"CenterAndExpand\"\n                            IsRunning=\"True\"\n                            VerticalOptions=\"CenterAndExpand\"\n                            WidthRequest=\"25\"\n                            Color=\"Red\" \/>\n\n                        &lt;Label\n                            HorizontalOptions=\"CenterAndExpand\"\n                            HorizontalTextAlignment=\"Center\"\n                            Text=\"Loading ...\" \/>\n                    &lt;\/VerticalStackLayout>\n\n                    &lt;!--  Empty State  -->\n                    &lt;VerticalStackLayout toolkit:StateView.StateKey=\"Empty\">\n\n                        &lt;Image\n                            HeightRequest=\"200\"\n                            HorizontalOptions=\"Center\"\n                            Source=\"empty.png\" \/>\n\n                    &lt;\/VerticalStackLayout>\n\n                    &lt;!--  Success State  -->\n                    &lt;StackLayout\n                        toolkit:StateView.StateKey=\"Success\"\n                        BindableLayout.ItemsSource=\"{Binding UserList}\"\n                        HorizontalOptions=\"FillAndExpand\"\n                        VerticalOptions=\"FillAndExpand\">\n                        &lt;BindableLayout.ItemTemplate>\n                            &lt;DataTemplate>\n                                &lt;Frame Padding=\"5\" CornerRadius=\"0\">\n                                    &lt;StackLayout\n                                        Padding=\"10\"\n                                        HorizontalOptions=\"FillAndExpand\"\n                                        Orientation=\"Horizontal\"\n                                        VerticalOptions=\"FillAndExpand\">\n                                        &lt;Label\n                                            x:Name=\"UserName\"\n                                            HorizontalOptions=\"FillAndExpand\"\n                                            Text=\"{Binding .}\"\n                                            TextColor=\"Black\" \/>\n                                        &lt;Frame\n                                            Padding=\"7\"\n                                            CornerRadius=\"15\"\n                                            HeightRequest=\"30\"\n                                            HorizontalOptions=\"EndAndExpand\"\n                                            WidthRequest=\"30\">\n                                            &lt;Image Source=\"delete.png\" \/>\n                                            &lt;Frame.GestureRecognizers>\n                                                &lt;TapGestureRecognizer Command=\"{Binding BindingContext.DeleteUserCommand, Source={x:Reference MainPageContainer}}\" CommandParameter=\"{Binding .}\" \/>\n                                            &lt;\/Frame.GestureRecognizers>\n                                        &lt;\/Frame>\n                                    &lt;\/StackLayout>\n                                &lt;\/Frame>\n                            &lt;\/DataTemplate>\n                        &lt;\/BindableLayout.ItemTemplate>\n                    &lt;\/StackLayout>\n\n                &lt;\/toolkit:StateContainer.StateViews>\n            &lt;\/VerticalStackLayout>\n\n            &lt;Entry\n                Placeholder=\"Type name\"\n                Text=\"{Binding User}\"\n                VerticalOptions=\"EndAndExpand\" \/>\n\n            &lt;Button\n                Margin=\"0,10,0,0\"\n                Command=\"{Binding AddUserCommand}\"\n                HorizontalOptions=\"CenterAndExpand\"\n                Text=\"Add User\" \/>\n\n        &lt;\/StackLayout>\n\n    &lt;\/ScrollView>\n\n&lt;\/ContentPage><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As in the above <strong>MainPage.xaml<\/strong> i have used three different views for <strong>Loading state<\/strong>, <strong>Empty state <\/strong>and <strong>Success state<\/strong> and each view uniquely identified by <strong>StateKey<\/strong>. <\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CurrentState<\/strong> property determines which&nbsp;view with the corresponding <strong>StateKey<\/strong>&nbsp;should be displayed. <strong>CurrentState<\/strong> is binded with <strong>CurrentState<\/strong> string property in <strong>MainPageViewModel.cs<\/strong> so that state can be changed at runtime.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ShouldAnimateOnStateChange<\/strong> property is used for enabling fade out\/in animation while switching between states.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size\"><strong>4 &#8211; Setting up the ViewModel<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>4.1 &#8211; Create a MainPageViewModel.cs class<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections.Generic;\nusing System.Collections.ObjectModel;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Input;\n\nnamespace MAUIStateContainerLayoutSample\n{\n    public class MainPageViewModel : INotifyPropertyChanged\n    {\n        public event PropertyChangedEventHandler PropertyChanged;\n        public ICommand AddUserCommand { get; set; }\n        public ICommand DeleteUserCommand { get; set; }\n\n        private ObservableCollection&lt;string> _list;\n        public ObservableCollection&lt;string> UserList\n        {\n            get => _list;\n            set\n            {\n                _list = value;\n                OnPropertyChanged();\n            }\n        }\n\n        private string _state = \"Loading\";\n        public string CurrentState\n        {\n            get => _state;\n            set\n            {\n                _state = value;\n                OnPropertyChanged();\n            }\n        }\n\n        private string _user;\n        public string User\n        {\n            get => _user;\n            set\n            {\n                _user = value;\n                OnPropertyChanged();\n            }\n        }\n\n        public MainPageViewModel()\n        {\n            AddUserCommand = new Command(() =>\n            {\n                Application.Current.Dispatcher.Dispatch(() =>\n                {\n                    if (!string.IsNullOrEmpty(User))\n                    {\n                        UserList.Add(User);\n\n                        if (UserList.Count > 0)\n                        {\n                            CurrentState = \"Success\";\n                        }\n\n                        User = string.Empty;\n                    }\n                });\n            });\n\n            DeleteUserCommand = new Command&lt;string>((user) =>\n            {\n                Application.Current.Dispatcher.Dispatch(() =>\n                {\n                    if (!string.IsNullOrEmpty(user))\n                    {\n                        UserList.Remove(user);\n\n                        if (UserList.Count &lt;= 0)\n                        {\n                            CurrentState = \"Empty\";\n                        }\n                    }\n                });\n            });\n\n            \/\/ Load list after 5 Second\n            Task.Delay(5000).ContinueWith(t => GetList());\n        }\n\n        private void GetList()\n        {\n            UserList = new ObservableCollection&lt;string>()\n            {\n                \"User 1\",\n                \"User 2\",\n                \"User 3\",\n                \"User 4\",\n            };\n\n            \/\/ Change current state from \"Loading\" to \"Success\"\n            CurrentState = \"Success\";\n        }\n\n        private void OnPropertyChanged([CallerMemberName] string propertyName = null)\n        {\n            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n        }\n    }\n}<\/pre>\n\n\n\n<p>Now, We have completed the coding, Let\u2019s try to run the application.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>5 &#8211; Result<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"2796\" style=\"aspect-ratio: 1290 \/ 2796;\" width=\"1290\" controls src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/12\/StateContainerInMAUI.mp4\"><\/video><\/figure>\n\n\n\n<p>That\u2019s all for now!<\/p>\n\n\n\n<p>You can check the full source code <strong><a href=\"https:\/\/github.com\/Alam-Ashraf\/MAUIStateContainerLayoutSample\" target=\"_blank\" rel=\"noopener\" title=\"\">here<\/a>.<\/strong><\/p>\n\n\n\n<p>Happy Coding!<strong> \ud83d\ude00<\/strong><\/p>\n\n\n\n<div style=\"height:35px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>You may also like<\/strong><\/p>\n\n\n\n<div class=\"wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex\">\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/learnmobiledevelopment.com\/index.php\/2022\/11\/22\/collectionview-as-a-griditemlayout\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid-1024x1012.png\" alt=\"Collectionview as a GridItemLayout\" class=\"wp-image-261\" width=\"512\" height=\"506\" srcset=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid-1024x1012.png 1024w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid-300x297.png 300w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid-768x759.png 768w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid-850x840.png 850w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/CollectionViewUsedAsGrid.png 1230w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\">How to use CollectionView as a GridItemLayout in Xamarin Forms<\/p>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\">\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\"><div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/learnmobiledevelopment.com\/index.php\/2022\/11\/20\/rotate-views-on-orientation-change\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation-1024x576.png\" alt=\"Rotate views on orientation change\" class=\"wp-image-181\" width=\"512\" height=\"288\" srcset=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation-1024x576.png 1024w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation-300x169.png 300w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation-768x432.png 768w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation-850x478.png 850w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2022\/11\/ScreenBothRotation.png 1224w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\">How to rotate views on orientation change in Xamarin Forms<\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Xamarin.CommunityToolkit&nbsp;StateContainer&nbsp;in MAUI&nbsp;is a layout which displaying a specific view when your app is in a specific state. StateContainer is an attached properties which enables the user to turn any layout into a state-aware layout. In this article, I\u2019m going to show you how to use&nbsp;StateContainer&nbsp;in MAUI&nbsp;Community Toolkit. In this sample demo i will take&#8230;<\/p>\n","protected":false},"author":1,"featured_media":481,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[4],"tags":[36,35,34],"class_list":["post-469","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnetmaui","tag-statecontainer-in-net-maui","tag-statecontainer-in-maui","tag-xamarin-communitytoolkit"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/469","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/comments?post=469"}],"version-history":[{"count":16,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/469\/revisions"}],"predecessor-version":[{"id":748,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/469\/revisions\/748"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/media\/481"}],"wp:attachment":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/media?parent=469"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/categories?post=469"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/tags?post=469"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}