Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8668181
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T18:09:00+00:00 2026-06-12T18:09:00+00:00

I’m trying to use a DataTemplate to create a Menu from my ViewModels with

  • 0

I’m trying to use a DataTemplate to create a Menu from my ViewModels with respect to MVVM. Basically, I’ve created several classes which will store information about my Menu structure. I then want to realize that menu stucture as a WPF Menu using a DataTemplate.

I have a menu service which allows different components to register new menus and items within the menus. Here’s how I’ve organized my menu information (ViewModel)

I have the following classes:
MainMenuViewModel – Contains a TopLevelMenuViewModelCollection (a collection of top level menus)

TopLevelMenuViewModel – Contains a MenuItemGroupViewModelCollection (a collection of groups of menu items), and a name for the menu ‘Text’

MenuItemGroupViewModel – Contains a MenuItemViewModelCollection (collection of menu items)

MenuItemViewModel – Contains text, image uri, command, children MenuItemViewModels

What I want to do is apply a DataTemplate to the previous classes to transform them into a normal Menu.

MainMenuViewModel -> Menu

TopLevelMenuViewModel -> MenuItems with header set

MenuItemGroupViewModel -> Separator followed by a MenuItem for each MenuItemViewModel

MenuItemViewModel -> MenuItem (HeirarchicalDataTemplate)

The problem is I don’t see how to generate multiple MenuItems for the MenuItemGroupViewModel. The Menu template wants to always create an ItemContainer for each item which is a MenuItem. Therefore, I either end up with my MenuItems inside a MenuItem which obviously doesn’t work, or it doesn’t work at all. I’ve tried several things and still cannot figure out how to make a single item produce more than one MenuItem.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:--">
<!-- These data templates provide the views for the menu -->

<!-- MenuItemGroupView -->
<Style x:Key="MenuItemGroupStyle" TargetType="{x:Type MenuItem}">
    <Setter Property="Header" Value="qqq" />
    <!-- Now what? I don't want 1 item here..
    I wanted this to start with a <separator /> and list the MenuItemGroupViewModel.MenuItems -->
</Style>

<!-- TopLevelMenuView -->
<Style x:Key="TopLevelMenuStyle" TargetType="{x:Type MenuItem}">
    <Setter Property="Header" Value="{Binding Text}" />
    <Setter Property="ItemsSource" Value="{Binding MenuGroups}" />
    <Setter Property="ItemContainerStyle" Value="{StaticResource MenuItemGroupStyle}"/>
</Style>

<!-- MainMenuView -->
<DataTemplate DataType="{x:Type local:MainMenuViewModel}">
    <Menu ItemsSource="{Binding TopLevelMenus}" ItemContainerStyle="{StaticResource TopLevelMenuStyle}" />
</DataTemplate>

<!-- MenuItemView -->
<!--<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}"
                              ItemsSource="{Binding Path=Children}"
                          >
    <HierarchicalDataTemplate.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Command"
                        Value="{Binding Command}" />
        </Style>
    </HierarchicalDataTemplate.ItemContainerStyle>
    <StackPanel Orientation="Horizontal">
        <Image Source="{Binding ImageSource}" />
        <TextBlock Text="{Binding Text}" />
    </StackPanel>
</HierarchicalDataTemplate>-->

Please Click the links to see a better picture of what I’m trying to do

Class Diagram

