M103 - Understanding the Shell Object in .NET MAUI: Benefits, Limitations, and Alternatives
Introduction
.NET MAUI is a cross-platform framework for building applications that run on Android, iOS, macOS, and Windows using a single codebase. One of the key aspects of any application is navigation—the ability to move between different screens or sections efficiently. In .NET MAUI, navigation can be managed using different approaches, with the Shell object being a powerful option for structuring and simplifying navigation and is used by default in new applications.
In this article, we will explore the following topics and by the end you’ll have a better understanding of whether Shell is the right choice for your application and what alternatives exist.
Background
In order to truly understand what the Shell in a .NET MAUI application is and how it works, a little background is helpful. Every application created in .NET MAUI has the following visual tree structure:
When the application is launched, the App.xaml.cs file creates a new Window which requires a page to be passed into its constructor which could either be created with the new syntax or pulled from the dependency injection services collection (if it was configured in the AppBuilder).
Tip: If you are developing an application for a specific mobile platform and device setting the maximum width and height on the window to be the size of the mobile screen before its returned allows your application to have the same size and proportions as your device while debugging it on your development machine. If you are developing for a desktop idiom, this allows you to set the desired size of your application to see how it behaves on different monitor resolutions.
At first glance this might appear to contradict the previous statement for if you look at the AppShell, it inherits from Shell not a page and the Shell.xaml has pointers to the actual pages in the application as ShellContent items. Actually, the Shell does inherit from Page and has a specific layout and functionality to speed up the application development process by creating the top-level menu and navigation structure of your application. It automatically creates and manages a flyout menu (vertical) or tabs (horizontal) for the defined pages in your application and navigates to those pages.
Pages
Besides the Shell, there are four types of pages that MAUI has defined for specific layout and navigation scenarios: Content, Flyout, Navigation, and Tabbed. In the above diagram, each of the page types defines a content area shown in grey where your actual page content will be rendered. ContentPage is the most widely used page in .NET MAUI applications and in fact, if you were to add a new Page to your project, the ContentPage is the only option available. The other pages are simply wrappers around a ContentPage which you would have to create manually or have your page inherit from one of those instead.
In my M101 article, I showed you the sample project and task tracking application that is included in a .NET MAUI application when you choose to included it when creating the project.
The following images show where I combined the Flyout page and Navigation pages together to wrap the Dashboard and ManageMeta pages where the met data page is now in the flyout menu page.
While this is a contrived example, it does show you how you could create a page of the appropriate size and have custom information, menu items and specific commands available as opposed to strictly menu items that navigate to another page. When you understand that the predefined page layouts are building blocks, for layouts and views & controls, it should be easier to see what the Shell is doing for you by adding functionality to automatically populate the menu items and show or hide the flyout menu and easily enable navigation to the root pages.
Views or Pages with custom ControlTemplates
Now that you have a basic understanding of a Page, the next step in the visual tree is layouts and then views. A layout control defines the root of any view and manages how the controls are "arranged" on the page. There are several built in layout controls available in .NET MAUI but if you want more information, the official documentation on Layouts is located here. Layouts In .NET MAUI. As previously mentioned a Layout may contain either more layouts or views and a view is any UI element from Labels to specialized container views like a CollectionView, CarouselView, etc.
A ControlTemplate is used to separate the visual representation of a control from the logic and allows you to change out or define the visual representation of a control (or part of a control). They also allow you to define place holders and use a special form of binding called TemplateBinding to supply content from outside the control that gets injected into the placeholder. This content could be defined either statically in XAML or code or it could also come from databinding techniques. If you were to apply this concept to custom views or pages, you can easily create reusable layouts in your application.
For example, let's just start with a simple two column layout I have defined with a grid and have create two placeholders called Left and Right. I can then easily reuse this in my application to provide a consistent layout experience. Granted, this may be a bit overdone for just a grid, but this is how custom layouts could be defined to any level of detail. Here is the layout in XAML followed by the bindable properties in the code behind.
Recommended by LinkedIn
Then I used my custom layout in my main page and supplied a view (which in this case is actually a simple vertical stack layout) with buttons and labels defined.
The real power comes from when you realize that while I supplied a control and children to each placeholder, I could have just as easily supplied an entire view into either of the Left or Right properties. I could also use triggers or code to change out the views at runtime. Interesting, this sounds a lot like how a Shell has a content section that it swaps out for root navigation pages whether it's from a TabBar or the FlyoutMenu… The Shell does actually place the page in the root of the navigation stack which is independent of the Shell but it displays the current page into the content placeholder.
Why / When to Use Shell?
By now you know the "what": The Shell is simply a custom page that accepts an array of ShellContent items as its content and then it displays these items in either a vertical list (Flyout Menu) or a horizontal list (TabBar). The ShellContent.ContentTemplate defines the page to be displayed in the content region placeholder of the Shell. It is important to remember that because the pages are being created on demand they need to either have a default empty constructor or their dependencies need to be passed into the constructors and the dependencies need to be registered in the services collection when the application is initialized.
In addition to the top level pages defined in the Shell, an application can have additional pages that are displayed (navigated) which can present additional information such as a detail page for a top level page item in a list. There are several ways to perform navigation such as pushing / popping, relative, inserting or removing pages from the stack, etc., and will likely be discussed in more detail in a future article but for additional information, you can refer to the official documentation from Microsoft:
Benefits of Using Shell
The primary purpose of the shell is to allow developers to quickly declare the top-level navigational pages and resulting menu structure and to enable navigation to these pages in a consistent manner across platforms. It is included by default in a new .NET MAUI application and as long as you don't have a need to stray away from its guardrails, it provides the following benefits.
Limitations of Shell
The primary purpose of being an application accelerator and out of the box template also exposes its limitations when your application design needs to do something slightly different. The most noticeable limitations I have come across so far have been related to the flyout menu restrictions, control over page lifecycles and its impact on memory usage for the applications. These limitations came out in an enterprise mobile application used for field technicians. The application had specific requirements about the layout and was quite complex as it had a mixture of root pages, modal popups, and multiple sequences of order completion pages so your experience might vary.
Conclusion
Now that you understand what the shell is and how you can use content presenters and control templates in custom pages or views, you have expanded your available layout and navigation options in your .NET MAUI applications allowing you to:
When your application fits within the guardrails of the shell and its limitations, it can be a boost to the productivity of the developers and the project as a whole but it can also cause a lot of frustration when you discover application crashes when running on the device for a while or when you keep trying to figure out how to make the Shell do something for which it's not intended to meet an application design requirement.
Analyzing your application requirements at the beginning of a project and collaborating with the designers and sponsors could allow you to identify any issues related to the layout and navigation of the application. This can open the door for discussions about compromises that will allow the application to fit within the framework of the Shell or identify areas where you will need to implement your own approach from the beginning because of the limitations of the Shell.
What’s your experience with .NET MAUI navigation? Let me know in the comments!
Modernizing Enterprise Architecture @ Centric | EDA, Cloud, and API Specialist | Builder & Mentor
2moI wish I had this level of explanation and detail when I started with asp.net way back when.