wpfmvvmbindingcommandcommandbinding

MVVM Command binding for contextemenu of TreeView Element


I need to bind a command (RelayCommand) of my ViewModel with the click event on an element of the conetxtmenu for a treeviewitem

ViewModel Command

private RelayCommand _myElementCommand;
public RelayCommand MyCommand
{
    get
    {
        return _myElementCommand?? (_myElementCommand= new RelayCommand(
           x =>
           {
               //LoadData();
               MessageBox.Show("Clicked!");
           }));
    }
}

VIEW

<TreeView x:Name="tvUBR" ItemsSource="{Binding UBRList, UpdateSourceTrigger=PropertyChanged}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" Text="{ Binding Description }">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Setter Property="Foreground" Value="Black" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsMatch}"
                                                Value="True">
                                    <Setter Property="Foreground" Value="Green" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                    <TextBlock.ContextMenu>
                        <ContextMenu>
                            <!--<MenuItem Header="Details" Command="{Binding DropedElementCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>-->
                            <MenuItem Header="Details">
                                <i:Interaction.Triggers>
                                <!-- EventName ??? -->
                                    <i:EventTrigger EventName="Click"> 
                                        <i:InvokeCommandAction Command="{Binding Path=PlacementTarget.Tag.DataContext.MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </MenuItem>
                        </ContextMenu>
                    </TextBlock.ContextMenu>
                </TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectedItemChanged">
            <i:InvokeCommandAction Command="{Binding SelectedUBRElementCommand}" 
                                            CommandParameter="{Binding SelectedItem, ElementName=tvUBR}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="b:TreeViewItemBehavior.IsBroughtIntoViewWhenSelected" Value="True" />
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

Any idea how to achieve this?


Solution

  • You could bind the Tag property of the TextBlock to the view model and then bind to the command using the PlacementTarget property of the ContextMenu:

    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
        <StackPanel Orientation="Horizontal">
            <TextBlock VerticalAlignment="Center" Text="{ Binding Description }">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType=TreeView}}" />
                        <Setter Property="Foreground" Value="Black" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsMatch}" Value="True">
                                <Setter Property="Foreground" Value="Green" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
                <TextBlock.ContextMenu>
                    <ContextMenu>
                        <MenuItem Header="Details"
                                  Command="{Binding PlacementTarget.Tag.MyCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
                    </ContextMenu>
                </TextBlock.ContextMenu>
            </TextBlock>
        </StackPanel>
    </HierarchicalDataTemplate>