Basic Menu I want to Make

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T18:09:01+00:00Added an answer on June 12, 2026 at 6:09 pm

    Because this is sort of complicated, I’ve updated this answer with a downloadable example.

    PrismMenuServiceExample

    My goal was to allow different modules to register menu commands and group them together with a title and sort the menu items in a proper order. First of all, let’s show an example of what the menu looks like.

    Grouped Menu Example

    This is useful, for example a “Tools” menu could have a “Module1” group that has menu items listed for each tool that belongs to Module1 which Module1 can register independently of the other modules.

    I have a “menu service” which allows modules to register new menus and menu items. Each node has a Path property which informs the service where to place the menu. This interface is likely in the infrastructure project, so that all modules can resolve it.

    public interface IMenuService
    {
        void AddTopLevelMenu(MenuItemNode node);
        void RegisterMenu(MenuItemNode node);
    }
    

    I can then implement that MenuService wherever is appropriate. (Infrastructure project, Separate Module, maybe the Shell). I go ahead and add some “default” menus that are defined application wide, although any module can add new top level menus.

    I could have created these menus in code, but I instead pulled them out of the resources because it was easier to write them out in XAML in a resource file. I’m adding that resource file to my application resources, but you could load it directly.

    public class MainMenuService : IMenuService
    {
        MainMenuNode menu;
        MenuItemNode fileMenu;
        MenuItemNode toolMenu;
        MenuItemNode windowMenu;
        MenuItemNode helpMenu;
    
        public MainMenuService(MainMenuNode menu)
        {
            this.menu = menu;
    
            fileMenu = (MenuItemNode)Application.Current.Resources["FileMenu"];
            toolMenu = (MenuItemNode)Application.Current.Resources["ToolMenu"];
            windowMenu = (MenuItemNode)Application.Current.Resources["WindowMenu"];
            helpMenu = (MenuItemNode)Application.Current.Resources["HelpMenu"];
    
            menu.Menus.Add(fileMenu);
            menu.Menus.Add(toolMenu);
            menu.Menus.Add(windowMenu);
            menu.Menus.Add(helpMenu);
        }
    
        #region IMenuService Members
    
        public void AddTopLevelMenu(MenuItemNode node)
        {
            menu.Menus.Add(node);
        }
    
        public void RegisterMenu(MenuItemNode node)
        {
            String[] tokens = node.Path.Split('/');
            RegisterMenu(tokens.GetEnumerator(), menu.Menus, node);
        }
    
        #endregion
    
        private void RegisterMenu(IEnumerator tokenEnumerator, MenuItemNodeCollection current, MenuItemNode item)
        {
            if (!tokenEnumerator.MoveNext())
            {
                current.Add(item);
            }
            else
            {
                MenuItemNode menuPath = current.FirstOrDefault(x=> x.Text == tokenEnumerator.Current.ToString());
    
                if (menuPath == null)
                {
                    menuPath = new MenuItemNode(String.Empty);
                    menuPath.Text = tokenEnumerator.Current.ToString();
                    current.Add(menuPath);
                }
    
                RegisterMenu(tokenEnumerator, menuPath.Children, item);
            }
        }
    }
    

    Here’s an example of one of those pre-defined menus in my resource file:

    <!-- File Menu Groups -->
    <menu:MenuGroupDescription x:Key="fileCommands"
                               Name="Files"
                               SortIndex="10" />
    <menu:MenuGroupDescription x:Key="printerCommands"
                               Name="Printing"
                               SortIndex="90" />
    <menu:MenuGroupDescription x:Key="applicationCommands"
                               Name="Application"
                               SortIndex="100" />
    
    <menu:MenuItemNode x:Key="FileMenu"
                       x:Name="FileMenu"
                       Text="{x:Static inf:DefaultTopLevelMenuNames.File}"
                       SortIndex="10">
        <menu:MenuItemNode Group="{StaticResource fileCommands}"
                           Text="_Open File..."
                           SortIndex="10"
                           Command="{x:Static local:FileCommands.OpenFileCommand}" />
        <menu:MenuItemNode Group="{StaticResource fileCommands}" Text="Recent _Files" SortIndex="20"/>
        <menu:MenuItemNode Group="{StaticResource fileCommands}" Text="Con_vert..."  SortIndex="30"/>
        <menu:MenuItemNode Group="{StaticResource fileCommands}"
                           Text="_Export"
                           SortIndex="40"
                           Command="{x:Static local:FileCommands.ExportCommand}" />
        <menu:MenuItemNode Group="{StaticResource fileCommands}" Text="_Save" SortIndex="50"/>
        <menu:MenuItemNode Group="{StaticResource fileCommands}" Text="Save _All" SortIndex="60"/>
        <menu:MenuItemNode Group="{StaticResource fileCommands}"
                           Text="_Close"
                           SortIndex="70"
                           Command="{x:Static local:FileCommands.CloseCommand}" />
        <menu:MenuItemNode Group="{StaticResource printerCommands}" Text="Page _Setup..." SortIndex="10"/>
        <menu:MenuItemNode Group="{StaticResource printerCommands}" Text="_Print..." SortIndex="10"/>
        <menu:MenuItemNode Group="{StaticResource applicationCommands}"
                           Text="E_xit"
                           SortIndex="10"
                           Command="{x:Static local:FileCommands.ExitApplicationCommand}" />
    </menu:MenuItemNode>
    

    OK, here lists the types that define the structure of my menu system… (Not what it looks like)

    The MainMenuNode basically exists so that you can easily create a different template for it. You probably what a menu bar or something that represents the menu as a whole.

    public class MainMenuNode
    {
        public MainMenuNode()
        {
            Menus = new MenuItemNodeCollection();
        }
    
        public MenuItemNodeCollection Menus { get; private set; }
    }
    

    Here’s the definition for each MenuItem. They include a Path which tells the service where to put them, a SortIndex which is sort of like TabIndex that allows them to be organized in the proper order, and a GroupDescription which allows you to put them into “groups” which can be styled differently and sorted.

    [ContentProperty("Children")]
    public class MenuItemNode : NotificationObject
    {
        private string text;
        private ICommand command;
        private Uri imageSource;
        private int sortIndex;
    
        public MenuItemNode()
        {
            Children = new MenuItemNodeCollection();
            SortIndex = 50;
        }
    
        public MenuItemNode(String path)
        {
            Children = new MenuItemNodeCollection();
            SortIndex = 50;
            Path = path;
        }
    
        public MenuItemNodeCollection Children { get; private set; }
    
        public ICommand Command
        {
            get
            {
                return command;
            }
            set
            {
                if (command != value)
                {
                    command = value;
                    RaisePropertyChanged(() => this.Command);
                }
            }
        }
    
        public Uri ImageSource
        {
            get
            {
                return imageSource;
            }
            set
            {
                if (imageSource != value)
                {
                    imageSource = value;
                    RaisePropertyChanged(() => this.ImageSource);
                }
            }
        }
    
        public string Text
        {
            get
            {
                return text;
            }
            set
            {
                if (text != value)
                {
                    text = value;
                    RaisePropertyChanged(() => this.Text);
                }
            }
        }
    
        private MenuGroupDescription group;
    
        public MenuGroupDescription Group
        {
            get { return group; }
            set
            {
                if (group != value)
                {
                    group = value;
                    RaisePropertyChanged(() => this.Group);
                }
            }
        }
    
        public int SortIndex
        {
            get
            {
                return sortIndex;
            }
            set
            {
                if (sortIndex != value)
                {
                    sortIndex = value;
                    RaisePropertyChanged(() => this.SortIndex);
                }
            }
        }
    
        public string Path
        {
            get;
            private set;
        }
    

    And a collection of menu items:

    public class MenuItemNodeCollection : ObservableCollection<MenuItemNode>
    {
        public MenuItemNodeCollection() { }
        public MenuItemNodeCollection(IEnumerable<MenuItemNode> items) : base(items) { }
    }
    

    Here’s how I ended up grouping MenuItems.. Each one has a GroupDescription

    public class MenuGroupDescription : NotificationObject, IComparable<MenuGroupDescription>, IComparable
    {
        private int sortIndex;
    
        public int SortIndex
        {
            get { return sortIndex; }
            set
            {
                if (sortIndex != value)
                {
                    sortIndex = value;
                    RaisePropertyChanged(() => this.SortIndex);
                }
            }
        }
    
        private String name;
    
        public String Name
        {
            get { return name; }
            set
            {
                if (name != value)
                {
                    name = value;
                    RaisePropertyChanged(() => this.Name);
                }
            }
        }
    
        public MenuGroupDescription()
        {
            Name = String.Empty;
            SortIndex = 50;
    
        }
    
        public override string ToString()
        {
            return Name;
        }
    
        #region IComparable<MenuGroupDescription> Members
    
        public int CompareTo(MenuGroupDescription other)
        {
            return SortIndex.CompareTo(other.SortIndex);
        }
    
        #endregion
    
        #region IComparable Members
    
        public int CompareTo(object obj)
        {
            if(obj is MenuGroupDescription)
                return sortIndex.CompareTo((obj as MenuGroupDescription).SortIndex);
            return this.GetHashCode().CompareTo(obj.GetHashCode());
        }
    
        #endregion
    }
    

    I then can design what my menu looks like with the following templates:

    <local:MenuCollectionViewConverter x:Key="GroupViewConverter" />
    
    <!-- The style for the header of a group of menu items -->
    <DataTemplate x:Key="GroupHeaderTemplate"
                  x:Name="GroupHeader">
        <Grid x:Name="gridRoot"
              Background="#d9e4ec">
            <TextBlock Text="{Binding Name}"
                       Margin="4" />
            <Rectangle Stroke="{x:Static SystemColors.MenuBrush}"
                       VerticalAlignment="Top"
                       Height="1" />
            <Rectangle Stroke="#bbb"
                       VerticalAlignment="Bottom"
                       Height="1" />
        </Grid>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Name}"
                         Value="{x:Null}">
                <Setter TargetName="gridRoot"
                        Property="Visibility"
                        Value="Collapsed" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
    
    <!-- Binds the MenuItemNode's properties to the generated MenuItem container -->
    <Style x:Key="MenuItemStyle"
           TargetType="MenuItem">
        <Setter Property="Header"
                Value="{Binding Text}" />
        <Setter Property="Command"
                Value="{Binding Command}" />
        <Setter Property="GroupStyleSelector"
                Value="{x:Static local:MenuGroupStyleSelectorProxy.MenuGroupStyleSelector}" />
    </Style>
    
    <Style x:Key="TopMenuItemStyle"
           TargetType="MenuItem">
        <Setter Property="Header"
                Value="{Binding Text}" />
        <Setter Property="Command"
                Value="{Binding Command}" />
        <Setter Property="GroupStyleSelector"
                Value="{x:Static local:MenuGroupStyleSelectorProxy.MenuGroupStyleSelector}" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Children.Count}"
                         Value="0">
                <Setter Property="Visibility"
                        Value="Collapsed" />
            </DataTrigger>
            <DataTrigger Binding="{Binding}"
                         Value="{x:Null}">
                <Setter Property="Visibility"
                        Value="Collapsed" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    
    <!-- MainMenuView -->
    <DataTemplate DataType="{x:Type menu:MainMenuNode}">
        <Menu ItemsSource="{Binding Menus, Converter={StaticResource GroupViewConverter}}"
              ItemContainerStyle="{StaticResource TopMenuItemStyle}" />
    </DataTemplate>
    
    <!-- MenuItemView -->
    <HierarchicalDataTemplate DataType="{x:Type menu:MenuItemNode}"
                              ItemsSource="{Binding Children, Converter={StaticResource GroupViewConverter}}"
                              ItemContainerStyle="{StaticResource MenuItemStyle}" />
    

    A key to make this work was figuring out how to inject my CollectionView with proper sorting definitions and grouping definitions into my DataTemplate. This is how I did it:

    [ValueConversion(typeof(MenuItemNodeCollection), typeof(IEnumerable))]
    public class MenuCollectionViewConverter : IValueConverter
    {
    
        #region IValueConverter Members
    
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(IEnumerable))
                throw new NotImplementedException();
    
            CollectionViewSource src = new CollectionViewSource();
            src.GroupDescriptions.Add(new PropertyGroupDescription("Group"));
            src.SortDescriptions.Add(new SortDescription("Group", ListSortDirection.Ascending));
            src.SortDescriptions.Add(new SortDescription("SortIndex", ListSortDirection.Ascending));
            src.Source = value as IEnumerable;
            return src.View;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value.GetType() != typeof(CollectionViewSource))
                throw new NotImplementedException();
            return (value as CollectionViewSource).Source;
        }
    
        #endregion
    }
    
    public static class MenuGroupStyleSelectorProxy
    {
        public static GroupStyleSelector MenuGroupStyleSelector { get; private set; }
    
        private static GroupStyle Style { get; set; }
    
        static MenuGroupStyleSelectorProxy()
        {
            MenuGroupStyleSelector = new GroupStyleSelector(SelectGroupStyle);
            Style = new GroupStyle()
            {
                HeaderTemplate = (DataTemplate)Application.Current.Resources["GroupHeaderTemplate"]
            }; 
        }
    
        public static GroupStyle SelectGroupStyle(CollectionViewGroup grp, int target)
        {
            return Style;
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Basically, what I'm trying to create is a page of div tags, each has
I am trying to understand how to use SyndicationItem to display feed which is
I'm trying to select an H1 element which is the second-child in its group
I have a text area in my form which accepts all possible characters from
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out
I'm trying to use string.replace('’','') to replace the dreaded weird single-quote character: ’ (aka
I'm trying to create an if statement in PHP that prevents a single post
link Im having trouble converting the html entites into html characters, (&# 8217;) i
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.