Interactive Features in UWP DataGrid (SfDataGrid)

22 Aug 202324 minutes to read

RowHeader

RowHeader is a special type of column used to indicate the currently focused row, editing status, and validation status. You can enable the RowHeader by setting SfDataGrid.ShowRowHeader property to true.

<syncfusion:SfDataGrid x:Name="dataGrid"
                       ShowRowHeader="True"
                       ItemsSource="{Binding Orders}"  />
dataGrid.ShowRowHeader = true;

Image used to display the row header enabled in uwp datagrid

You can change the default width of the RowHeader by using SfDataGrid.RowHeaderWidth property.

<syncfusion:SfDataGrid x:Name="dataGrid"
                       ShowRowHeader="True"
                       RowHeaderWidth="50"
                       ItemsSource="{Binding Orders}"  />
dataGrid.RowHeaderWidth = 50;

Customizing RowHeader

Display the RowIndex to the RowHeaderCell

You can display the corresponding row index in each RowHeader, by customizing the ControlTemplate of GridRowHeaderCell. You have to bind the RowIndex property to TextBlock.Text like the below code example.

<Style TargetType="syncfusion:GridRowHeaderCell">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="syncfusion:GridRowHeaderCell">
                <Border x:Name="PART_RowHeaderCellBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <TextBlock HorizontalAlignment="Center"
                                   VerticalAlignment="Center"
                                   Text="{Binding RowIndex,RelativeSource={RelativeSource TemplatedParent}}"
                                   TextAlignment="Center" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Image used to display the row index displayed in row header cell of uwp datagrid

You can get the sample from here.

Change the CurrentRow Indicator

You can change the CurrentRowIndicator in the RowHeader by customizing the control template of GridRowHeaderCell.

<Style TargetType="syncfusion:GridRowHeaderCell">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="syncfusion:GridRowHeaderCell">
                <Border x:Name="PART_RowHeaderCellBorder"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="IndicationStates">
                            <VisualState x:Name="Normal">
                            </VisualState>
                        <VisualState x:Name="CurrentRow">
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RowHeaderIndicator" Storyboard.TargetProperty="Data">
                                    <DiscreteObjectKeyFrame KeyTime="0">
                                        <DiscreteObjectKeyFrame.Value>
                                            <Geometry>F1M-218.342,2910.79L-234.066,2926.52 -233.954,2926.63 -225.428,2926.63 -210.87,2912.07 -206.495,2907.7 -225.313,2888.88 -234.066,2888.88 -218.342,2904.6 -259.829,2904.6 -259.829,2910.79 -218.342,2910.79z</Geometry>
                                        </DiscreteObjectKeyFrame.Value>
                                    </DiscreteObjectKeyFrame>
                                </ObjectAnimationUsingKeyFrames>                                            
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                    <Path x:Name="PART_RowHeaderIndicator"
                          Width="8.146"
                          Height="8.146"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Fill="#FF303030"
                          Stretch="Fill">
                    </Path>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Image used to display the current row indicator changed in uwp datagrid

You can get the sample from here.

Touch Support

ColumnResizing with the Touch

SfDataGrid allows you to re-size the columns in touch by press and hold the column header. You can enable resizing in SfDataGrid by setting AllowResizingColumns as True.

<syncfusion:SfDataGrid   x:Name="dataGrid" 
                         AllowResizingColumns="True" 
                         ShowGroupDropArea="True"
                         AllowGrouping="True"
                         AutoGenerateColumns="True"
                         ItemsSource="{Binding Orders}" >
this.dataGrid.AllowResizingColumns = true;

Image used to display the columnresizing with the touch in uwp datagrid

You can also resize the hidden column through the touch by setting the AllowResizingHiddenColumns by True. You have to press and hold the hidden line to resize the hidden column in touch.

<syncfusion:SfDataGrid  x:Name="dataGrid" 
                        AllowResizingHiddenColumns="True"
                        ShowGroupDropArea="True"
                        AllowGrouping="True" 
                        AutoGenerateColumns="True"
                        ItemsSource="{Binding Orders}" >
this.dataGrid.AllowResizingHiddenColumns = true;

