Creating dynamic ContextMenu for TreeView in WPF
Views (563)
Hi,
Sharing a simple example wherein we are generating dynamic menuitems for the context menu based on the node or treeviewitem selected in the treeview.
If root Packages is selected –

If Package is selected –

If Batch is selected –

The xml file
<?xml version="1.0" encoding="utf-8" ?> <Packages> <Package Name="Package 1" Type="Package"> <Batch Name="Batch 1" Type="Batch"/> <Batch Name="Batch 2" Type="Batch"/> </Package> <Package Name="Package 2" Type="Package"> <Batch Name="Batch 1" Type="Batch"/> <Batch Name="Batch 2" Type="Batch"/> </Package> </Packages>
XAML
<Window x:Class="SampleSyncServerAdminTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!--Binding TreeView-->
<XmlDataProvider x:Key="MyList" Source="Packages.xml" XPath="Packages"/>
<HierarchicalDataTemplate DataType="Packages" ItemsSource="{Binding XPath=*}">
<TextBlock Text="Packages"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Package" ItemsSource="{Binding XPath=*}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Batch" ItemsSource="{Binding XPath=*}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
<!-- Resources for Right Hand Side detail grid-->
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel Width="120">
<Button
Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Courier"
FontSize="9"
FontWeight="Bold"
Margin="0,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16" Height="16"
/>
<ContentPresenter
Content="{Binding Path=DisplayName}"
VerticalAlignment="Center"
/>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
</Window.Resources>
<Grid>
<DockPanel>
<TreeView DockPanel.Dock="Left" Width="150" Name="treeViewPackages"
ItemsSource="{Binding Source={StaticResource MyList}}">
<TreeView.Resources>
<ContextMenu x:Key="TestMenu">
</ContextMenu>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
<EventSetter Event="PreviewMouseRightButtonDown"
Handler="OnPreviewMouseRightButtonDown" />
</Style> </TreeView.ItemContainerStyle>
</TreeView>
<Grid DockPanel.Dock="Right">
<HeaderedContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}"
Header="Workspaces"
/>
</Grid>
</DockPanel>
</Grid>
</Window>
XAML.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace SampleSyncServerAdminTool
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject obj = e.OriginalSource as DependencyObject;
TreeViewItem item = GetDependencyObjectFromVisualTree(obj, typeof(TreeViewItem)) as TreeViewItem;
XmlElement selectedElement = (XmlElement)item.Header;
string header = selectedElement.Name;
if (header.ToUpper() == "PACKAGES")
{
// Packages root node
MenuItem mnuItem = new MenuItem();
mnuItem.Header = "New Package";
ContextMenu menu = new ContextMenu() { };
menu.Items.Add(mnuItem);
(sender as TreeViewItem).ContextMenu = menu;
}
else
{
string attName = selectedElement.Attributes["Name"].Value;
string type = selectedElement.Attributes["Type"].Value;
string fullNodeInfo = "Header: " + header + " Attribute Name: " + attName + " Type: " + type;
if (type.ToUpper() == "PACKAGE")
{
MenuItem mnuItem1 = new MenuItem();
mnuItem1.Header = "New Package";
MenuItem mnuItem2 = new MenuItem();
mnuItem2.Header = "Show Package Details";
MenuItem mnuItem3 = new MenuItem();
mnuItem3.Header = "Edit Package";
MenuItem mnuItem4 = new MenuItem();
mnuItem4.Header = "Delete Package";
MenuItem mnuItem5 = new MenuItem();
mnuItem5.Header = "Add to Queue";
ContextMenu menu = new ContextMenu() { };
menu.Items.Add(mnuItem1);
menu.Items.Add(mnuItem2);
menu.Items.Add(mnuItem3);
menu.Items.Add(mnuItem4);
menu.Items.Add(mnuItem5);
(sender as TreeViewItem).ContextMenu = menu;
}
else if (type.ToUpper() == "BATCH")
{
MenuItem mnuItem1 = new MenuItem();
mnuItem1.Header = "Show Batch Details";
MenuItem mnuItem2 = new MenuItem();
mnuItem2.Header = "Edit Batch";
MenuItem mnuItem3 = new MenuItem();
mnuItem3.Header = "Delete Batch";
ContextMenu menu = new ContextMenu() { };
menu.Items.Add(mnuItem1);
menu.Items.Add(mnuItem2);
menu.Items.Add(mnuItem3);
(sender as TreeViewItem).ContextMenu = menu;
}
}
}
private static DependencyObject GetDependencyObjectFromVisualTree(DependencyObject startObject, Type type)
{
var parent = startObject;
while (parent != null)
{
if (type.IsInstanceOfType(parent))
break;
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}
}
}
Bye.
Filed under: WPF Tagged: WPF
This was originally posted here.

Like
Report
*This post is locked for comments