Our application is going to have a main dashboard where all the operations of the authenticated user occur. You may also refer to this type of page as the main page or an application shell. In our application we will call it the dashboard, which is going to be our first deep dive into layout and menus. In Uno Platform you have several different ways to build your view stack and menus. In this chapter we are going to highlight some of the standard techniques and then build a flyout menu–style dashboard.
Navigation Types
Frame-based navigation (view stack)
Tabbed menu
Master-detail menu
These standard techniques are not mutually exclusive and can be combined to create the right user experience.
Frame-Based Navigation (View Stack)
View stack navigation is typically used with other navigation techniques. Consider you are building a shopping app and a user selects an item they want to purchase and see more details of. You could use a view stack and push a new page onto the screen that displays all the details. When they click the back button, the page is popped off the view stack, and they are back to the list of items.
Tabbed Menu
A tabbed menu is when you have several menu options always available as quick icons in a tab bar. When the user selects the tab, the main display area updates to the new page. By design all major pages are one tap away for the user, which makes it very easy to navigate to the various pages in your application.
You are not limited to where you display the tabs. You can place your tabbed menu horizontally on the top or bottom of the page. You can also place your tabbed menu vertically on the left or right of the page.
A challenge with tabbed menus is you can only display so many tabs on the screen at once. In smaller devices such as the typical Android or iOS phone, you can only have four or five menu options.
Master-Detail Menu
A master-detail menu is popular on small form factor devices such as mobile phones where there is an icon with three horizontal lines commonly called the “hamburger” icon, which opens the menu. This menu can open from the left or the right portion of the screen depending on application design. The master-detail menu is popular because it is an easy way to store several options that can’t be displayed in a tabbed menu or another navigation structure.
The master-detail menu is not just for small form factor devices but is very useful on tablets as well as desktop or laptop computers. In the larger form factors, the menu is typically always opened with the content area in the middle of the application. The menu can then be made responsive for the desktop or laptop scenario. As the screen size shrinks, it will fall back to a traditional flyout menu that is activated by the “hamburger” icon.
Combination
When building your application, you are not limited to just one navigation structure . It is common to mix and match these techniques where it makes the most sense. You may end up using all these techniques or even some that aren’t listed.
A common pairing is tabbed menus and flyout menus, where the popular options are listed in the tabbed menu. Then there is a “More” or “Settings” icon that opens a master-detail menu, which has the less common options.
Create a Dashboard Layout
The first thing we need to do is build our dashboard core layout. Once we have this built, we can start adding menu options and event handlers to properly implement the master-detail design pattern .
Master-detail control
NavigationView
Visual state manager
To get started we need to create a new Views folder in the shared project. This folder will contain all of our user interface pages, as well as any helper class to support those pages.
The typical convention in XAML-based applications is to have a Views folder or a Pages folder. It stores the various pages and sometimes more. This is entirely convention based and is up to you and your team. We are going to use a Views folder for this book.
We are going to be creating some new views in this chapter. Once you have the new folder created, move the existing LoginPage into this folder and then add four new blank Uno Platform pages called Dashboard, MyFilesPage , RecentFilesPage , and SharedFilesPage . See Figure 6-2 for a screenshot of the Visual Studio Solution Explorer.
It is best to create your XAML files using the Visual Studio extension, which will generate the XAML file and code behind correctly. If you have trouble, the complete code snippets included with this chapter will help you out.
Dashboard.xaml – basic layout with NavigationView. The xmlns have been omitted
PaneCustomContent
This allows you to place any content that will render above the menu items in the flyout menu. This will be used to display information about the user such as name and their profile photo.
MenuItems
This defines all the menu options that the user can navigate to from the flyout menu. In this container you will specify a list of NavigationViewItems, and each one will define an icon and text to keep a consistent menu experience.
Header
This specifies a standard content object where you can control what your page header looks like. The page header is the content that is rendered just above the main content area to the right of the flyout menu.
Frame
The content frame is where the current page or main content is rendered.
Now that we have the basic structure, we can start implementing various pieces to the dashboard page. Let’s start by overriding some of the default values and configuring the platform targets.
Dashboard.xaml – NavigationView properties
Dashboard.xaml.cs – MenuItemSelected method stub for the event in NavigationView
Dashboard.xaml – XAML xmlns definitions
Dashboard.xaml – XAML xmlns ignorables
Dashboard.xaml – NavigationView updated pane display rules for the various target platforms
This may appear like a lot of code, but we are only modifying IsPaneToggleButtonVisible (hamburger menu icon visibility) and PaneDisplayMode (always open or flyout menu style). Since we need to customize two properties for many platforms, the code ends up being quite verbose.
Dashboard.xaml – NavigationView PaneCustomContent implementation that renders at the top of the pane
The code in Listing 6-7 displays the user’s name and email and a horizontal line to separate the header section from the MenuItems section. Currently we are hard-coding the name and email address, but in future chapters when we connect to the Microsoft Graph , we will be using the logged-in user’s information.
Dashboard.xaml – NavigationViewItems
Depending on the version of Uno Platform, you may need to download the font file and add it to your various platform targets. Custom fonts are covered in Chapter 7 .
Notice that each NavigationViewItem has a special x:Name property to define a name. This is intentional, and when we get to the code behind portion of this chapter, we will be using the names to configure the event handler that opens the various pages.
Dashboard.xaml – NavigationView header
Dashboard.xaml – NavigationView frame content using the implicit approach
Dashboard.xaml – NavigationView frame content using the explicit approach
The choice is yours on how you want to use the control. We are going to use the implicit approach from Listing 6-10 as it generates less verbose XAML.
Dashboard.xaml completed XAML
Dashboard.xaml.cs – constructor initialization
In the navigation code from Listing 6-13, we explicitly pass the SuppressNavigationTransitionInfo, which tells the navigation system to not render any animation behavior. There are several different options to provide in the Navigate() method to render rich animations.
Now we can run the application across the various platforms and figure out if we need to make any platform-specific code changes . See the running application in Figure 6-3 for Windows, Figure 6-4 for WASM, Figure 6-5 for Android, and Figure 6-6 for iOS.
Windows
The header object that reads “My Files” is pushed to the right, which is by design of the WinUI control we are using. This behavior will be consistent across the various platforms. As you get more content in the pages, it will look better. If you need to have the control left-aligned, you will need to add some custom styles to apply a negative margin or create your own control template.
WASM
Android
iOS
Once you launch the application , you may notice that the flyout menu doesn’t work as the menu icon is in the top bar of the phone. This isn’t appealing for our design, and it is not functional, and the menu won’t open.
In this instance we will need to add an iOS-specific top margin to move the entire NavigationView down and into the safe zone of the phone.
The safe zone is a mobile device term that was coined when iOS and Android devices started to introduce the top notch for the camera. Typically, you will want to not have any content rendered outside of the “safe zone” as you will not be able to guarantee that the user can interact with it. The “safe zone” is the area of the screen that the user can safely interact with using their touch events.
Dashboard.xaml – iOS-specific margin to prevent text from rendering behind the notch
Dashboard.xaml – complete NavigationView property declarations
macOS
Linux
WPF
Menu Navigation
At this point you should have your application rendering correctly for the left menu and flyout menu depending on the platform you are running it on. Let’s start adding some code in the code behind in Dashboard.xaml.cs that properly updates the main content area when selecting a menu option on the left.
My Files: myFiles
Recent: recentFiles
Shared: sharedFiles
Recycle Bin: recycleBin
Dashboard.xaml.cs – initial implementation of the MenuItemSelected method
We can check the arguments of the event listener and if they match a well-known menu item in the application and navigate. The well-known menu item is the x:Name property that we defined earlier in the XAML. This makes it easier to check in the event listener for navigation. Once we have identified the page type we want to navigate to, we can tell the contentFrame to navigate to the new page.
Dashboard.xaml.cs – implementation of MenuItemSelected
This will finish implementing the menu items that open a page, but it won’t complete all menu items. We need to add a special implementation for “Sign Out” as that will log the user out of OneDrive. Since we haven’t connected to the Microsoft Graph yet, this case will just return and do nothing.
Dashboard.xaml.cs – MenuItemSelected snippet for sign-out logic
Dashboard.xaml.cs – complete implementation of MenuItemSelected
Now if you run the application, you will be able to click the menu items, and the pages will update. There was no need to add any special platform-specific code in this section as we only configured navigation rules.
Page Header
The page header as implemented is a simple Border control and is included in the main Dashboard page. As the application complexity expands, we are going to want to add additional rules to the page header such as adding new files. Let’s convert this to use a custom UserControl and decouple the XAML and code from the Dashboard page.
UserControl for the NavigationView header
UserControl for NavigationView – TextBlock with platform-specific XAML
We have not added any platform-specific customization for iOS, macOS, or Skia, so we may need to add additional properties for those platforms when we look at the running application. We have our basic UserControl implemented, so we can edit the Dashboard.xaml to include it.
We have been using the NavigationView.Header , but the control pushes our header content to a position that we don’t want. Our goal is to make the header line up with the menu icon on mobile and be top left on desktop.
Let’s remove the NavigationView.Header block and merge it with our Frame content. We will do this by creating a Grid and adding the new HeaderControl as the first item and the existing Frame as the second item.
xmlns definition for UnoDrive.Controls
Dashboard.xaml – NavigationView content Grid that wraps the HeaderControl and the Frame
This new XAML will place all the content starting at the top leftmost point. We need to add a little bit of padding and spacing to get our look and feel just right.
Dashboard.xaml – NavigationView content Grid Padding and RowSpacing
This change will cause the HeaderControl to overlap the menu icon in smaller displays for Android and iOS. When we review the screenshots, we will make changes to push the text to the right slightly.
Let’s run the application and test all the platforms to make sure everything looks correct for the TextBlock . See screenshots of running application in Figure 6-12 for Windows, and Figure 6-13 for WASM, Figure 6-14 and Figure 6-15 for Android, Figure 6-16 and Figure 6-17 for iOS, Figure 6-18 for macOS, Figure 6-19 for Linux, and Figure 6-20 for WPF.
Windows
WASM
Android
HeaderControl padding for Android
Completed header main content code
iOS
Dashboard.xaml – NavigationView main content Grid complete code
macOS
Linux
WPF
Dashboard.xaml – NavigationView PaneCustomContent two buttons
Dashboard.xaml – NavigationView PaneCustomContent first button (New) content
Dashboard.xaml – NavigationView PaneCustomContent second button (Upload) content
Now let’s run the application and see how the right column looks and if there are any changes we need to make to any of the platforms. See Figure 6-21 for Windows, Figure 6-22 for WASM, Figure 6-23 for Android, Figure 6-24 and Figure 6-25 for iOS, Figure 6-26 for macOS, Figure 6-27 for Linux, and Figure 6-28 for WPF.
Windows
WASM
Android
The assets were not loaded correctly for Android. This is expected as the Segoe MDL2 Assets are only available on Windows by default. We will need to explicitly add these for Android.
We will be fixing this in the next chapter.
iOS
HeaderControl.xaml – grid column definitions
The iOS application does not have the font icons loaded correctly as the Segoe MDL2 Assets are only included in Windows by default. We will need to add the assets to the iOS project for them to show up correctly.
This will be explained in detail in the next chapter.
macOS
The Segoe MDL2 Assets are not included by default for macOS. We will need to add them to the project.
This will be explained in the next chapter.
Linux
Just like iOS and macOS, the Linux application does not have the Segoe MDL2 Assets. For this platform it is considered a custom font and needs to be added to the project.
This will be explained in the next chapter.
WPF
Even though the WPF project uses the same Skia rendering engine as Linux, since it is on Windows, it has the Segoe MDL2 Assets. There’s no need to explicitly add them to the WPF project.
We are going to conclude with the fonts not working on all platforms. In the next chapter, we are going to fix this by adding custom fonts.
Conclusion
In this chapter we covered the fundamental navigation strategy of a dashboard page using a left menu or flyout menu depending on the target platform. We also added navigation for the various stubbed pages we added.
In the next chapter we are going to pick up where we left off by adding custom fonts to all the projects, so the icons look identical between the platforms. If you had any trouble following the code in this chapter, you can download the code for Chapter 6 at https://github.com/SkyeHoefling/UnoDrive/tree/main/Chapter%206 .