XAML Islands - UWP NavigationView Control In WPF Using .NET Core😍

In this article, you will learn how to use XAML Islands to host the UWP NavigationView Control in a .NET Core WPF application.

This sample is using the UWP NavigationView control in WPF to change the NavigationView themes from WPF (Left side NavigationView, Right side, WPF User control).
 
 

XAML Islands


XAML Islands is a new technology that allows loading UWP controls in non-UWP desktop applications, such as WPF, Windows Forms, MFC. XAML Islands is released on Windows 10 1903 version.

System Requirement
  1. Visual Studio 2019 IDE + WPF workload 
  2. Install the latest .NET Core 3 Preview version
  3. Windows 10 SDK Version 

Project Installation steps


First, create a WPF App (.NET Core) project.
 
 

Add Windows Runtime APIs in WPF

 
Add contracts in the WPF project. These contracts are available in the Windows 10 SDK version. In this sample, I have used Windows 10 18362 SDK version.

Windows.Foundation.FoundationContract & Windows.Foundation.UniversalApiContract
  1. C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd
  2. C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd
 

WPF Target Windows 10 Version

 
UWP controls always target the Windows 10 versions while creating UWP application. You can always notice the Min and Max versions we have to specify. The same concept applies in WPF also, but we have to set only the Max Version.
 
To set this, create a new .mainfest file and enable the supportedOSId and set the maxVersionTested value filed as Windows 10 SDK version.
 
Moreover, make sure the .mainfest file is attached to the WPF Project. To verify this, go to the WPF Project -> Application section -> Resources -> Icon and manifest -> manifest -> check file is selected or not. If not, then select the file.
 
 

Add the UWP NavigationView Control


To load the UWP control in WPF, we have to use two XAML Islands packages provided by the Windows Community Toolkit.
 
Note
We can create our package also.
 

Install NuGet package

 
The below packages are used to load the UWP controls in WPF; this package is created by the Windows Community Toolkit.

Microsoft.Toolkit.Wpf.UI.Controls
 
This package provides wrapper classes for UWP Controls to use in WPF.

Microsoft.Toolkit.Wpf.UI.XamlHost
 
This is a Helper class to host the UWP control in WPF application. 
 
 
 
Important installation steps have been done. Next, we are loading the NavigationView control in WPF application.
 

WPF XAML changes


First, add the Xamlhost namespace in the XAML file.
  1. xmlns:xamlHost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"  
UWP control has to be specified in the WindowsXamlHost control in the WPF surface. Use the InitialTypeName property to set the UWP control type. The type must be set with a fully qualified name.
  1. <xamlHost:WindowsXamlHost x:Name="MyNavView" InitialTypeName="Windows.UI.Xaml.Controls.NavigationView"/>  
NOTE
UWP Control is not available in the design time. So, we have to load control in the runtime, WPF Xaml we specified the only declaration.

Code Behind load the NavigationViewContrl,

ChildChanged

Once control fully loaded use the ChildChanged property to initialize the events and property styles.
 
NavigationView Code
  1. public MainWindow()  
  2. {  
  3.      InitializeComponent();  
  4.      MyNavView.ChildChanged += MyNavView_ChildChanged;           
  5. }  
  6.   
  7. private void MyNavView_ChildChanged(object sender, EventArgs e)  
  8.        {  
  9.            if (MyNavView.Child is XamlIslands.NavigationView navigationView)  
  10.            {  
  11.                _navView = navigationView;  
  12.                _navView.RequestedTheme = ElementTheme.Light;  
  13.                _navView.IsBackButtonVisible = XamlIslands.NavigationViewBackButtonVisible.Visible;  
  14.                _navView.PaneDisplayMode = XamlIslands.NavigationViewPaneDisplayMode.Left;  
  15.                _navView.MenuItems.Add(CreateMenu("Home"));  
  16.                _navView.MenuItems.Add(CreateMenu("Admin"));  
  17.                _navView.ItemInvoked += NavView_ItemInvoked;  
  18.            }  
  19.        }  
  1. private void NavView_ItemInvoked(XamlIslands.NavigationView sender, XamlIslands.NavigationViewItemInvokedEventArgs args)  
  2.         {  
  3.             if (args.IsSettingsInvoked)  
  4.             {  
  5.   
  6.             }  
  7.             else if (args.InvokedItemContainer != null)  
  8.             {  
  9.                 var navItemTag = args.InvokedItemContainer.Tag.ToString();  
  10.                 MessageBox.Show(navItemTag);  
  11.             }  
  12.   
  13.         }  
  14.   
  15.         private static XamlIslands.NavigationViewItem CreateMenu(string menuName)  
  16.         {  
  17.             XamlIslands.NavigationViewItem item = new XamlIslands.NavigationViewItem  
  18.             {  
  19.                 Name = menuName, Content = menuName,Tag = menuName  
  20.             };  
  21.             return item;  
  22.         }  
Compile and run the application.
 
AppSettings
 