Image used to display the resize the hidden column through the touch in uwp datagrid

NOTE

you can resize the column by dragging the bubbles on the Tool-Tip

Drag and Drop with the Touch Support

You can also drag and drop the columns through the touch by setting the AllowDraggingColumns as true. You have to press and drag the column header to move the column in touch.

<syncfusion:SfDataGrid x:Name="dataGrid" 
                       AllowDraggingColumns="True"
                       ShowGroupDropArea="True"
                       AllowGrouping="True" 
                       AutoGenerateColumns="True"
                       ItemsSource="{Binding Orders}" >
this.dataGrid.AllowDraggingColumns = true;

Image used to display the drag and drop with the touch support in uwp datagrid

Drag and Drop Rows

SfDataGrid allows you to row drag and drop by setting the SfDataGrid.AllowDraggingRows and AllowDrop property. Also, you can do row drag-and-drop operations between SfDataGrid and other controls like ListView, TreeView.

<Syncfusion:SfDataGrid x:Name="datagrid" 
                               AllowDraggingRows="True"
                               AllowDrop="True"
                               ItemsSource="{Binding Source}"/>
this.datagrid.AllowDraggingRows = true;
this.datagrid.AllowDrop = true;

Image used to display the drag and drop rows in uwp datagrid

Dragging multiple rows

The SfDataGrid allows to drag multiple selected rows. To enable multiple selection, set the SfDataGrid.SelectionMode as Multiple or Extended.

NOTE

The drag selection cannot be performed while the AllowDraggingRows enabled as true in the SfDataGrid.

Image used to display the dragging multiple rows in uwp datagrid

Customizing row drag and drop

Disable dragging of certain rows

To restrict dragging of certain rows, override the ProcessOnDragStarting method in the GridRowDragDropController class.

this.datagrid.RowDragDropController = new GridRowDragDropControllerExt();

public class GridRowDragDropControllerExt : GridRowDragDropController
{
    protected override void ProcessOnDragStarting(DragStartingEventArgs args, RowColumnIndex rowColumnIndex)
    {
        // Skip dragging of the rows less than 5.
        var rowIndex = rowColumnIndex.RowIndex;
        if (rowIndex < 0)
            return;
        var recordIndex = this.DataGrid.ResolveToRecordIndex(rowIndex);

        if (recordIndex < 5)
            return;
        base.ProcessOnDragStarting(args, rowColumnIndex);
    }
}

Disable drag over of certain rows

To restrict drop over specific node, override the GetDropPosition method in the GridRowDragDropController class.

this.datagrid.RowDragDropController = new GridRowDragDropControllerExt();

public class GridRowDragDropControllerExt : GridRowDragDropController
{
    protected override DropPosition GetDropPosition(DragEventArgs args, RowColumnIndex rowColumnIndex, ObservableCollection<object> draggingRecords)
{
    var recordIndex = this.DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);

    if (recordIndex < 6)
    {
        return DropPosition.None;
    }

    return base.GetDropPosition(args, rowColumnIndex, draggingRecords);
}     
}

Customizing drag UI Text

Drag UI text can be customized by overriding the ProcessOnDragOver method in the GridRowDragDropController Class.

this.datagrid.RowDragDropController = new GridRowDragDropControllerExt();

protected override void ProcessOnDragOver(DragEventArgs args, RowColumnIndex rowColumnIndex)
{
    base.ProcessOnDragOver(args, rowColumnIndex);
    var draggingRecords = args.DataView.Properties["Records"] as ObservableCollection<object>;
    var dropPosition = GetDropPosition(args, rowColumnIndex, draggingRecords);
    if (dropPosition == DropPosition.DropAbove)
        args.DragUIOverride.Caption = "Drop above the row";
}

Image used to display the customizing drag ui text in uwp datagrid

Customizing dragging records

While dragging, all selected records will be added to dragging records collection. To customize the dragging records collection, override the ProcessOnDragStarting method in the GridRowDragDropController class.

this.datagrid.RowDragDropController = new GridRowDragDropControllerExt();

