Click here to Skip to main content
15,881,600 members
Articles / Programming Languages / C#

Creating a Dynamic WPF Menu: Part 2

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
24 Oct 2014CPOL2 min read 11.6K   4  
Part 2 of creating a dynamic WPF menu

File Menu

In part 1, I introduced the idea of a dynamic menu build using WPF and the hierarchical data template. In part 2, I will carry on putting the foundations in place for the menu, and in part 3, I will link everything together.

Firstly, I shall cover the implementation of ICommand for the purposes of this menu. You will see in the base MenuItem class in part 1 we exposed an ICommand property. The ICommand allows us to specify a command to run when we click our menu item, and also to specify whether or not we can click the command. WPF uses the second to determine whether or not the menu item should be enabled.

C#
class MenuCommand : ICommand
    {
        private Action execute;

        private Func<bool> canExecute;

        public MenuCommand(Action execute, Func<bool> canExecute)
        {
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public void Execute(object parameter)
        {
            execute();
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute();
        }

        private void RaiseCanExecuteChanged()
        {
            CommandManager.InvalidateRequerySuggested();
        }

        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }
    }

When we initialize the ICommand, you can see that we pass the Action to execute and a function that returns a boolean (Function). If you look at our MenuItem class in part 1, you can see that there’s a virtual method that by default returns true. If we do require to disable a menu item, then we can override this, but the majority of the time this will not be needed.

The CanExecuteChanged event is hooked up to the command manager requery suggested event, which fires sufficiently often from our user interface that it will make the disabling look like it occurs in realtime.

Now the hierarchical data template. To use this, we do two things. We bind the menu bar to the top-level [parent] items, then we bind the data template to the menu item subitems list. The hierarchical data template will then iterate through all menu items and get the sub items until a complete tree has been built. In each case, we also bind the text property of the menu item object to display to the user. The RecognizesAccessKey property allows us to specify a shortcut key with the _ character.

We also need to create a style to bind OnSelected command of each MenuItem, and apply that style to each.

XML
<Window x:Class="DynamicMenuExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" 
        Width="525" SizeToContent="Manual">
    <Window.Resources>
       <Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
        <Setter Property="Command" Value="{Binding OnSelected}" />
    </Style> 
    </Window.Resources>    
    <Grid>
        <DockPanel LastChildFill="True" >
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
                <Menu IsMainMenu="True" 
                ItemsSource="{Binding ParentItems}" Width="525"> 
                    <Menu.ItemTemplate>
                    <HierarchicalDataTemplate 
                    ItemContainerStyle="{StaticResource MenuItemStyle}">
                        <ContentPresenter Content="{Binding Text}" 
                        RecognizesAccessKey="True" />
                        <HierarchicalDataTemplate.ItemsSource>
                            <Binding Path="SubItems" />
                        </HierarchicalDataTemplate.ItemsSource>
                    </HierarchicalDataTemplate>
                </Menu.ItemTemplate>
            </Menu>
        </StackPanel>
        <Grid />
        </DockPanel>
    </Grid>
</Window>

In part 3, I will put all of this together.

Filed under: C#, CodeProject, Software, WPF
Tagged: C#, custom, dynamic, HierarchicalDataTemplate, ICommand, menu, WPF
Image 2 Image 3 Image 4 Image 5 Image 6 Image 7 Image 8 Image 9

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --