Telerik blogs

Telerik RadControls for Silverlight provide a very powerful ContextMenu control, that supports right click, modifier keys and that can be easily attached to any visual element. In this article I will show how to attach RadContextMenu to a data-bound RadTreeView and perform actions on the clicked treeview items, depending on the selection in the context menu. For simplicity, here I will use a treeview, bound to a static collection, but it can be easily extended to load its items from a web service:

<UserControl x:Class="ContextMenuInTreeView.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ContextMenuInTreeView" xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" xmlns:telerikNavigation="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"> <UserControl.Resources> <local:DataViewModel x:Key="ViewModel" /> <telerik:HierarchicalDataTemplate x:Key="TreeViewItemTemplate" ItemsSource="{Binding Children}"> <TextBlock Text="{Binding Text}"> <telerikNavigation:RadContextMenu.ContextMenu> <telerikNavigation:RadContextMenu> <telerikNavigation:RadMenuItem Header="New Child" /> <telerikNavigation:RadMenuItem Header="New Sibling" /> <telerikNavigation:RadMenuItem Header="Delete" /> </telerikNavigation:RadContextMenu> </telerikNavigation:RadContextMenu.ContextMenu> </TextBlock> </telerik:HierarchicalDataTemplate> </UserControl.Resources> <StackPanel Background="White" DataContext="{StaticResource ViewModel}"> <TextBlock Text="Right-click the tree view to show a context menu" /> <telerikNavigation:RadTreeView x:Name="TreeView" ItemsSource="{Binding Items}" ItemTemplate="{StaticResource TreeViewItemTemplate}" /> </StackPanel> </UserControl>

 

The DataViewModel class is the main data storage, that creates the TreeView data items. Its Items property is of type DataItemCollection and contains DataItem objects:

[ContentProperty("Children")]
public class DataItem
{
    public DataItem()
    {
        this.Children = new DataItemCollection();
    }

    public string Text { get; set; }

    public DataItemCollection Children { get; private set; }
}

public class DataItemCollection : ObservableCollection<DataItem>
{
}

 

To enable the right clicking you should make the Silverlight plugin windowless. To do that open the ASPX page where the Silverlight is declared and add attribute windowless=”true”:

<asp:Silverlight ID="Xaml1" runat="server" 
 Windowless="true" Source="~/ClientBin/ContextMenuInTreeView.xap" 
 MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />

 

If your Silverlight plugin is declared as an Object element, add the following param tag:

<object ...>
  <param name="windowless" value="true"/>
  ...
</object>

 

The final result should look like this:

ContextMenuInTreeView

 

To add a handler for the Click event of the context menu, add the following line in the page constructor:

using Telerik.Windows;
public partial class Page : System.Windows.Controls.UserControl
{
    public Page()
    {
        InitializeComponent();

        this.TreeView.AddHandler(RadMenuItem.ClickEvent, 
            new RoutedEventHandler(OnContextMenuClick));
    }

    ...
}

Note that the AddHandler() extension method is defined in the Telerik.Windows namespace. You should add “using Telerik.Windows;” on top of your code behind if you don’t already have it.

The OnContextMenuClick() method finds the clicked RadTreeViewItem and performs the selected action:

private void OnContextMenuClick(object sender, RoutedEventArgs args)
{
    // Get the clicked context menu item
    RadMenuItem menuItem = ((RadRoutedEventArgs)args).OriginalSource as RadMenuItem;

    // Find the tree item that is associated with the clicked context menu item
    RadTreeViewItem treeViewItem = FindParentOfType<RadTreeViewItem>(menuItem);

    DataItem dataItem = treeViewItem.Item as DataItem;

    ItemsControl parentItemsControl = 
        (ItemsControl)treeViewItem.ParentItem ?? 
        treeViewItem.ParentTreeView;

    string header = menuItem.Header as string;
    switch (header)
    {
        case "New Child":
            dataItem.Children.Add(new DataItem() { Text = "New Item" });
            break;

        case "New Sibling":
            (parentItemsControl.ItemsSource as DataItemCollection).Add(
 new DataItem() { Text = "New Item" });
            break;

        case "Delete":
            (parentItemsControl.ItemsSource as DataItemCollection).Remove(dataItem);
            break;
    }
}

The final element is the FindParentOfType<T>() method, which makes possible finding the RadTreeViewItem that is associated with a given RadMenuItem:

private static T FindParentOfType<T>(UIElement element) where T : UIElement
{
    if (element == null) return null;

    DependencyObject parent = 
        Telerik.Windows.RoutedEvent.GetLogicalParent(element) ?? 
        VisualTreeHelper.GetParent(element);

    while ((parent != null) && !(parent is T))
    {
        parent = 
            Telerik.Windows.RoutedEvent.GetLogicalParent(parent) ?? 
            VisualTreeHelper.GetParent(parent);
    }

    return (T)parent;
}

 

The source code of the application can be found here:


About the Author

Valeri Hristov

Team Lead,
Platform Team

Comments

Comments are disabled in preview mode.