public class GridRowDragDropControllerExt : GridRowDragDropController
    {
        public GridRowDragDropControllerExt()
        {

        }
        ObservableCollection<object> draggingRecords = new ObservableCollection<object>();

        protected override void ProcessOnDragStarting(DragStartingEventArgs args, RowColumnIndex rowColumnIndex)
        {
            var rowIndex = rowColumnIndex.RowIndex;
            if (rowIndex < 0)
                return;

            var recordIndex = this.DataGrid.ResolveToRecordIndex(rowIndex);

            // ResolveToRecordIndex returns -1 for AddNewRow, TableSummary, Filter, Unbound rows.
            if (recordIndex < 0)
                return;

            object record = null;
            
            var records = new ObservableCollection<object>();

            record = (this.DataGrid.View.Records[recordIndex]).Data;
            if (record == null)
                return;
            records.Add(record);

            args.Data.Properties.Add("Records", records);
            args.Data.Properties.Add("SourceDataGrid", DataGrid);
            args.Data.SetText(StandardDataFormats.Text);
            args.DragUI.SetContentFromDataPackage();        
   }
}

Row drag and drop between DataGrid and ListView

To perform dragging between the ListView and SfDataGrid, override the ProcessOnDragOver and ProcessOnDrop methods in the GridRowDragDropController class.

this.datagrid.RowDragDropController = new GridRowDragDropControllerExt();

public class GridRowDragDropControllerExt : GridRowDragDropController
{
    ObservableCollection<object> draggingRecords = new ObservableCollection<object>();

    protected override void ProcessOnDragOver(DragEventArgs args, RowColumnIndex rowColumnIndex)
    {
        if (args.DataView.Properties.ContainsKey("DraggedItem"))
            draggingRecords = args.DataView.Properties["DraggedItem"] as ObservableCollection<object>;

        else

            draggingRecords = args.DataView.Properties["Records"] as ObservableCollection<object>;

        if (draggingRecords == null)
            return;

        var dropPosition = GetDropPosition(args, rowColumnIndex, draggingRecords);

        if (dropPosition == DropPosition.None)
        {
            CloseDragIndicators();
            args.AcceptedOperation = DataPackageOperation.None;
            args.DragUIOverride.Caption = "Can't drop here";
            return;
        }

        else if (dropPosition == DropPosition.DropAbove)
        {
            if (draggingRecords != null && draggingRecords.Count > 1)
                args.DragUIOverride.Caption = "Drop these " + draggingRecords.Count + "  rows above";
            else
            {
                args.AcceptedOperation = DataPackageOperation.Copy;

                args.DragUIOverride.IsCaptionVisible = true;
                args.DragUIOverride.IsContentVisible = true;
                args.DragUIOverride.IsGlyphVisible = true;
                args.DragUIOverride.Caption = "Drop above";
            }
        }
          
        else
        {
            if (draggingRecords != null && draggingRecords.Count > 1)
                args.DragUIOverride.Caption = "Drop these " + draggingRecords.Count + "  rows below";
            else
                args.DragUIOverride.Caption = "Drop below";
        }
        args.AcceptedOperation = DataPackageOperation.Move;

        ShowDragIndicators(dropPosition, rowColumnIndex, args);
        args.Handled = true;
    }

