Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - How can I create menu and submenus using binding

People also ask

Which .NET WPF class used to create menus?

WPF Menu control is represented by the Menu class in C#. This menus tutorial and menus code examples explain how to use menus in WPF using C#. In WPF, the Menu and the MenuItem classes represent a menu and a menu item respectively. A Menu is a collection of menu items with a command associated with each menu item.

How many types of binding are there in WPF?

WPF binding offers four types of Binding. Remember, Binding runs on UI thread unless otherwise you specify it to run otherwise. OneWay: The target property will listen to the source property being changed and will update itself.

Which XAML tag is used for menu bar?

The <Menu> and <MenuItem> XAML elements are used to create menus in XAML.


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; }
}