0

I am trying to bind a VM method as a command in MenuItem. Though menu is displays correctly the function never get called.I expecting the MenuCommand Method to be get called from the command binding.

Xaml

<Menu.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding SubMenu}">
        <TextBlock Text="{Binding Name}">
            <TextBlock.InputBindings>
                <MouseBinding Command="{Binding MenuCommand}" MouseAction="LeftClick" />
            </TextBlock.InputBindings>
        </TextBlock>
    </HierarchicalDataTemplate>
</Menu.ItemTemplate>

ViewModel

public class MenuViewModel : ViewModelBase
{
    public ObservableCollection<Menu> Menu { get; set; }

    public RelayCommand MenuCommand { get; set; }

    public void Load()
    {
        Menu = new ObservableCollection<Menu> {
            new Menu
            {
                Name = "File",
                SubMenu = new List<Menu>
                {
                    new Menu  { Name = "New" },
                    new Menu  { Name = "Open" },
                    new Menu  { Name = "Save" }
                }
            }};
           MenuCommand = new RelayCommand(MenuExecution);
    }

    public void MenuExecution(object item)
    {
        MessageBox.Show("Hello");
    }
}
Shiju Samuel
  • 1,373
  • 6
  • 22
  • 45
  • You're going about this completely wrong. You have an ObservableCollection inside a MenuViewModel, which says you're trying to do MVVM, but the collection is of type Menu i.e. a graphics object. So you're basically mixing up your view and view model layer. The MenuViewModel should contain a collection of MenuItemViewModel, with your command handlers either there or in the MenuViewModel. The only place the Menu and MenuItem should appear in is your XAML. – Mark Feldman Aug 04 '18 at 02:35
  • Here you go, check [this answer to a previous SO question](https://stackoverflow.com/a/23941998/1177147), that's how you do it properly. (Although in that particular example he's using the Window as it's own ViewModel, which technically isn't proper MVVM but at least demonstrates the point). – Mark Feldman Aug 04 '18 at 02:53
  • I think "MenuCommand" command is trying to find in "SubMenu" class which it could not able to find it. Try to bind MenuCommand from DataContext of a Windwo/UserControl and then path to "MenuCommand" property. – G K Aug 04 '18 at 05:48
  • @GK I am getting below errors. How can I bind from a DataContext of Window/UserControl System.Windows.Data Error: 40 : BindingExpression path error: 'MenuCommand' property not found on 'object' ''Menu' (HashCode=62990845)'. BindingExpression:Path=MenuCommand; DataItem='Menu' (HashCode=62990845); target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand') – Shiju Samuel Aug 04 '18 at 06:24
  • @MarkFeldman The Menu is not a graphics object, its a custom Model. I want a single command to be called for all the menus so I have defined the command at VM. – Shiju Samuel Aug 04 '18 at 06:27
  • 1
    @ShijuSamuel check this link https://stackoverflow.com/a/3547707/1966993 Command={Binding ElementName=level1Lister, Path=DataContext.MyLevel1Command} ElementName - Can be your window or user control name and MyLevel1Command is nothing but your command. Give a try and lets know. – G K Aug 04 '18 at 06:33
  • 1
    @ShijuSamuel my apologies, I misunderstood. (In general though it's good practice to name your models and view models with `ViewModel` or something in the name to avoid such misunderstandings). In that case GK's comment is correct, but you'll also need to do `CommandParameter="{Binding}"` so that the associated menu view item gets passed into the command handler, otherwise you won't know one was selected. – Mark Feldman Aug 04 '18 at 08:27

1 Answers1

0

Thanks @GK & @Mark I am able to bind the command successfully by below Xaml

<Menu ItemsSource="{Binding Menu}" >
        <Menu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}" >
                <Setter Property="Command" Value="{Binding ElementName=level1Lister, Path=DataContext.MenuCommand}" />
                <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}"/>
            </Style>
        </Menu.ItemContainerStyle>
        <Menu.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Path=SubMenu}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </Menu.ItemTemplate>
</Menu>
Shiju Samuel
  • 1,373
  • 6
  • 22
  • 45