    ListView listview;
    protected override void ProcessOnDrop(DragEventArgs args, RowColumnIndex rowColumnIndex)
    {
        listview = null;
            
        if (args.DataView.Properties.ContainsKey("ListView"))
            listview=args.DataView.Properties["ListView"] as ListView;

        if (!DataGrid.SelectionController.CurrentCellManager.CheckValidationAndEndEdit())
            return;

        var dropPosition = GetDropPosition(args, rowColumnIndex, draggingRecords);
        if (dropPosition == DropPosition.None)
            return;

        var droppingRecordIndex = this.DataGrid.ResolveToRecordIndex(rowColumnIndex.RowIndex);

        if (droppingRecordIndex < 0)
            return;

        foreach (var record in draggingRecords)
        {
            if (listview != null)
            {
                (listview.ItemsSource as ObservableCollection<BusinessObjects>).Remove(record as BusinessObjects);
                var sourceCollection = this.DataGrid.View.SourceCollection as IList;

                if (dropPosition == DropPosition.DropBelow)
                    sourceCollection.Insert(droppingRecordIndex + 1, record);
                else
                    sourceCollection.Insert(droppingRecordIndex, record);
            }
            else
            {
                var draggingIndex = this.DataGrid.ResolveToRowIndex(draggingRecords[0]);

                if (draggingIndex < 0)
                {
                    return;
                }

                var recordIndex = this.DataGrid.ResolveToRecordIndex(draggingIndex);
                var recordEntry = this.DataGrid.View.Records[recordIndex];
                this.DataGrid.View.Records.Remove(recordEntry);

                if (draggingIndex < rowColumnIndex.RowIndex && dropPosition == DropPosition.DropAbove)
                    this.DataGrid.View.Records.Insert(droppingRecordIndex - 1, this.DataGrid.View.Records.CreateRecord(record));
                else if (draggingIndex > rowColumnIndex.RowIndex && dropPosition == DropPosition.DropBelow)
                    this.DataGrid.View.Records.Insert(droppingRecordIndex + 1, this.DataGrid.View.Records.CreateRecord(record));
                else
                    this.DataGrid.View.Records.Insert(droppingRecordIndex, this.DataGrid.View.Records.CreateRecord(record));
            }
        }

        CloseDragIndicators();
    }
}

For ListView, you can wire the DragEnter, DragItemStarting, DragOver and Drop events.

private void ListView_DragEnter(object sender, DragEventArgs e)
{
    e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
}

private void ListView_Drop(object sender, DragEventArgs e)
{
    foreach (var item in records1)
    {
        this.datagrid.View.Remove(item as BusinessObjects);

        (this.DataContext as ViewModel).GDCSource1.Add(item as BusinessObjects);
    }
}

ObservableCollection<object> records1 = new ObservableCollection<object>();
private void ListView_DragOver(object sender, DragEventArgs e)
{
    if (e.DataView.Properties.ContainsKey("Records"))
        records1 = e.DataView.Properties["Records"] as ObservableCollection<object>;
}

private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
    var records = new ObservableCollection<object>();
    records.Add(listView.SelectedItem);
    e.Data.Properties.Add("DraggedItem", records);
    e.Data.Properties.Add("ListView", listView);
    e.Data.SetText(StandardDataFormats.Text);
}

Image used to display the row drag and drop between sfdatagrid and listview in uwp datagrid

NOTE

View Sample in GitHub

Row Drag and Drop between two SfDataGrids

You should enable AllowDraggingRows and AllowDrop property for the SfDataGrid’ s which are involved in row drag and drop operations.

NOTE

View Sample in GitHub

Context Menu

DataGrid provides an entirely customizable context menu to expose the functionality on user interface. You can create context menu for different rows in an efficient manner.

The below code example shows the context menu with command bindings.

<MenuFlyout>
    <MenuFlyoutItem Text="Copy" Command="{Binding Path=DataGrid.DataContext.GridCopyCommand}"
                    CommandParameter="{Binding}">
    </MenuFlyoutItem>
</MenuFlyout>
public class DelegateCommand : ICommand
{

    #region Fields
    Func<object, bool> canExecute;
    Action<object> executeAction;
    #endregion

    #region Constructors
    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>

    public DelegateCommand(Action<object> executeAction)
        : this(executeAction, null)
    {

    }     

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>

    public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
    {
        if (executeAction == null)            
            throw new ArgumentNullException("executeAction");
    
        this.executeAction = executeAction;        
        this.canExecute = canExecute;
    }        
    #endregion
    
    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        bool result = true;
        Func<object, bool> canExecuteHandler = this.canExecute;

        if (canExecuteHandler != null)
        {
            result = canExecuteHandler(parameter);
            return result;
        }
        return result;
    }
    
    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = this.CanExecuteChanged;
        if (handler != null)
        {
           handler(this, new EventArgs());
        }
    }

    public void Execute(object parameter)
    {		
        if (this.executeAction != null)
        {
            this.executeAction(parameter);
            return;
        }           
    }
    
    #endregion
}