Create a user-defined class and define the ElementTheme. This class is used to set the value from WPF control to UWP control and vice versa. 
  1. using Windows.UI.Xaml;  
  2.   
  3. namespace WPFXamlTemplate  
  4. {  
  5.     public delegate void OnThemeUpdate();  
  6.     public static class AppSettings  
  7.     {  
  8.         public static ElementTheme CurrentTheme = ElementTheme.Default;  
  9.   
  10.         public static event OnThemeUpdate ThemeEvent;  
  11.   
  12.         public static void ThemeUpdate()  
  13.         {  
  14.             ThemeEvent?.Invoke();  
  15.         }  
  16.   
  17.     }  
  18. }  

WPF User control

 
Create WPF user control; In XAML define the Radio buttons and add the event handler based on the Radio button event set the ElementTheme value in App settings class
 
User-defined XAML file 
  1. <UserControl x:Class="WPFXamlTemplate.SettingsCtrl"  
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
  6.              xmlns:local="clr-namespace:WPFXamlTemplate"  
  7.              mc:Ignorable="d"   
  8.              d:DesignHeight="450" d:DesignWidth="800">  
  9.     <Grid>  
  10.         <Grid.RowDefinitions>  
  11.             <RowDefinition Height="Auto" />  
  12.             <RowDefinition Height="Auto" />  
  13.             <RowDefinition Height="Auto" />  
  14.         </Grid.RowDefinitions>  
  15.   
  16.         <StackPanel>  
  17.             <Label FontWeight="Bold" FontSize="30">WPF Window</Label>  
  18.         </StackPanel>  
  19.   
  20.         <StackPanel Margin="10" Grid.Row="1">  
  21.             <Label FontWeight="Bold" FontSize="25">Theme Settings</Label>  
  22.             <RadioButton x:Name="RdDark" Tag="Dark" Margin="10"  FontSize="25"  Checked="RadioButtonChecked">Dark</RadioButton>  
  23.             <RadioButton x:Name="RdLight" Tag="light" Margin="10"  FontSize="25"  Checked="RadioButtonChecked">Light</RadioButton>  
  24.         </StackPanel>  
  25.   
  26.     </Grid>  
  27. </UserControl>  
User defined control code behind file, 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Windows;  
  5. using System.Windows.Controls;  
  6. using System.Windows.Data;  
  7. using System.Windows.Documents;  
  8. using System.Windows.Input;  
  9. using System.Windows.Media;  
  10. using System.Windows.Media.Imaging;  
  11. using System.Windows.Navigation;  
  12. using System.Windows.Shapes;  
  13. using Windows.UI.Xaml;  
  14. using RoutedEventArgs = System.Windows.RoutedEventArgs;  
  15.   
  16. namespace WPFXamlTemplate  
  17. {  
  18.     /// <summary>  
  19.     /// Interaction logic for SettingsCtrl.xaml  
  20.     /// </summary>  
  21.     public partial class SettingsCtrl : UserControl  
  22.     {  
  23.         public SettingsCtrl()  
  24.         {  
  25.             InitializeComponent();  
  26.         }  
  27.   
  28.         private void RadioButtonChecked(object sender, RoutedEventArgs e)  
  29.         {  
  30.             if (sender is RadioButton rdButton)  
  31.             {  
  32.                 switch (rdButton.Tag.ToString())  
  33.                 {  
  34.                     case "Dark":  
  35.                         AppSettings.CurrentTheme = ElementTheme.Dark;  
  36.                         break;  
  37.                     case "light":  
  38.                         AppSettings.CurrentTheme = ElementTheme.Light;  
  39.                         break;  
  40.                 }  
  41.   
  42.                 AppSettings.ThemeUpdate();  
  43.             }  
  44.         }  
  45.     }  
  46. }  
Main application Changes

Add the user-defined control in the Main application XAML page.
 
Left side loads the NavigationView , Right side loads the WPF user defined control
  1. <Window x:Class="WPFXamlTemplate.MainWindow"  
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  6.         xmlns:local="clr-namespace:WPFXamlTemplate"  
  7.         xmlns:xamlHost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"  
  8.         mc:Ignorable="d"  
  9.         Title="MainWindow" Height="450" Width="800">  
  10.     <Grid>  
  11.   
  12.         <Grid.ColumnDefinitions>  
  13.             <ColumnDefinition Width="Auto" />  
  14.             <ColumnDefinition Width="Auto" />  
  15.         </Grid.ColumnDefinitions>  
  16.   
  17.        <xamlHost:WindowsXamlHost Grid.Column="0" x:Name="MyNavView" InitialTypeName="Windows.UI.Xaml.Controls.NavigationView"/>  
  18.         <StackPanel Grid.Column="1">  
  19.            <local:SettingsCtrl x:Name="UserCtrlSetting" Margin="0"  Width="200" Height="200"/>  
  20.         </StackPanel>  
  21.     </Grid>  
  22. </Window>  
Main application Changes
 
In the main application code behind the page, implement the AppSettings callback event handler whenever the user clicks the theme radio button. This callback gets a trigger, and updates the Navigationview control theme.  
  1. AppSettings.ThemeEvent += AppSettings_ThemeEvent;  
  2.   
  3. private void AppSettings_ThemeEvent()  
  4.         {  
  5.             _navView.RequestedTheme = AppSettings.CurrentTheme;  
  6.         }  
 
Output 
 
 

Conclusion

 
I hope you understand how to implement the UWP Control in WPF application.
 
Happy Reading. Happy coding.