Back to Devexpress

WPF Hamburger Menu: MVVM Support

wpf-119474-controls-and-libraries-windows-modern-ui-hamburger-menu-mvvm-support.md

latest9.9 KB
Original Source

WPF Hamburger Menu: MVVM Support

  • Oct 13, 2021
  • 3 minutes to read

The Hamburger Menu allows you to implement the MVVM design pattern.

Use the HamburgerMenuNavigationButtonBase<TOwner>.NavigationTargetTypeName or HamburgerMenuNavigationButtonBase<TOwner>.NavigationTargetType property to specify the navigation target page for a button. See the example below.

xaml
<dxwui:HamburgerMenu>
    <dxwui:HamburgerMenuNavigationButton Content="My Page" NavigationTargetTypeName="MyPage"/>
</dxwui:HamburgerMenu>
xaml
<dxwui:NavigationPage x:Class="DXSample.MyPage"
      xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui"
      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" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock Text="My Page" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="32" FontWeight="Bold"/>
    </Grid>
</dxwui:NavigationPage>

Another approach is to generate menu items based on a data source collection. Use the HamburgerMenu.ItemsSource property to bind the menu to data. The HamburgerMenu.ItemTemplate property allows you to specify the template used to render items from the data source. Use the HamburgerMenu.ItemTemplateSelector property to implement custom template selection logic.

For sub menus, use the HamburgerSubMenu.ItemsSource, HamburgerSubMenu.ItemTemplate and HamburgerSubMenu.ItemTemplateSelector properties.

For the bottom bar, use the HamburgerMenu.BottomBarItemsSource, HamburgerMenu.BottomBarItemTemplate, HamburgerMenu.BottomBarItemTemplateSelector properties.

This example illustrates how to create an application that uses the Hamburger Menu for navigation based on the MVVM design pattern.

View Example

xaml
<dxwui:NavigationPage x:Class="Hamburger.SimplePage"
      xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui"
      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:Hamburger"
      mc:Ignorable="d" >

    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
            <TextBlock Text="The menu is hidden" HorizontalAlignment="Center" />
            <Button Content="Show menu"
                    Command="{Binding Path=ToggleViewStateCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dxwui:HamburgerMenu}}}"/>
        </StackPanel>
    </Grid>
</dxwui:NavigationPage>
xaml
<Window xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui" x:Class="Hamburger.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:ViewModel="clr-namespace:Hamburger.ViewModel"
        xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Hamburger"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <ViewModel:MainViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate x:Key="HamburgerMenuItemTemplate" DataType="{x:Type ViewModel:MainViewModel}">
            <dxwui:HamburgerMenuNavigationButton Content="{Binding Caption}" NavigationTargetTypeName="{Binding PageName}" />
        </DataTemplate>
    </Window.Resources>
    <dxwui:HamburgerMenu IsMenuVisible="{Binding IsMenuVisible}" ItemsSource="{Binding Items}" AllowBuiltInNavigation="True"
                         SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ItemTemplate="{StaticResource HamburgerMenuItemTemplate}" >
    </dxwui:HamburgerMenu>

</Window>
xaml
<dxwui:NavigationPage x:Class="Hamburger.MainPage"
      xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui"
      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:Hamburger"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Main Page" />
    </Grid>
</dxwui:NavigationPage>
vb
Imports DevExpress.Mvvm
Imports System.Collections.ObjectModel
Imports System

Namespace Hamburger.ViewModel
    Public Class MainViewModel
        Inherits NavigationViewModelBase

        Public Property SelectedItem() As HamburgerMenuItemViewModel
            Get
                Return GetProperty(Function() SelectedItem)
            End Get
            Set(ByVal value As HamburgerMenuItemViewModel)
                SetProperty(Function() SelectedItem, value, AddressOf OnSelectedItemChanged)
            End Set
        End Property

        Public Property IsMenuVisible() As Boolean
            Get
                Return GetProperty(Function() IsMenuVisible)
            End Get
            Set(ByVal value As Boolean)
                SetProperty(Function() IsMenuVisible, value)
            End Set
        End Property
        Public Property Items() As ObservableCollection(Of HamburgerMenuItemViewModel)
            Get
                Return GetProperty(Function() Items)
            End Get
            Set(ByVal value As ObservableCollection(Of HamburgerMenuItemViewModel))
                SetProperty(Function() Items, value)
            End Set
        End Property
        Private ReadOnly Property NavigationService() As INavigationService
            Get
                Return GetService(Of INavigationService)()
            End Get
        End Property
        Public Sub New()
            Items = New ObservableCollection(Of HamburgerMenuItemViewModel)()
            Items.Add(New HamburgerMenuItemViewModel("Main Page", "MainPage"))
            Items.Add(New HamburgerMenuItemViewModel("Simple Page", "SimplePage"))
            SelectedItem = Items(0)
        End Sub
        Private Sub OnSelectedItemChanged()
            If SelectedItem IsNot Nothing Then
                IsMenuVisible = SelectedItem.Caption <> "Simple Page"
            End If
        End Sub
    End Class
    Public Class HamburgerMenuItemViewModel
        Public Property Caption() As String
        Public Property PageName() As String
        Public Sub New(ByVal caption As String, ByVal pageName As String)
            Me.Caption = caption
            Me.PageName = pageName
        End Sub
    End Class
End Namespace
csharp
using DevExpress.Mvvm;
using System.Collections.ObjectModel;
using System;

namespace Hamburger.ViewModel {
    public class MainViewModel : NavigationViewModelBase {
        public HamburgerMenuItemViewModel SelectedItem {
            get { return GetProperty(() => SelectedItem); }
            set { SetProperty(() => SelectedItem, value, OnSelectedItemChanged); }
        }

        public bool IsMenuVisible {
            get { return GetProperty(() => IsMenuVisible); }
            set { SetProperty(() => IsMenuVisible, value); }
        }
        public ObservableCollection<HamburgerMenuItemViewModel> Items {
            get { return GetProperty(() => Items); }
            set { SetProperty(() => Items, value); }
        }
        INavigationService NavigationService { get { return GetService<INavigationService>(); } }
        public MainViewModel() {
            Items = new ObservableCollection<HamburgerMenuItemViewModel>();
            Items.Add(new HamburgerMenuItemViewModel("Main Page", "MainPage"));
            Items.Add(new HamburgerMenuItemViewModel("Simple Page", "SimplePage"));
            SelectedItem = Items[0];
        }
        void OnSelectedItemChanged() {
            if (SelectedItem != null) {
                IsMenuVisible = SelectedItem.Caption != "Simple Page";
            }
        }
    }
    public class HamburgerMenuItemViewModel {
        public string Caption { get; set; }
        public string PageName { get; set; }
        public HamburgerMenuItemViewModel(string caption, string pageName) {
            Caption = caption;
            PageName = pageName;
        }
    }
}