public class ContextMenuViewModel : MenuFlyoutItem, INotifyPropertyChanged
{

    public ContextMenuViewModel()
    {
        copyCommand = new DelegateCommand(Copy);
    }
    
    private DelegateCommand copyCommand

    public DelegateCommand CopyCommand
    {
        get
        {
            return copyCommand;
        }
        set
        {
            copyCommand = value;
        }
    }
    
    public void Copy(object param)
    {
        if (param is GridRecordContextMenuInfo)
        {
            var grid = (param as GridRecordContextMenuInfo).DataGrid;
            grid.GridCopyPaste.Copy();
        }
    }
}

Context menu for record rows

You can set the context menu for the data rows by using SfDataGrid.RecordContextMenu property.

<syncfusion:SfDataGrid.RecordContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name="Cut" Text="Cut" />
        <MenuFlyoutItem x:Name="Copy" Text="Copy"  />
        <MenuFlyoutItem x:Name="Paste" Text="Paste" />
        <MenuFlyoutItem x:Name="Delete" Text="Delete" />
    </MenuFlyout>
</syncfusion:SfDataGrid.RecordContextMenu>
this.dataGrid.RecordContextMenu = new MenuFlyout();
this.dataGrid.RecordContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Cut" });
this.dataGrid.RecordContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Copy" });
this.dataGrid.RecordContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Paste" });
this.dataGrid.RecordContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Delete" });

Context menu added for data rows in uwp datagrid

While binding the menu item using CommandBinding you can get the command parameter as GridRecordContextMenuInfo which contains the record of the corresponding row.

<syncfusion:SfDataGrid.RecordContextMenu>
	<MenuFlyout>
		<MenuFlyoutItem Text="Copy"
                        Command="{Binding Path=DataGrid.DataContext.GridCopyCommand}"
                        CommandParameter="{Binding}">
		</MenuFlyoutItem>
	<MenuFlyout>
</syncfusion:SfDataGrid.RecordContextMenu>
private void Copy(object param)
{
    if (param is GridRecordContextMenuInfo)
    {
        var grid = (param as GridRecordContextMenuInfo).DataGrid;
		var record = (param as GridRecordContextMenuInfo).Record;
        grid.GridCopyPaste.Copy();
    }
}

Context menu for column header

You can set the context menu for the header by using SfDataGrid.HeaderContextMenu property.

<syncfusion:SfDataGrid.HeaderContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name=" SortAscending " Text="SortAscending" />
        <MenuFlyoutItem x:Name=" SortDescending " Text="SortDescending" />
        <MenuFlyoutItem x:Name=" ClearSorting " Text="ClearSorting" />
        <MenuFlyoutItem x:Name=" ClearFiltering " Text="ClearFiltering" />
        <MenuFlyoutItem x:Name=" Group by this column " Text="Group by this column" />
        <MenuFlyoutItem x:Name=" Expand/Collapse Group Drop Area " Text="Expand/Collapse Group Drop Area" />
        <MenuFlyoutItem x:Name=" BestFit " Text="BestFit" />
    </MenuFlyout>
</syncfusion:SfDataGrid.HeaderContextMenu>
this.dataGrid.HeaderContextMenu = new MenuFlyout();
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "SortAscending" });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "SortDescending" });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ClearSorting" });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = " ClearFiltering " });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Group by this column" });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Expand/Collapse Group Drop Area" });
this.dataGrid.HeaderContextMenu.Items.Add(new MenuFlyoutItem() { Text = "BestFit" });

Context menu added for header row in uwp datagrid

While binding the menu item using CommandBinding you can get the parameter as GridColumnContextMenuInfo which contains the particular GridColumn.

<syncfusion:SfDataGrid.HeaderContextMenu>
	<MenuFlyout>
        <MenuFlyoutItem Text="SortAscending"
                        Command="{Binding Path=DataGrid.DataContext.SortAscendingCommand}"                                    
                        CommandParameter="{Binding}" >
		</MenuFlyoutItem>
	<MenuFlyout>
