Use Commands with the RadContextMenu

As the RadMenuItem implements the ICommandSource interface, you are able to use any kind of commands that inherit from the ICommand interface with it. This tutorial will show you how to use the RadContextMenu with RoutedUICommands combined with the MVVM pattern. Two commands are going to be exposed - one for moving an item in a ListBox up and one for moving an item down. The following things will come in focus:

Attaching a RadContextMenu to a ListBox control

Before getting to the commands, you have to prepare the UI on which they will get executed. In this tutorial a ListBox and a RadContextMenu are used.

<ListBox x:Name="listBox"> 
    <telerik:RadContextMenu.ContextMenu> 
        <telerik:RadContextMenu x:Name="radContextMenu"> 
        </telerik:RadContextMenu> 
    </telerik:RadContextMenu.ContextMenu> 
</ListBox> 

Having the UI prepared, you have to add some data to it.

Populating the ListBox with data via a ViewModel

As the MVVM pattern should be used, you have to create a ViewModel for your UserControl, which will control its behavior. In it you will store the data which the View is using. Here is the declaration of the ViewModel class. It has a constructor, a method that initializes the items for the ListBox and an Items property, that stores them. Additionally create a SelectedItem property that will hold the selected item of the ListBox.

public class ExampleViewModel : INotifyPropertyChanged 
{ 
    private DataItem selectedItem; 
    public ExampleViewModel() 
    { 
        this.InitItems(); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    public ObservableCollection<DataItem> Items 
    { 
        get; 
        set; 
    } 
    public DataItem SelectedItem 
    { 
        get 
        { 
            return this.selectedItem; 
        } 
        set 
        { 
            if (this.selectedItem != value) 
            { 
                this.selectedItem = value; 
                this.OnNotifyPropertyChanged("SelectedItem"); 
            } 
        } 
    } 
    private void OnNotifyPropertyChanged(string propertyName) 
    { 
        if (this.PropertyChanged != null) 
        { 
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
        } 
    } 
    private void InitItems() 
    { 
        ObservableCollection<DataItem> items = new ObservableCollection<DataItem>(); 
        items.Add(new DataItem("Item 1")); 
        items.Add(new DataItem("Item 2")); 
        items.Add(new DataItem("Item 3")); 
        this.Items = items; 
    } 
} 
Public Class ExampleViewModel 
    Implements INotifyPropertyChanged 
    Private selectedItemField As DataItem 
    Public Sub New() 
        Me.InitItems() 
    End Sub 
    Public Property Items() As ObservableCollection(Of DataItem) 
        Get 
        End Get 
        Set(value As ObservableCollection(Of DataItem)) 
        End Set 
    End Property 
    Public Property SelectedItem() As DataItem 
        Get 
            Return Me.selectedItemField 
        End Get 
        Set(value As DataItem) 
            If Me.selectedItemField Is value Then 
                Me.selectedItemField = value 
                Me.NotifyPropertyChanged("SelectedItem") 
            End If 
        End Set 
    End Property 
 
    Private Sub InitItems() 
        Dim items As New ObservableCollection(Of DataItem)() 
        items.Add(New DataItem("Item 1")) 
        items.Add(New DataItem("Item 2")) 
        items.Add(New DataItem("Item 3")) 
        Me.Items = items 
    End Sub 
 
    Public Event PropertyChanged As PropertyChangedEventHandler _ 
        Implements INotifyPropertyChanged.PropertyChanged 
 
    Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing) 
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
    End Sub 
End Class 

In the constructor of the UserControl you have to create an instance of the ViewModel, store it in a field and pass it as a DataContext of the entire UserControl.

private ExampleViewModel viewModel; 
public Default_Cs() 
{ 
    InitializeComponent(); 
    this.viewModel = new ExampleViewModel(); 
    this.DataContext = viewModel; 
} 
Private viewModel As ExampleViewModel 
Public Sub New() 
    InitializeComponent() 
    Me.viewModel = New ExampleViewModel() 
    Me.DataContext = viewModel 
End Sub 

In the XAML you have to set the SelectedItem, the DisplayMemberPath and the ItemsSource properties of the ListBox in order to visualize the data.

