Search code examples
wpfcommandmvvm-lightdatacontextcommandparameter

CommandParameter with MVVM Light


I'm trying to get a RelayCommand working with a CommandParameter working using MVVM Light. The command is defined in my viewmodel, and I want to pass the selected ListBox item as the parameter. The command is bound, but the parameter is not. Is this possible?

<UserControl x:Class="Nuggets.Metro.Views.EmployeeListView"
         ...
         DataContext="{Binding EmployeeList,Source={StaticResource Locator}}">
   <ListBox x:Name="lstEmployee" ItemsSource="{Binding EmployeeItems}" Style="{StaticResource EmployeeList}" Tag="{Binding EmployeeItems}">
        <ListBox.ContextMenu>
            <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
                <MenuItem Header="Edit item" Command="{Binding EditEmployeeCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
                <MenuItem Header="Delete item" Command="{Binding DeleteEmployeeCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
            </ContextMenu>
        </ListBox.ContextMenu>

Solution

  • This should work

    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
      <MenuItem Header="Edit item" 
                Command="{Binding EditEmployeeCommand}" 
                CommandParameter="{Binding SelectedItem,ElementName=lstEmployee}"/>
      <MenuItem Header="Delete item" 
                Command="{Binding DeleteEmployeeCommand}"
                CommandParameter="{Binding SelectedItem,ElementName=lstEmployee}"/>
     </ContextMenu>
    

    Use the Name of your ListBox als ElementName in the binding of the CommandParameter and set the path to SelectedItem.

    Update:

    The above code does not work for ListBox and ContextMenu, cause they belong to diffrent visual trees. The result is

    System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=lstEmployee'. BindingExpression:Path=SelectedItem; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')
    

    The following XAML does the job. Using the PlacementTarget (that is the ListBox) of the ContextMenu.

    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
      <MenuItem Header="Edit item" 
                Command="{Binding EditEmployeeCommand}" 
                CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
      <MenuItem Header="Delete item" 
                Command="{Binding DeleteEmployeeCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
    </ContextMenu>