</syncfusion:SfDataGrid.HeaderContextMenu>
private void SortAscending(object param)                
{
    if (param is GridColumnContextMenuInfo)
    {
        var grid = (param as GridContextMenuInfo).DataGrid;
        var column = (param as GridColumnContextMenuInfo).Column;
        grid.SortColumnDescriptions.Clear();
        grid.SortColumnDescriptions.Add(new SortColumnDescription() { ColumnName = column.MappingName, SortDirection = ListSortDirection.Ascending });
    }
}

Context menu for group drop area

You can set the context menu for the GroupDropArea by using SfDataGrid.GroupDropAreaContextMenu property.

<syncfusion:SfDataGrid.GroupDropAreaContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name=" ExpandAll " Text="ExpandAll" />
        <MenuFlyoutItem x:Name=" CollapseAll " Text="CollapseAll" />
        <MenuFlyoutItem x:Name=" ClearGroups " Text="ClearGroups" />
    </MenuFlyout>
</syncfusion:SfDataGrid.GroupDropAreaContextMenu>
this.dataGrid.GroupDropAreaContextMenu = new MenuFlyout();
this.dataGrid.GroupDropAreaContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ExpandAll" });
this.dataGrid.GroupDropAreaContextMenu.Items.Add(new MenuFlyoutItem() { Text = "CollapseAll" });
this.dataGrid.GroupDropAreaContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ClearGroups" });

Context menu added for GroupDropArea in uwp datagrid

While binding the menu item using CommandBinding you can get the parameter as GridGroupDropAreaContextMenuInfo.

<syncfusion:SfDataGrid.GroupDropAreaContextMenu>
	<MenuFlyout>
        <MenuFlyoutItem Text="Expand all"
                        Command="{Binding Path=DataGrid.DataContext.ExpandAllCommand}"        
                        CommandParameter="{Binding}" >
		</MenuFlyoutItem>
	</MenuFlyout>
</syncfusion:SfDataGrid.GroupDropAreaContextMenu>
private void ExpandAll(object param)
{
    if (param is Syncfusion.UI.Xaml.Grid.GridContextMenuInfo)
    {
        var grid = (param as Syncfusion.UI.Xaml.Grid.GridContextMenuInfo).DataGrid;
        grid.ExpandAllGroup();
    }
}

Context menu for group item

You can set the context menu for the group drop item by using SfDataGrid.GroupDropItemContextMenu property.

<syncfusion:SfDataGrid.GroupDropItemContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name=" ExpandAll " Text="ExpandAll" />
        <MenuFlyoutItem x:Name=" CollapseAll " Text="CollapseAll" />
        <MenuFlyoutItem x:Name=" SortAscending " Text="SortAscending" />
        <MenuFlyoutItem x:Name=" SortDescending " Text="SortDescending" />
        <MenuFlyoutItem x:Name=" ClearGroup " Text="ClearGroup" />
        <MenuFlyoutItem x:Name=" ClearSorting " Text="ClearSorting" />
    </MenuFlyout>
</syncfusion:SfDataGrid.GroupDropItemContextMenu>
this.dataGrid.GroupDropItemContextMenu = new MenuFlyout();
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ExpandAll" });
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "CollapseAll" });
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "SortAscending" });
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "SortDescending" });
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ClearGroup" });
this.dataGrid.GroupDropItemContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ClearSorting" });

Context menu added for GroupDropItem in uwp datagrid

While binding the menu item using CommandBinding you can get the parameter as GridColumnContextMenuInfo which contains the particular GridColumn.

<syncfusion:SfDataGrid.GroupDropItemContextMenu>
	<MenuFlyout>
		<MenuFlyoutItem Text="Collapse all"
                    Command="{Binding Path=DataGrid.DataContext.CollapseAllCommand}"
                    CommandParameter="{Binding}" >					
		</MenuFlyoutItem>
	</MenuFlyout>
</syncfusion:SfDataGrid.GroupDropItemContextMenu>
private void CollapseAll(object param)
{
    if (param is GridContextMenuInfo)
    {
        var grid = (param as GridContextMenuInfo).DataGrid;
        grid.CollapseAllGroup();
    }
}

