2

Please note: This question is different to WPF - How can I create menu and submenus using binding because I want to use my own view models. MyFirstViewModel, MySecondViewModel, MyThirdViewModel cannot be merged in one kind of MenuItemViewModel and the layering with these 3 view models is my problem and the answer about hierarchical datatemplate doesn't work for me.

I want to make a menu where I know I have 3 levels.

  1. The first level is one static menu item
  2. the second level is generated from a binding to an ObservableCollection<MySecondViewModel> in my view model.
  3. In MySecondViewModel I also have a ObservableCollection<MyThirdViewModel> which I want to bind to my 3rd menu item level.

In the third level I also want to use a template with a Checkbox which is also bind to properties in MyThirdViewModel. So my ViewModels look like this:

public class MyFirstViewModel 
{
    public ObservableCollection<MySecondViewModel> MenuItemsSecondLevel { get; set; }
    ...
}

public class MySecondViewModel
{
    public string DisplayName{get; set;}
    public ObservableCollection<MyThirdViewModel> MenuItemsThirdLevel{ get; set; }
    ...
}

public class MyThirdViewModel
{
    public string DisplayName{get; set;}
    public bool IsChecked {get;set;}
    ...
}

How can I create my WPF Menu based on this? if I try this:

<Menu>
  <MenuItem Header="Select Source:" ItemsSource="{Binding MenuItemsSecondLevel}">
   <MenuItem Header="{Binding DisplayName}" ItemsSource="{Binding MenuItemsThirdLevel}" >
     <MenuItem.ItemTemplate>
        <DataTemplate>
           <CheckBox  Content="{Binding DisplayName}" IsChecked="{Binding IsChecked}"/>
        </DataTemplate>
     </MenuItem.ItemTemplate>
   </MenuItem>
 </MenuItem>
</Menu>

Then my bindings are not working. He cannot find any of my Collections.If I make it more advanced like this:

<Menu>
  <MenuItem Header="Select Source:" ItemsSource="{Binding MenuItemsSecondLevel}">
    <MenuItem.ItemTemplate>
      <DataTemplate>
        <MenuItem Header="{Binding DisplayName}" ItemsSource="{Binding MenuItemsThirdLevel}" >
          <MenuItem.ItemTemplate>
            <DataTemplate>
              <CheckBox Content="{Binding DisplayName}" IsChecked="{Binding IsChecked}" />
            </DataTemplate>
          </MenuItem.ItemTemplate>
        </MenuItem>
      </DataTemplate>
    </MenuItem.ItemTemplate>
  </MenuItem>
</Menu>

He finds the second level but not the third. What's the best way to make the menu levels like the structure of my view models?

Please note, I know that you can make menu items selectable but there is a design reason why we use here checkboxes.

Nelly
  • 522
  • 6
  • 15
  • Have you tried making a custom `MenuItem` by making a new class deriving from `MenuItem`? – lightlike Aug 30 '17 at 09:29
  • No, I didn't but do you think that would help? How could that solve my problem? – Nelly Aug 30 '17 at 09:31
  • Oh. Sorry. I think I misunderstood your problem. Can you try implementing `INotifyPropertyChanged` on your ViewModels. It might be that you set the `ObservableCollection` after the UI already loaded it. – lightlike Aug 30 '17 at 09:45
  • I use MVVMLight (so the INotifyPropertyChanged event is already implemented) and I tested the binding by also using ItemControls, so I know that the DataContext and the Bindings work correctly. it seems to me that the Menuitems cannot handle different collections in their layering. I'm also open to use different wpf controls but I don't know what fits my needs better than the Menuitems.... – Nelly Aug 30 '17 at 09:52
  • 1
    @lightlike `INotifyPropertyChanged` isn't the problem. Have a look at my answer. – Mighty Badaboom Aug 30 '17 at 10:03

1 Answers1

3

You could use this

<Menu>
    <MenuItem Header="Select Source:"
              ItemsSource="{Binding FirstViewModel.MenuItemsSecondLevel}">
        <MenuItem.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:MySecondViewModel}"
                                      ItemsSource="{Binding MenuItemsThirdLevel}">
                <TextBlock Text="{Binding DisplayName}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:MyThirdViewModel}">
                <CheckBox Content="{Binding DisplayName}" />
            </DataTemplate>
        </MenuItem.Resources>
    </MenuItem>
</Menu>

Assuming FirstViewModel is a property of your viewmodel.

Mighty Badaboom
  • 6,067
  • 5
  • 34
  • 51