2

Good daytime.

I've got a problem with creating ContextMenu of TreeView. The problem is very simple. I want to add new items to treeview clicking RMB on treeviewitem and selecting a context menu command.
I know that I need to pass to my command a parameter that contains parent item. BUT. I need that I can RMB click on any treeviewitem, not only selected.
And heres the question:
How to pass the binded data of treeviewitem to my command.

Here is class diag enter image description here

Here is Xaml (EDIT)

        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Item.Children}">
                <TextBlock Text="{Binding Item.Code}" HorizontalAlignment="Stretch">
                    <TextBlock.ContextMenu>
                        <ContextMenu Name="MyContextMenu" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
                            <MenuItem Header="{Binding DataContext.ToString()}" Command="{Binding DataContext.Item.AddNewItemCommand}" CommandParameter="{Binding}"/>
                        </ContextMenu>                            
                    </TextBlock.ContextMenu>
                </TextBlock>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>

But it does not even call my command.

    private void AddNewItem(object toItem)
    {
        if (toItem == null)
            return;
        ItemViewModel item = toItem as ItemViewModel;
        ItemMaterialModel itemMaterial = new ItemMaterialModel(ItemModel.CreateNewItem());

        ItemMaterialViewModel itemMaterialViewModel = new ItemMaterialViewModel(itemMaterial);
        item.Children.Add(itemMaterialViewModel);
    }

Maybe my command in wrong ViewModel?

Regards, Dmitry.

IAbstract
  • 19,551
  • 15
  • 98
  • 146
StNickolas
  • 576
  • 7
  • 20
  • have you tried binding it to CommandParameter – yo chauhan Feb 03 '13 at 13:43
  • @ethicallogics That is actuallly part of the question. 1st I dont know how to bind it to commandparameter. And 2nd I dont know how to pass NOT selected, but just r-clikcked element. – StNickolas Feb 03 '13 at 13:48

3 Answers3

2

Hi this is just a way you can bind

        <ContextMenu Name="MyContextMenu" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
                <MenuItem Header="Add" Command="{Binding DataContext.AddNewItemCommand}" CommandParameter="{Binding }"/>
            </ContextMenu>

I hope this will help.

yo chauhan
  • 12,079
  • 4
  • 39
  • 58
  • This is good, but it can be used only for selected item. I need to detect rightclicked item – StNickolas Feb 03 '13 at 14:24
  • for that you can use the PlacementTarget Property of the ContextMenu – yo chauhan Feb 03 '13 at 14:30
  • same result I think there must be some property that indicates is mouse over the node. Bute using MVVM I dont know where to place it but codebehind – StNickolas Feb 03 '13 at 14:50
  • I am not sure whats wrong but PlacementTarget guna solve your problem if on right click ContextMenu opens – yo chauhan Feb 03 '13 at 14:58
  • What this PlacementTarget exactly must do? – StNickolas Feb 03 '13 at 15:17
  • It gives the reference of UIElement on which your ContextMenu opens – yo chauhan Feb 03 '13 at 15:38
  • i have updated solution with some dummy code . you can refer it .In this it works. – yo chauhan Feb 03 '13 at 15:58
  • Modified my question, take a look – StNickolas Feb 04 '13 at 14:00
  • I can see issue in it and updated the answer try it.PlacementTarget is a Property of ContextMenu. – yo chauhan Feb 04 '13 at 14:17
  • Now it passed some parameter, but it is not correct parameter. If I Bind `{Binding}` to `CommandParameter` what data should pass? It passes ItemCollection Of treeview now – StNickolas Feb 04 '13 at 14:26
  • What you exactly want in command parameter . You can extract from it. – yo chauhan Feb 04 '13 at 14:45
  • I need DataContext if TreeViewItem on which Right Click were invoked. Im new to wpf and mvvm, so great thanks for your responses. – StNickolas Feb 04 '13 at 14:53
  • if you want MainItem.Code then do CommandParameter="{Binding Header}" ,If you want MainItem.Children then do CommandParameter="{Binding ItemsSource}" . And don,t forget to cast them to their appropriate type because from here you will get the of object type. – yo chauhan Feb 04 '13 at 16:55
  • I think I understood one thing. I think I placed my command in wrong ViewModel, or just have wrong class structure. Because when I click on MenuItem I get ViewModel of whole UserControl, but i need to get ViewModel only for one TreeViewItem. – StNickolas Feb 04 '13 at 17:14
  • I have updated my post. Can you tell me which class is binded for context menu now? – StNickolas Feb 05 '13 at 16:35
2

Thanks to ethicallogics and his info about PlacementProperty, I've modified my Xaml like here:

        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Item.Children}">
                <TextBlock Text="{Binding Item.Code}" HorizontalAlignment="Stretch">
                    <TextBlock.ContextMenu>
                        <ContextMenu DataContext="{Binding PlacementTarget.DataContext,RelativeSource={RelativeSource Mode=Self}}">
                            <MenuItem 
                                Header="{Binding Item.Code}"
                                Command="{Binding Item.AddNewItemCommand}" 
                                      CommandParameter="{Binding Item}"/>
                        </ContextMenu>                            
                    </TextBlock.ContextMenu>
                </TextBlock>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>

And in my StructureManagerViewModel I made not simple MainItem, but a collection of MainItems used in itemssourse of tree.

Regards, Dmitry.
Hope this experience will help people.

StNickolas
  • 576
  • 7
  • 20
0

You can use the code found here to detect the item under the right click (and select it for positive visual feedback).

Follow this link for an explanation of what PlacementTarget is doing in the solution provided by @ethicallogics.

Hopefully you can use a combination of the two answers to solve your problem.

Community
  • 1
  • 1
Mash
  • 1,496
  • 13
  • 17