Context menu for caption summary wow

You can set the context menu for the group caption by using SfDataGrid.GroupCaptionContextMenu property.

<syncfusion:SfDataGrid.GroupCaptionContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name=" Expand " Text="Expand" />
        <MenuFlyoutItem x:Name=" Collapse " Text="Collapse" />
    </MenuFlyout>
</syncfusion:SfDataGrid.GroupCaptionContextMenu>
this.dataGrid.GroupCaptionContextMenu = new MenuFlyout();
this.dataGrid.GroupCaptionContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Expand" });
this.dataGrid.GroupCaptionContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Collapse" });

Context menu added for group caption rows in uwp datagrid

While binding the menu item using CommandBinding you can get the command parameter as GridRecordContextMenuInfo which contains the record of the corresponding row.

<syncfusion:SfDataGrid.GroupCaptionContextMenu>
	<MenuFlyout>
        <MenuFlyoutItem Text="Expand" 
						Command="{Binding Path=DataGrid.DataContext.ExpandCommand}"
						CommandParameter="{Binding}"/>				
		</MenuFlyoutItem>
	<MenuFlyout>
</syncfusion:SfDataGrid.GroupCaptionContextMenu>
private void Expand(object param)
{
    if (param is GridRecordContextMenuInfo)
    {
        var grid = (param as GridRecordContextMenuInfo).DataGrid;
        var group = (param as GridRecordContextMenuInfo).Record as Group;
        grid.ExpandGroup(group);
    }
}

Context menu for group summary row

You can set the context menu for the group summary by using SfDataGrid.GroupSummaryContextMenu property.

<syncfusion:SfDataGrid.GroupSummaryContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name="ClearSummary" Text="ClearSummary" />
    </MenuFlyout>
</syncfusion:SfDataGrid.GroupSummaryContextMenu>
this.dataGrid.GroupSummaryContextMenu = new MenuFlyout();
this.dataGrid.GroupSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "ClearSummary" });

Context menu added for group summary rows in uwp datagrid

While binding the menu item using CommandBinding you can get the command parameter as GridRecordContextMenuInfo which contains the record of the corresponding row.

<syncfusion:SfDataGrid.GroupSummaryContextMenu>
	<MenuFlyout>
        <MenuFlyoutItem Text="Clear Summary"
                        Command="{Binding Path=DataGrid.DataContext.ClearSummaryCommand}"
                        CommandParameter="{Binding}">
		</MenuFlyoutItem>
	</MenuFlyout>
</syncfusion:SfDataGrid.GroupSummaryContextMenu>
private void ClearSummary(object param)
{
    if (param is GridRecordContextMenuInfo)
    {
        var grid = (param as GridRecordContextMenuInfo).DataGrid;

        if (grid.GroupSummaryRows.Any())
            grid.GroupSummaryRows.Clear();
    }
}

Context menu for table summary row

You can set the context menu for the table summary by using SfDataGrid.TableSummaryContextMenu property.

<syncfusion:SfDataGrid.TableSummaryContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem x:Name="TableSummaryCount" Text="Count" />
        <MenuFlyoutItem x:Name="TableSummaryMax" Text="Max" />
        <MenuFlyoutItem x:Name="TableSummaryMin" Text="Min" />
        <MenuFlyoutItem x:Name="TableSummaryMin" Text="Average" />
        <MenuFlyoutItem x:Name="TableSummaryMin" Text="Sum" />
    </MenuFlyout>
</syncfusion:SfDataGrid.TableSummaryContextMenu>
this.dataGrid.TableSummaryContextMenu = new MenuFlyout();
this.dataGrid.TableSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Count" });
this.dataGrid.TableSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Max" });
this.dataGrid.TableSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Min" });
this.dataGrid.TableSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Average" });
this.dataGrid.TableSummaryContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Sum" });

Context menu added for table summary rows in uwp datagrid

While binding the menu item using CommandBinding you can get the command parameter as GridRecordContextMenuInfo which contains the record of the corresponding row.

