views:

51

answers:

2

I want to use CommandParameter attribute in a context menu associated to a DataTemplate. The commandParameter should contain a reference to the object that triggered the data template as shown in the code sample below. I tried to use "{Binding Path=this}" but it does not work because "this" is not a property. The command fires but I can't get the right parameter. Do any one have an idea on how to do this?

Note: I removed Command="{Binding DeleteSelectedMeetingCommand}" by replacing it with a reference to the view locator and the command was triggering.

       <DataTemplate DataType="{x:Type Models:MeetingDbEntry}">

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"  Text="{Binding Path=HostTeam}"/>
            <TextBlock Grid.Column="1" Text="{Binding Path=GuestTeam}"/>
            <TextBlock Grid.Column="2" Text="{Binding Path=Result}"/>
            <Grid.ContextMenu>
                <ContextMenu Name="MeetingMenu">
                    <MenuItem Header="Delete"  
                              Command="{Binding 
                                            Source={StaticResource Locator}, 
                                            Path=Main.DeleteSelectedMeetingCommand}"
                              CommandParameter="{Binding Path=this}"/>
                </ContextMenu>
            </Grid.ContextMenu>
        </Grid>
    </DataTemplate>

Thanks,

A: 

I'd expose the DeleteSelectedMeetingCommand on the object it deletes and bind the context menu entry to it. Then add a member variable holding the object to delete to the command and initialize it with this in the object to delete that's holding the command.

Example:

public class DeletableObject
{
    public ICommand DeleteCommand { get; }

    public DeleteableObject()
    {
        DeleteCommand = new DeleteCommand(this);
    }
}

public class DeleteCommand : ICommand
{
    private DeletableObject _DeletableObject;

    public DeleteCommand(DeletableObject deletableObject)
    {
        _DeletableObject = deletableObject;
    }

    // skipped the implementation of ICommand but it deletes _DeletableObject
}

Hope that helps.

andyp
Thanks for the answer. In fact, I was using asimilar approach, I binded the selected item to a property and I used a command without parameters. The command then uses the selected property to delete the object.However, I am trying to explore the templated version of RelayCommand in MVVM Light toolkit and I want to bind to a RelayCommand directy through XAML without having to right specific code for binding (I succeeded to bind through the click attribute).
AmineK
A: 

It is working with the code below. You just need to type {Binding} in the CommandParameter attribute in order to reference the property that triggered the DataTemplate.

 <DataTemplate DataType="{x:Type Models:MeetingDbEntry}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"  Text="{Binding Path=HostTeam}"/>
            <TextBlock Grid.Column="1" Text="{Binding Path=GuestTeam}"/>
            <TextBlock Grid.Column="2" Text="{Binding Path=Result}"/>
            <Grid.ContextMenu>
                <ContextMenu Name="MeetingMenu">
                    <MenuItem Header="Delete"  
                              Command="{Binding 
                                      Source={StaticResource Locator}, 
                                      Path=Main.DeleteSelectedMeetingCommand}"
                              CommandParameter="{Binding}"
                              />

                </ContextMenu>
            </Grid.ContextMenu>
        </Grid>
    </DataTemplate>
AmineK