<ListBox x:Name="listBox1" 
         DisplayMemberPath="Value" 
         ItemsSource="{Binding Items}" 
         SelectedItem="{Binding SelectedItem, Mode=TwoWay}"> 
    <telerik:RadContextMenu.ContextMenu> 
        <telerik:RadContextMenu x:Name="radContextMenu1"> 
        </telerik:RadContextMenu> 
    </telerik:RadContextMenu.ContextMenu> 
</ListBox> 

Selecting the right-clicked ListBoxItem

Before continuing, there is one more thing to be done. When right-clicking to open the RadContextMenu, the clicked item should get selected, or if no item was clicked, the selection should be removed. This is done by handling the Opened event of the RadContextMenu.

<ListBox x:Name="listBox2" 
         DisplayMemberPath="Value" 
         ItemsSource="{Binding Items}" 
         SelectedItem="{Binding SelectedItem, Mode=TwoWay}"> 
    <telerik:RadContextMenu.ContextMenu> 
        <telerik:RadContextMenu x:Name="radContextMenu2" 
                                  Opened="RadContextMenu_Opened"> 
        </telerik:RadContextMenu> 
    </telerik:RadContextMenu.ContextMenu> 
</ListBox> 

private void RadContextMenu_Opened(object sender, RoutedEventArgs e) 
{ 
    System.Windows.Controls.ListBoxItem item = this.radContextMenu.GetClickedElement<System.Windows.Controls.ListBoxItem>(); 
    if (item != null) 
    { 
        this.listBox.SelectedItem = item.DataContext; 
    } 
    else 
    { 
        this.listBox.SelectedItem = null; 
    } 
} 
Private Sub RadContextMenu_Opened(sender As Object, e As RoutedEventArgs) 
    Dim item As System.Windows.Controls.ListBoxItem = Me.radContextMenu.GetClickedElement(Of System.Windows.Controls.ListBoxItem)() 
    If item Is Nothing Then 
        Me.listBox.SelectedItem = item.DataContext 
    Else 
        Me.listBox.SelectedItem = Nothing 
    End If 
End Sub 

Preparing the RoutedUICommands

The next step is to create your commands. They will be host by the ViewModel.

public RoutedUICommand MoveUpCommand 
{ 
    get; 
    private set; 
} 
public RoutedUICommand MoveDownCommand 
{ 
    get; 
    private set; 
} 
Public Property MoveUpCommand() As RoutedUICommand 
    Get 
    End Get 
    Private Set(value As RoutedUICommand) 
    End Set 
End Property 
Public Property MoveDownCommand() As RoutedUICommand 
    Get 
    End Get 
    Private Set(value As RoutedUICommand) 
    End Set 
End Property 

Initialize them in the constructor of the ViewModel:

public ExampleViewModel() 
{ 
    this.MoveUpCommand = new RoutedUICommand("Move Up", "MoveUp", typeof(ExampleViewModel)); 
    this.MoveDownCommand = new RoutedUICommand("Move Down", "MoveDown", typeof(ExampleViewModel)); 
    this.InitItems(); 
} 
Public Sub New() 
    Me.MoveUpCommand = New RoutedUICommand("Move Up", "MoveUp", GetType(ExampleViewModel)) 
    Me.MoveDownCommand = New RoutedUICommand("Move Down", "MoveDown", GetType(ExampleViewModel)) 
    Me.InitItems() 
End Sub 

Bind them in the View.

<ListBox x:Name="listBox3" 
         DisplayMemberPath="Value" 
         ItemsSource="{Binding Items}" 
         SelectedItem="{Binding SelectedItem, Mode=TwoWay}"> 
    <telerik:RadContextMenu.ContextMenu> 
        <telerik:RadContextMenu x:Name="radContextMenu3" 
                                Opened="RadContextMenu_Opened"> 
            <telerik:RadMenuItem Header="{Binding MoveUpCommand.Text}" 
                                 Command="{Binding MoveUpCommand}" /> 
            <telerik:RadMenuItem Header="{Binding MoveDownCommand.Text}" 
                                 Command="{Binding MoveDownCommand}" /> 
        </telerik:RadContextMenu> 
    </telerik:RadContextMenu.ContextMenu> 
</ListBox> 

You will also need methods that will get called when the command is executed. In the next section is explained how to connect the methods to the command. Here are sample methods for the two commands.

public void MoveUp(object sender, ExecutedRoutedEventArgs e) 
{ 
    if (this.SelectedItem == null || this.Items.IndexOf(this.SelectedItem as DataItem) == 0) 
    { 
        return; 
    } 
    DataItem item = this.SelectedItem; 
    int index = this.Items.IndexOf(item as DataItem); 
    this.Items.Remove(item as DataItem); 
    this.Items.Insert(index - 1, item as DataItem); 
    this.SelectedItem = item; 
} 
public void MoveDown(object sender, ExecutedRoutedEventArgs e) 
{ 
    if (this.SelectedItem == null || this.Items.IndexOf(this.SelectedItem as DataItem) == this.Items.Count - 1) 
    { 
        return; 
    } 
    DataItem item = this.SelectedItem; 
    int index = this.Items.IndexOf(item as DataItem); 
    this.Items.Remove(item as DataItem); 
    this.Items.Insert(index + 1, item as DataItem); 
    this.SelectedItem = item; 
} 
Public Sub MoveUp(sender As Object, e As ExecutedRoutedEventArgs) 
    If Me.SelectedItem Is Nothing OrElse Me.Items.IndexOf(TryCast(Me.SelectedItem, DataItem)) = 0 Then 
        Return 
    End If 
    Dim item As DataItem = Me.SelectedItem 
    Dim index As Integer = Me.Items.IndexOf(TryCast(item, DataItem)) 
    Me.Items.Remove(TryCast(item, DataItem)) 
    Me.Items.Insert(index - 1, TryCast(item, DataItem)) 
    Me.SelectedItem = item 
End Sub 
Public Sub MoveDown(sender As Object, e As ExecutedRoutedEventArgs) 
    If Me.SelectedItem Is Nothing OrElse Me.Items.IndexOf(TryCast(Me.SelectedItem, DataItem)) = Me.Items.Count - 1 Then 
        Return 
    End If 
    Dim item As DataItem = Me.SelectedItem 
    Dim index As Integer = Me.Items.IndexOf(TryCast(item, DataItem)) 
    Me.Items.Remove(TryCast(item, DataItem)) 
    Me.Items.Insert(index + 1, TryCast(item, DataItem)) 
    Me.SelectedItem = item 
End Sub 

Creating the CommandBindings

In order to use the commands in the UI you have to provide a CommandBinding for each of the commands. The CommandBinding binds the command to a method that is called when the command gets executed. The CommandBidnings get set via the CommandManager. As the CommandManager is called by the View you have to expose a method in your ViewModel that returns a collection of its CommandBindings.

public CommandBindingCollection GetCommandBindings() 
{ 
    CommandBindingCollection bindings = new CommandBindingCollection(); 
    bindings.Add(new CommandBinding(this.MoveUpCommand, this.MoveUp)); 
    bindings.Add(new CommandBinding(this.MoveDownCommand, this.MoveDown)); 
    return bindings; 
} 
Public Function GetCommandBindings() As CommandBindingCollection 
    Dim bindings As New CommandBindingCollection() 
    bindings.Add(New CommandBinding(Me.MoveUpCommand, Me.MoveUp)) 
    bindings.Add(New CommandBinding(Me.MoveDownCommand, Me.MoveDown)) 
    Return bindings 
End Function 

Setting the CommandBindings

In the View get the CommandBindingsCollection and set it through the CommandManager.

public Default_Cs() 
{ 
    InitializeComponent(); 
    this.viewModel = new ExampleViewModel(); 
    this.DataContext = viewModel; 
    CommandManager.SetCommandBindings(this, this.viewModel.GetCommandBindings()); 
} 
Public Sub New() 
    InitializeComponent() 
    Me.viewModel = New ExampleViewModel() 
    Me.DataContext = viewModel 
    CommandManager.SetCommandBindings(Me, Me.viewModel.GetCommandBindings()) 
End Sub 

See Also

In this article