<syncfusion:SfDataGrid.TableSummaryContextMenu>
	<MenuFlyout>
        <MenuFlyoutItem Command="{Binding Path=DataGrid.DataContext.TotalSummaryCountCommand}" 
						CommandParameter="{Binding}" 
						Text="Count" >
		</MenuFlyoutItem>
	</MenuFlyout>
</syncfusion:SfDataGrid.TableSummaryContextMenu>
private void TotalSummaryCount(object param)
{
    if (param is GridRecordContextMenuInfo)
    {
        var grid = (param as GridRecordContextMenuInfo).DataGrid;
        var record = (param as GridRecordContextMenuInfo).Record as SummaryRecordEntry;
        if (record != null)
        {
            var summaryrow = new GridSummaryRow() { Name = "totalgroupsummaryrow", Title = "{totalSummary}", ShowSummaryInRow = true };
            summaryrow.SummaryColumns.Add(new GridSummaryColumn() { Name = "totalSummary", MappingName = "OrderID", SummaryType = SummaryType.CountAggregate, Format = "Total Employee Count : {Count}" });
            grid.TableSummaryRows.Clear();
            grid.TableSummaryRows.Add(summaryrow);
        }
    }
}

Events

GridContextMenuOpening

GridContextMenuOpening event occurs while opening the context menu in SfDataGrid.

GridContextMenuEventArgs has the following members which provides the information about GridContextMenuOpening event.

  • ContextMenu – Gets the corresponding context menu.

  • ContextMenuInfo – Returns the context menu info based on the row which opens the context menu.

  • ContextMenuType – Returns the type of context menu.

  • RowColumnIndexRowColumnIndex of the context menu which is currently going to open. RowColumnIndex is updated only for the RecordContextMenu and remains left empty.

  • Handled – Indicates whether the GridContextMenuOpening event is handled or not.

Customization of context menu

Change the menu item when the context menu opening.

You can use the GridContextMenuOpening event to change the menu item when the context menu opening.

<syncfusion:SfDataGrid.RecordContextMenu>
    <MenuFlyout>
        <MenuFlyoutItem Text="Cut"
                                Command="{Binding Path=DataGrid.DataContext.GridCutCommand}"
                                CommandParameter="{Binding}"/>
        <MenuFlyoutItem Text="Copy"
                                Command="{Binding Path=DataGrid.DataContext.GridCopyCommand}"
                                CommandParameter="{Binding}"/>
        <MenuFlyoutItem Text="Paste"
                                Command="{Binding Path=DataGrid.DataContext.GridPasteCommand}"
                                CommandParameter="{Binding}"/>
    </MenuFlyout>
</syncfusion:SfDataGrid.RecordContextMenu>
this.dataGrid.GridContextMenuOpening += DataGrid_GridContextMenuOpening;

private void DataGrid_GridContextMenuOpening(object sender, GridContextMenuEventArgs e)
{
    e.ContextMenu.Items.Clear();

    if (e.ContextMenuType == ContextMenuType.RecordCell)
    {
        e.ContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Record" });
        e.ContextMenu.Items.Add(new MenuFlyoutItem() { Text = "Data" });
    }
}

Context menu changed for record cell while opening in uwp datagrid

Customizing appearance of context menu

You can change the appearance of the context menu by customizing the style with TargetType as MenuFlyoutPresenter.

<Style x:Key="MenuFlyoutPresenterStyle" TargetType="MenuFlyoutPresenter">
    <Setter Property="Background" Value="AliceBlue"/>
    <Setter Property="BorderBrush" Value="Red"/>
    <Setter Property="BorderThickness" Value="2,2,2,2"/>
</Style>

<MenuFlyout MenuFlyoutPresenterStyle="{StaticResource MenuFlyoutPresenterStyle}">
    <MenuFlyoutItem x:Name="Cut" Text="Cut" />
    <MenuFlyoutItem x:Name="Copy" Text="Copy"  />
    <MenuFlyoutItem x:Name="Paste" Text="Paste" />
    <MenuFlyoutItem x:Name="Delete" Text="Delete" />
</MenuFlyout>

Context menu background changed in uwp datagrid