Edit this page

Use a RadContextMenu in MVVM

This tutorial will show you how use a RadContextMenu with a RadGridView

It will show you how to do the following:

Define a RadContextMenu with MenuItems

First you need to define the context menu with menu items.

<local:ObjectToStringConverter x:Key="ObjectToStringConverter" />
<local:RadContextMenuXamlHolder x:Key="ContextMenuHolder">
    <telerik:RadContextMenu DataContext="{Binding Path=UIElement.Column.DataControl.DataContext, RelativeSource={RelativeSource Self}}" InheritDataContext="False">
        <telerik:RadMenuItem Command="{Binding SortAscendingCommand}"
                    CommandParameter="{Binding Path=Menu.UIElement,
                                            RelativeSource={RelativeSource Self}}"
                    Header="{Binding Path=Menu.UIElement.Column.Header,
                                    RelativeSource={RelativeSource Self},
                                    Converter={StaticResource ObjectToStringConverter},
                                    ConverterParameter='Sort Ascending by &quot;{0}&quot;'}" />
        <telerik:RadMenuItem Command="{Binding SortDescendingCommand}"
                    CommandParameter="{Binding Path=Menu.UIElement,
                                            RelativeSource={RelativeSource Self}}"
                    Header="{Binding Path=Menu.UIElement.Column.Header,
                                    RelativeSource={RelativeSource Self},
                                    Converter={StaticResource ObjectToStringConverter},
                                    ConverterParameter='Sort Descending by &quot;{0}&quot;'}" />
        <telerik:RadMenuItem Command="{Binding ClearSortCommand}"
                    CommandParameter="{Binding Path=Menu.UIElement,
                                            RelativeSource={RelativeSource Self}}"
                    Header="{Binding Path=Menu.UIElement.Column.Header,
                                    RelativeSource={RelativeSource Self},
                                    Converter={StaticResource ObjectToStringConverter},
                                    ConverterParameter='Clear Sorting by &quot;{0}&quot;'}" />
        <telerik:RadMenuItem Command="{Binding GroupbyCommand}"
                    CommandParameter="{Binding Path=Menu.UIElement,
                                            RelativeSource={RelativeSource Self}}"
                    Header="{Binding Path=Menu.UIElement.Column.Header,
                                    RelativeSource={RelativeSource Self},
                                    Converter={StaticResource ObjectToStringConverter},
                                    ConverterParameter='Group by &quot;{0}&quot;'}" />
        <telerik:RadMenuItem Command="{Binding UngroupCommand}"
                    CommandParameter="{Binding Path=Menu.UIElement,
                                            RelativeSource={RelativeSource Self}}"
                    Header="{Binding Path=Menu.UIElement.Column.Header,
                                    RelativeSource={RelativeSource Self},
                                    Converter={StaticResource ObjectToStringConverter},
                                    ConverterParameter='Ungroup by &quot;{0}&quot;'}" />
        <telerik:RadMenuItem Header="Choose Columns:" ItemsSource="{Binding Path=Menu.UIElement.Column.DataControl.Columns, RelativeSource={RelativeSource Self}}">
            <telerik:RadMenuItem.ItemContainerStyle>
                <Style TargetType="telerik:RadMenuItem">
                    <Setter Property="Header" Value="{Binding Header}" />
                    <Setter Property="IsChecked" Value="{Binding IsVisible, Mode=TwoWay}" />
                    <Setter Property="IsCheckable" Value="True" />
                </Style>
            </telerik:RadMenuItem.ItemContainerStyle>
        </telerik:RadMenuItem>
    </telerik:RadContextMenu>
</local:RadContextMenuXamlHolder>

Create a style for the column headers

You need to attach the defined context menu to the column headers.

<Style TargetType="telerik:GridViewHeaderCell">
    <Setter Property="telerik:RadContextMenu.ContextMenu" Value="{Binding Path=ContextMenu, Source={StaticResource ContextMenuHolder}}" />
</Style>

Define the RadGridView

The style targeting GridViewHeaderCell will be automatically applied for the RadGridView

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource ViewModel}">
    <telerik:RadGridView ItemsSource="{Binding Items}" />
</Grid>

Implementaions in code behind

The RadContextMenuXamlHolder class is defined in code behind like so:

[ContentProperty("ContextMenu")]
public class RadContextMenuXamlHolder : INotifyPropertyChanged
{
    private RadContextMenu contextMenu;
    public event PropertyChangedEventHandler PropertyChanged;

