Hello,
We need to create an MVVM solution for tree view control with context menu. The context menu has to be different for each node, based on the type of the node.
We have tried the following approach: binding the context menu items to given properties of the XamDataTree's ItemSource.
<ig:XamDataTree x:Name="customerGroupTreeView"
ActiveNodeChanged="customerGroupTreeViewProjects_ActiveNodeChanged"
ItemsSource="{Binding TreeViewCustomersGroup}"
BorderThickness="0">
<ig:XamDataTree.ContextMenu>
<ContextMenu Loaded="ContextMenu_Loaded">
<MenuItem Header="New"
IsEnabled="{Binding Data.IsNew}">MenuItem>
ContextMenu>
ig:XamDataTree.ContextMenu>
<ig:XamDataTree.EditingSettings>
<ig:TreeEditingSettings AllowDeletion="{Binding AllowDeletion}"
AllowEditing="{Binding AllowEditing}" />
ig:XamDataTree.EditingSettings>
<ig:XamDataTree.Resources>
<DataTemplate x:Key="NodeDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20">ColumnDefinition>
<ColumnDefinition>ColumnDefinition>
Grid.ColumnDefinitions>
<Image Grid.Column="0"
Height="16"
Width="16"
Source="{Binding Data.ImagePath}">
Image>
<TextBlock Text="{Binding Data.Name}"
Margin="5,0,0,0"
Grid.Column="1" />
Grid>
DataTemplate>
ig:XamDataTree.Resources>
<ig:XamDataTree.SelectionSettings>
<ig:TreeSelectionSettings NodeSelection="Single" />
ig:XamDataTree.SelectionSettings>
<ig:XamDataTree.GlobalNodeLayouts>
<ig:NodeLayout Key="MyNode"
TargetTypeName="Node"
ItemTemplate="{StaticResource NodeDataTemplate}">
ig:NodeLayout>
ig:XamDataTree.GlobalNodeLayouts>
ig:XamDataTree>
1. This binding isn't working. Can you please give an example of how the contextmenu would be bound to the Node data?
2. Also, we would like the Node which the user has right clicked on to be the selected node. How can we implement this?
Thanks!
DVSE Team
1) You set your context menu on the tree object, not on a node object. So the context menu would only have the properties available at that level.
You would probably want to set up the ItemTemplate off the NodeLayout to be something like this.
<ig:NodeLayout Key="blah" DisplayMemberPath="Name" TargetTypeName="Person"> <ig:NodeLayout.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Data.Name}"> <TextBlock.ContextMenu> <ContextMenu> <MenuItem Header="New" IsEnabled="{Binding Data.IsEnabled}" ></MenuItem> </ContextMenu> </TextBlock.ContextMenu> </TextBlock> </DataTemplate> </ig:NodeLayout.ItemTemplate></ig:NodeLayout>
As for how to activate the node which is right clicked. You would have to react to the right mouse down somehow and set the node to be the active node. One way you could try doing this is listening to when the context menu is opening and then have the information available to set the node active
<TextBlock.ContextMenu> <ContextMenu IsVisibleChanged="ContextMenu_IsVisibleChanged" Tag="{Binding Node}" > <MenuItem Header="New" IsEnabled="{Binding Data.IsEnabled}" ></MenuItem> </ContextMenu> </TextBlock.ContextMenu>
private void ContextMenu_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { // if the context menu is now visible
// check the Tag property of the context menu (the sender object)
// get the node out of the Tag and set the IsActive flag }
Hi Darrel,I've tried to follow your suggestion (looks great!) but when I set IsActive property, menu disappears...Any ideas? This is the full code:
<TextBlock.ContextMenu> <ContextMenu IsVisibleChanged="ContextMenu_IsVisibleChanged" Tag="{Binding Node}"> <MenuItem Header="Collapse" Command="{x:Static my:Control.collapseCommand}" /> </ContextMenu> </TextBlock.ContextMenu>
private void ContextMenu_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { ContextMenu menu = sender as ContextMenu; if (menu != null && menu.IsVisible) { XamDataTreeNode nd = menu.Tag as XamDataTreeNode; if (nd != null) { nd.IsActive = true; } } }
Thank you, bye. Maria
Hello Maria,
I have been looking into your post and I can say that this behavior is expected since the focus is moved to the Node after you set its IsActive Property to true.
Hope this helps you.
I have the same problem and I want to set the selected or active property when the context menu opens. So that the user understands for which item the context menu is opened and it is very confusing.
I have the same problem and it just goes away after it opens. I tried to do it on the right-click, context menu visible change, context menu opened events but, all of them have the same behavior and after them the context menu closes.
How can I fix this issue and achieve this?
Hello Arash,
I created a sample project where I set the Tag of the clicked Node to true and use this value in a Style's Trigger to set the Node's background, so the user can see which node is clicked.