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

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.

 create a WPF App

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

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

Add Windows Runtime APIs in WPF

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.

WPF Target Windows 10 Version

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. 

Install NuGet package 

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.

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.

<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

public MainWindow()  
{  
     InitializeComponent();  
     MyNavView.ChildChanged += MyNavView_ChildChanged;           
}  
  
private void MyNavView_ChildChanged(object sender, EventArgs e)  
{  
    if (MyNavView.Child is XamlIslands.NavigationView navigationView)  
    {  
        _navView = navigationView;  
        _navView.RequestedTheme = ElementTheme.Light;  
        _navView.IsBackButtonVisible = XamlIslands.NavigationViewBackButtonVisible.Visible;  
        _navView.PaneDisplayMode = XamlIslands.NavigationViewPaneDisplayMode.Left;  
        _navView.MenuItems.Add(CreateMenu("Home"));  
        _navView.MenuItems.Add(CreateMenu("Admin"));  
        _navView.ItemInvoked += NavView_ItemInvoked;  
    }  
}
private void NavView_ItemInvoked(XamlIslands.NavigationView sender, XamlIslands.NavigationViewItemInvokedEventArgs args)  
{  
    if (args.IsSettingsInvoked)  
    {  

    }  
    else if (args.InvokedItemContainer != null)  
    {  
        var navItemTag = args.InvokedItemContainer.Tag.ToString();  
        MessageBox.Show(navItemTag);  
    }  
}  

private static XamlIslands.NavigationViewItem CreateMenu(string menuName)  
{  
    XamlIslands.NavigationViewItem item = new XamlIslands.NavigationViewItem  
    {  
        Name = menuName, Content = menuName,Tag = menuName  
    };  
    return item;  
}

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. \

using Windows.UI.Xaml;  
  
namespace WPFXamlTemplate  
{  
    public delegate void OnThemeUpdate();  
    public static class AppSettings  
    {  
        public static ElementTheme CurrentTheme = ElementTheme.Default;  
  
        public static event OnThemeUpdate ThemeEvent;  
  
        public static void ThemeUpdate()  
        {  
            ThemeEvent?.Invoke();  
        }
    }  
}

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 

<UserControl x:Class="WPFXamlTemplate.SettingsCtrl"  
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
             xmlns:local="clr-namespace:WPFXamlTemplate"  
             mc:Ignorable="d"   
             d:DesignHeight="450" d:DesignWidth="800">  
    <Grid>  
        <Grid.RowDefinitions>  
            <RowDefinition Height="Auto" />  
            <RowDefinition Height="Auto" />  
            <RowDefinition Height="Auto" />  
        </Grid.RowDefinitions>
        <StackPanel>  
            <Label FontWeight="Bold" FontSize="30">WPF Window</Label>  
        </StackPanel>
        <StackPanel Margin="10" Grid.Row="1">  
            <Label FontWeight="Bold" FontSize="25">Theme Settings</Label>  
            <RadioButton x:Name="RdDark" Tag="Dark" Margin="10"  FontSize="25"  Checked="RadioButtonChecked">Dark</RadioButton>  
            <RadioButton x:Name="RdLight" Tag="light" Margin="10"  FontSize="25"  Checked="RadioButtonChecked">Light</RadioButton>  
        </StackPanel>
    </Grid>  
</UserControl>

User defined control code behind file,

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
using Windows.UI.Xaml;  
using RoutedEventArgs = System.Windows.RoutedEventArgs;  
  
namespace WPFXamlTemplate  
{  
    /// <summary>  
    /// Interaction logic for SettingsCtrl.xaml  
    /// </summary>  
    public partial class SettingsCtrl : UserControl  
    {  
        public SettingsCtrl()  
        {  
            InitializeComponent();  
        }  
  
        private void RadioButtonChecked(object sender, RoutedEventArgs e)  
        {  
            if (sender is RadioButton rdButton)  
            {  
                switch (rdButton.Tag.ToString())  
                {  
                    case "Dark":  
                        AppSettings.CurrentTheme = ElementTheme.Dark;  
                        break;  
                    case "light":  
                        AppSettings.CurrentTheme = ElementTheme.Light;  
                        break;  
                }  
  
                AppSettings.ThemeUpdate();  
            }  
        }  
    }  
}

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

<Window x:Class="WPFXamlTemplate.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:local="clr-namespace:WPFXamlTemplate"  
        xmlns:xamlHost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"  
        mc:Ignorable="d"  
        Title="MainWindow" Height="450" Width="800">  
    <Grid>  
  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition Width="Auto" />  
            <ColumnDefinition Width="Auto" />  
        </Grid.ColumnDefinitions>  
  
       <xamlHost:WindowsXamlHost Grid.Column="0" x:Name="MyNavView" InitialTypeName="Windows.UI.Xaml.Controls.NavigationView"/>  
        <StackPanel Grid.Column="1">  
           <local:SettingsCtrl x:Name="UserCtrlSetting" Margin="0"  Width="200" Height="200"/>  
        </StackPanel>  
    </Grid>  
</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.  

AppSettings.ThemeEvent += AppSettings_ThemeEvent;  
  
private void AppSettings_ThemeEvent()  
{  
    _navView.RequestedTheme = AppSettings.CurrentTheme;  
} 

Find the complete source code here.(https://github.com/rvinothrajendran/XAML-Islands/tree/master/NavigationViewInWPF/WPFXamlTemplate)

Output 

UWP Control in WPF application

Conclusion

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

Happy Reading. Happy coding.


Similar Articles