    public RadContextMenu ContextMenu
    {
        get
        {
            return this.contextMenu;
        }
        set
        {
            if (this.contextMenu != value)
            {
                this.contextMenu = value;
                this.RaisePropertyChanged("ContextMenu");
            }
        }
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The RadContextMenuXamlHolder class is defined as follows:

public class ObjectToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return string.Format(System.Convert.ToString(parameter), value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The implementation of the ViewModel is below:

public ViewModel()
{
    this.Items = LoadData();

    this.SortAscendingCommand = new DelegateCommand(OnSortAscending, CanSortAscending);
    this.SortDescendingCommand = new DelegateCommand(OnSortDescending, CanSortDescending);
    this.ClearSortCommand = new DelegateCommand(OnClearSort, CanClearSort);
    this.GroupbyCommand = new DelegateCommand(OnGroupby, CanGroupby);
    this.UngroupCommand = new DelegateCommand(OnUngroup, CanUngroup);
}

public DelegateCommand SortAscendingCommand { get; private set; }
public DelegateCommand SortDescendingCommand { get; private set; }
public DelegateCommand ClearSortCommand { get; private set; }
public DelegateCommand GroupbyCommand { get; private set; }
public DelegateCommand UngroupCommand { get; private set; }

public IEnumerable Items
{
    get;
    private set;
}

private static void Sort(GridViewHeaderCell cell, ListSortDirection sortDirection)
{
    RadGridView grid = cell.Column.DataControl as RadGridView;
    ColumnSortDescriptor sd = (from d in grid.SortDescriptors.OfType<ColumnSortDescriptor>()
                               where object.Equals(d.Column, cell.Column)
                               select d).FirstOrDefault();

    if (sd != null)
    {
        grid.SortDescriptors.Remove(sd);
    }

    ColumnSortDescriptor newDescriptor = new ColumnSortDescriptor();
    newDescriptor.Column = cell.Column;
    newDescriptor.SortDirection = sortDirection;

    grid.SortDescriptors.Add(newDescriptor);
}

private void OnSortAscending(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.Ascending)
    {
        Sort(cell, ListSortDirection.Ascending);
    }
}

private bool CanSortAscending(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.CanSort() && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.Ascending)
    {
        return true;
    }

    return false;
}

private void OnSortDescending(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.CanSort() && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.Descending)
    {
        Sort(cell, ListSortDirection.Descending);
    }
}

private bool CanSortDescending(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.CanSort() && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.Descending)
    {
        return true;
    }

    return false;
}

private void OnClearSort(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.CanSort() && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.None)
    {
        RadGridView grid = cell.Column.DataControl as RadGridView;
        ColumnSortDescriptor sd = (from d in grid.SortDescriptors.OfType<ColumnSortDescriptor>()
                                   where object.Equals(d.Column, cell.Column)
                                   select d).FirstOrDefault();

        if (sd != null)
        {
            grid.SortDescriptors.Remove(sd);
        }
    }
}

private bool CanClearSort(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.CanSort() && cell.Column.DataControl != null && cell.Column.SortingState != SortingState.None)
    {
        return true;
    }

    return false;
}

private void OnGroupby(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.DataControl != null && cell.Column.CanGroup())
    {
        RadGridView grid = cell.Column.DataControl as RadGridView;

        ColumnGroupDescriptor gd = (from d in grid.GroupDescriptors.OfType<ColumnGroupDescriptor>()
                                    where object.Equals(d.Column, cell.Column)
                                    select d).FirstOrDefault();

        if (gd == null)
        {
            ColumnGroupDescriptor newDescriptor = new ColumnGroupDescriptor();
            newDescriptor.Column = cell.Column;
            newDescriptor.SortDirection = ListSortDirection.Ascending;
            grid.GroupDescriptors.Add(newDescriptor);
        }
    }
}

private bool CanGroupby(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.DataControl != null && cell.Column.CanGroup())
    {
        RadGridView grid = cell.Column.DataControl as RadGridView;

        ColumnGroupDescriptor gd = (from d in grid.GroupDescriptors.OfType<ColumnGroupDescriptor>()
                                    where object.Equals(d.Column, cell.Column)
                                    select d).FirstOrDefault();

        if (gd == null)
        {
            return true;
        }
    }

    return false;
}

private void OnUngroup(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.DataControl != null && cell.Column.CanGroup())
    {
        RadGridView grid = cell.Column.DataControl as RadGridView;

        ColumnGroupDescriptor gd = (from d in grid.GroupDescriptors.OfType<ColumnGroupDescriptor>()
                                    where object.Equals(d.Column, cell.Column)
                                    select d).FirstOrDefault();

        if (gd != null)
        {
            grid.GroupDescriptors.Remove(gd);
        }
    }
}

private bool CanUngroup(object parameter)
{
    GridViewHeaderCell cell = parameter as GridViewHeaderCell;
    if (cell != null && cell.Column != null && cell.Column.DataControl != null && cell.Column.CanGroup())
    {
        RadGridView grid = cell.Column.DataControl as RadGridView;

        ColumnGroupDescriptor gd = (from d in grid.GroupDescriptors.OfType<ColumnGroupDescriptor>()
                                    where object.Equals(d.Column, cell.Column)
                                    select d).FirstOrDefault();

        if (gd != null)
        {
            return true;
        }
    }

    return false;
}

private static List<Order> LoadData()
{
    // return data
    return new List<Order>();
}
    }

The defined ContextMenu works

gridview-how-to-use-radcontextmenu-mvvm 1

A sample project can be downloaded here.
You can also check Header Context Menu and Row Context Menu WPF Demos.

Was this article helpful? Yes No

Give article feedback

Tell us how we can improve this article

Dummy