WPF - How can I create menu and submenus using binding WPF - How can I create menu and submenus using binding wpf wpf

WPF - How can I create menu and submenus using binding


For me, it worked with this simple template:

<Menu.ItemContainerStyle>    <Style TargetType="{x:Type MenuItem}">        <Setter Property="Command" Value="{Binding Command}" />    </Style></Menu.ItemContainerStyle><Menu.ItemTemplate>    <HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">        <TextBlock Text="{Binding Header}"/>    </HierarchicalDataTemplate></Menu.ItemTemplate>

Here is the complete example:

MainWindow.xaml:

<Window x:Class="WpfApplication14.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:local="clr-namespace:WpfApplication14"        Title="MainWindow" Height="350" Width="525">    <DockPanel>        <Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}">            <Menu.ItemContainerStyle>                <Style TargetType="{x:Type MenuItem}">                    <Setter Property="Command" Value="{Binding Command}" />                </Style>            </Menu.ItemContainerStyle>            <Menu.ItemTemplate>                <HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">                    <TextBlock Text="{Binding Header}"/>                </HierarchicalDataTemplate>            </Menu.ItemTemplate>        </Menu>        <Grid>        </Grid>    </DockPanel></Window>

MainWindow.xaml.cs:

using System;using System.Collections.ObjectModel;using System.Windows;using System.Windows.Input;namespace WpfApplication14{    public partial class MainWindow : Window    {        public ObservableCollection<MenuItemViewModel> MenuItems { get; set; }        public MainWindow()        {            InitializeComponent();            MenuItems = new ObservableCollection<MenuItemViewModel>            {                new MenuItemViewModel { Header = "Alpha" },                new MenuItemViewModel { Header = "Beta",                    MenuItems = new ObservableCollection<MenuItemViewModel>                        {                            new MenuItemViewModel { Header = "Beta1" },                            new MenuItemViewModel { Header = "Beta2",                                MenuItems = new ObservableCollection<MenuItemViewModel>                                {                                    new MenuItemViewModel { Header = "Beta1a" },                                    new MenuItemViewModel { Header = "Beta1b" },                                    new MenuItemViewModel { Header = "Beta1c" }                                }                            },                            new MenuItemViewModel { Header = "Beta3" }                        }                },                new MenuItemViewModel { Header = "Gamma" }            };            DataContext = this;        }    }    public class MenuItemViewModel    {        private readonly ICommand _command;        public MenuItemViewModel()        {            _command = new CommandViewModel(Execute);        }        public string Header { get; set; }        public ObservableCollection<MenuItemViewModel> MenuItems { get; set; }        public ICommand Command        {            get            {                return _command;            }        }        private void Execute()        {            // (NOTE: In a view model, you normally should not use MessageBox.Show()).            MessageBox.Show("Clicked at " + Header);        }    }    public class CommandViewModel : ICommand    {        private readonly Action _action;        public CommandViewModel(Action action)        {            _action = action;        }        public void Execute(object o)        {            _action();        }        public bool CanExecute(object o)        {            return true;        }        public event EventHandler CanExecuteChanged        {            add { }            remove { }        }    }}

The resulting window looks like this:

screen shot


that is very easy,you can use this code for your nested menu

ViewModel: TopMenuViewModel.cs

public partial class TopMenuViewModel {    public TopMenuViewModel()    {        TopMenuItems = new ObservableCollection<MenuItem>        {            new MenuItem            {                Title = "File",                PageName =typeof(OfficeListView).FullName,                ChildMenuItems= {                    new MenuItem                    {                        Title = "New"                    },                     new MenuItem                    {                        Title = "Open"                    },                     new MenuItem                    {                        Title = "Save"                    }                }            },            new MenuItem            {                Title = "Edit"            },            new MenuItem            {                Title = "Search"            }        };    }

View: TopMenuView.xaml

<Menu IsMainMenu="True" ItemsSource="{Binding TopMenuItems}">            <Menu.ItemContainerStyle>                <Style TargetType="{x:Type MenuItem}">                    <Setter Property="Header" Value="{Binding Title}"/>                    <Setter Property="ItemsSource" Value="{Binding Path=ChildMenuItems}"/>                </Style>            </Menu.ItemContainerStyle></Menu>   


If like me you are keen to keep UI constructs in the XAML code, after some difficulty, I have worked a nice way of binding custom-typed collections to create menu items.

In XAML:

<Menu DockPanel.Dock="Top">    <MenuItem Header="SomeHeaderName" ItemsSource="{Binding Path=MyCollection}">        <MenuItem.ItemsContainerStyle>            <Setter Property="Header" Value="{Binding Path=SomeRelevantTextProperty}"/>            <EventSetter Event="Click" Handler="SomeMenuItemClickEventHandler"/>        </MenuItem.ItemsContainerStyle>    </MenuItem></Menu>

In code-behind:

ObservableCollection<MyClass> MyCollection;private void SomeMenuItemClickEventHandler(object sender, RoutedEventArgs e){    MenuItem menuItem = sender as MenuItem;    MyClass myClass = menuItem.DataContext as MyClass;    // do something useful!}
public class MyClass{    public string SomeRelevantTextProperty { get; }}