1

i have a HierarchicalDataTemplate for a TreeViewItem, in the template i have a contextmenu and i want to pass as CommandParameter the ContextMenu parent - i.e the TreeViewItem owner that was right clicked at the moment, is there a way to do that? here is my template:

    <HierarchicalDataTemplate 
    x:Key="ServerTemplate"
    DataType="{x:Type models:Server}" 
    ItemsSource="{Binding Channels}"
    ItemTemplate="{StaticResource ChannelTemplate}">
    <StackPanel
        Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"
        Orientation="Horizontal">
        <StackPanel.ContextMenu>
            <ContextMenu
                FontSize="14"
                FontFamily="Arial">
                <MenuItem 
                    Header="{x:Static p:Resources.ServerOperations_CommunicationSettings}"
                    Command="{Binding PlacementTarget.Tag.ServerCommunicationSettingCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContextMenu}}}"
                    CommandParameter="{Binding Path=Parent, RelativeSource={RelativeSource Mode=Self}}">
                </MenuItem>

            </ContextMenu>
        </StackPanel.ContextMenu>
        <Image 
            Source="{Binding ImageURL, Converter={StaticResource StringToImageConverter}}"
            Margin="0,0,2,0"
            Height="25"
            Width="25"/>
        <TextBlock 
            Text="{Binding ServerName}"
            Foreground="White"/>
    </StackPanel>
</HierarchicalDataTemplate>

thanks for the help

user1531186
  • 323
  • 1
  • 7
  • 20

1 Answers1

3

You can get the TreeViewItem by getting PlacementTarget of ContextMenu which will be StackPanel and its TemplatedParent will be ContentPresenter and its TemplatedParent will be TreeViewItem. So this will work:

CommandParameter="{Binding Path=PlacementTarget.TemplatedParent.TemplatedParent, 
                           RelativeSource={RelativeSource Mode=FindAncestor,
                                            AncestorType={x:Type ContextMenu}}}"

PlacementTarget (StackPanel) --> TemplatedParent (ContentPresenter) --> TemplatedParent (TreeViewItem)


Ideally it's not a good idea to pass UI components to ViewModel. You should pass data i.e. DataContext of TreeViewItem as you can always play with that.

In case you want to pass Server instance i.e. DataContext of TreeviewItem, you can simply do "{Binding}" since MenuItem will inherit it from StackPanel.

CommandParameter="{Binding}"
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • you are that what i meant sorry for the confusion, but your way of passing the DataContext doesn't work(it causes the contextmenu to be non repsonsive for the user), apparently all is needed is CommandParameter={Binding} thing is that now the contextmenu is not responsive for the first time u right click to open, and from the second time it works fine... – user1531186 Mar 17 '14 at 08:03
  • It works at my end though. But yeah you are right MenuItem will inherit `DataContext` as well. So simple binding will work too. I will update in answer. – Rohit Vats Mar 17 '14 at 08:06
  • `contextmenu is not responsive for the first time` - What do you mean by this? Small sample in my code and it all works fine for me. Do you have `CanExecute` on `ICommand` which is most likely cause for disabling it? – Rohit Vats Mar 17 '14 at 08:10
  • 1
    my bad... it was my CanExecute method that didn't work properly, for some reason the first time u call CanExecute when an item is right clicked the DataContext is null, but if u simply send the parameter for the execution method it passes correctly... weird... thanks a lot for your help man! – user1531186 Mar 17 '14 at 08:13