New to Telerik UI for .NET MAUI? Start a free 30-day trial

.NET MAUI DataGrid Columns Reordering

The .NET MAUI DataGrid exposes a reordering feature allowing the user to drag and drop columns and change their order.

DataGrid Reordering Desktop

The following properties are relted to the reordering feature:

  • CanUserReorderColumns(bool)—Defines whether the user can reorder the DataGridColumns. The default value is true.
  • ColumnReorderIndicatorTemplate(DataTemplate)—Defines the template that presents the indicator that is displayed between two columns during reordering.
  • ColumnHeaderDragVisualTemplate (DataTemplate)—Specifies the template that presents the drag visual of the dragged column header.

Events

The DataGrid exposes the following events related to the reordering operation:

  • ColumnReorderStarting—Raised when the user starts to drag a column to reorder it. The ColumnReorderStarting event handler receives the following parameters:

    • A sender argument, which is of type object, but can be cast to the RadDataGrid type.
    • A ColumnReorderStartingEventArgs object, which has a reference to the following properties:
      • Column (DataGridColumn)—Gets the column that will be reordered.
      • Index (int) —Gets the index of the column that will be reordered. The Index is the index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of Column.IsFrozen.
      • Cancel (bool)—Defines a value indicating whether the reordering operation is canceled.
  • ColumnReordering—Raised continuously while the column is being dragged. The ColumnReordering event handler receives the following parameters:

    • A sender argument, which is of type object, but can be cast to the RadDataGrid type.
    • A ColumnReorderingEventArgs object, which has a reference to the following properties:
      • Column (DataGridColumn)—Gets the column that will be reordered.
      • OldIndex (int) —Gets the initial index of the column that is being reordered. The OldIndex is the old index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of Column.IsFrozen.
      • NewIndex (int) —Gets the new potential index of the column that is being reordered. The NewIndex is the new index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of NewIsFrozen.
      • NewIsFrozen (bool)—Gets the new potential Telerik.Maui.Controls.DataGrid.DataGridColumn.IsFrozen value of the column that is being reordered.
      • CanDrop (bool)—Defines a value indicating whether dropping the column at this specific location is allowed. The default value is true.
  • ColumnReorderCompleting—Raised when the user drops the column. This doesn't mean the column is reordered. The ColumnReorderCompleting event handler receives the following parameters:

    • A sender argument, which is of type object, but can be cast to the RadDataGrid type.
    • A ColumnReorderCompletingEventArgs object, which has a reference to the following properties:
      • Column (DataGridColumn)—Gets the column that is being reordered.
      • OldIndex (int) —Gets the initial index of the column that is being reordered. The OldIndex is the old index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of Column.IsFrozen.
      • NewIndex (int) —Gets the new potential index of the column that is being reordered. The NewIndex is the new index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of NewIsFrozen.
      • NewIsFrozen (bool)—Gets the new potential Telerik.Maui.Controls.DataGrid.DataGridColumn.IsFrozen value of the column that is being reordered.
      • IsDropAllowed (bool)—Gets a value that indicates whether the column was dropped at a valid location. A valid location means that the column has changed its index and/or the value of its IsFrozen property and the drop at this location was not forbidden by setting the Telerik.Maui.Controls.DataGrid.ColumnReorderingEventArgs.CanDrop property of the Telerik.Maui.Controls.DataGrid.ColumnReorderingEventArgs to false. The default value is true.
      • Cancel (bool)—Defines a value indicating whether the reordering operation is canceled.
  • ColumnReordered—Raised when a column has been successfully reordered. The ColumnReordered event handler receives the following parameters:

    • A sender argument which is of type object, but can be cast to the RadDataGrid type.
    • A ColumnReorderCompletingEventArgs object, which has a reference to the following properties:
      • Column (DataGridColumn)—Gets the column that has been reordered.
      • OldIndex (int) —Gets the initial index of the column that has been reordered. The OldIndex is the old index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of OldIsFrozen.
      • OldIsFrozen (bool)—Gets the initial Telerik.Maui.Controls.DataGrid.DataGridColumn.IsFrozen value of the column that has been reordered.
      • NewIndex (int) —Gets the new index of the column that has been reordered. The NewIndex is the new index of the item inside the FrozenColumns or UnfrozenColumns collection, depending on the value of Column.IsFrozen.

Example with Reorder Columns and Events

The following example shows how to bind the CanUserReorderColumns using MVVM and a sample scenario with the reordering events.

1. Create a sample model:

public class PersonDetails
{
    public string Name { get; set; }
    public int Age { get; set; }
    public double Weight { get; set; }
    public Gender Gender { get; set; }
}

2. Create a ViewModel:

public class ViewModel : NotifyPropertyChangedBase
{
    private bool isReorderingEnabled = true;

    public ViewModel()
    {
        this.Data = new ObservableCollection<PersonDetails>
        {
            new PersonDetails { Name = "Juan", Age = 21, Gender = Gender.Male, Weight = 94.2 },
            new PersonDetails { Name = "Larry", Age = 22, Gender = Gender.Male, Weight = 68.9 },
            new PersonDetails { Name = "Tiffany", Age = 34, Gender = Gender.Female, Weight = 83 },
            new PersonDetails { Name = "Sebastian", Age = 16, Gender = Gender.Other, Weight = 72 },
            new PersonDetails { Name = "Bojidara", Age = 42, Gender = Gender.Female, Weight = 52 },
        };
    }

    public ObservableCollection<PersonDetails> Data { get; set; }

    public bool IsReorderingEnabled
    {
        get => this.isReorderingEnabled;
        set => this.UpdateValue(ref this.isReorderingEnabled, value);
    }
}

3. Define the DataGrid and a control which will change the CanUserReorderColumns value in XAML:

<Grid RowDefinitions="Auto, *">
    <Grid ColumnDefinitions="Auto, Auto" Margin="0, 0, 0, 10">
        <Label Text="Enable Column Reordering: " VerticalOptions="Center"/>
        <Switch Grid.Column="1"
                IsToggled="{Binding IsReorderingEnabled, Mode=TwoWay}"
                VerticalOptions="Center"
                HorizontalOptions="End"/>
    </Grid>
    <telerik:RadDataGrid x:Name="dataGrid"
                         Grid.Row="1"
                         AutoGenerateColumns="False"
                         ItemsSource="{Binding Data}"
                         CanUserReorderColumns="{Binding IsReorderingEnabled}"
                         ColumnReorderStarting="OnColumnReorderStarting"
                         ColumnReordering="OnColumnReordering"
                         ColumnReorderCompleting="OnColumnReorderCompleting"
                         ColumnReordered="OnColumnReordered">
        <telerik:RadDataGrid.Columns>
            <telerik:DataGridTextColumn PropertyName="Name" IsFrozen="True" />
            <telerik:DataGridNumericalColumn PropertyName="Age" />
            <telerik:DataGridComboBoxColumn PropertyName="Gender" />
            <telerik:DataGridNumericalColumn PropertyName="Weight" />
        </telerik:RadDataGrid.Columns>
    </telerik:RadDataGrid>
</Grid>

4. Add the telerik namespace:

xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"

5. Sample implementation in the reordering event:

private void OnColumnReorderStarting(object sender, Telerik.Maui.Controls.DataGrid.ColumnReorderStartingEventArgs e)
{
    if (e.Column.IsFrozen)
    {
        e.Cancel = true;
        Application.Current.MainPage.DisplayAlert("", "Reorder is canceled because the column is Frozen", "OK");
    }
}

private void OnColumnReordering(object sender, Telerik.Maui.Controls.DataGrid.ColumnReorderingEventArgs e)
{
    // add your logic here
}

private void OnColumnReorderCompleting(object sender, Telerik.Maui.Controls.DataGrid.ColumnReorderCompletingEventArgs e)
{
    if (!e.Column.IsFrozen && e.NewIsFrozen)
    {
        e.Cancel = true;
        Application.Current.MainPage.DisplayAlert("", $"Cannot add the {(e.Column as DataGridTypedColumn).HeaderText} column to the frozen area", "OK");
    }
}

private void OnColumnReordered(object sender, Telerik.Maui.Controls.DataGrid.ColumnReorderedEventArgs e)
{
    Application.Current.MainPage.DisplayAlert("", $"{(e.Column as DataGridTypedColumn).HeaderText} column was reordered!", "OK");
}

The result on mobile:

DataGrid Reordering Phone

Example with Indicator Template when Reordering Columns

The following example shows how to define the ColumnReorderIndicatorTemplate in XAML:

1. Define the DataTemplate for the Indicator in the Resources of the page:

<DataTemplate x:Key="ReorderIndicatorTemplate">
    <telerik:RadBorder BackgroundColor="#80CBC4"
                       WidthRequest="4"
                       HorizontalOptions="Start"
                       InputTransparent="True" />
</DataTemplate>

2. Define the DataTemplate for the header drag template in the Resources of the page:

<DataTemplate x:Key="HeaderDragTemplate">
    <telerik:RadBorder BackgroundColor="#80CBC4"
                       CornerRadius="2"
                       MinimumWidthRequest="{Binding ActualWidth}">
        <Label Text="{Binding HeaderText, FallbackValue='dragging...'}"
               TextColor="#000000"
               Margin="10, 8" />
    </telerik:RadBorder>
</DataTemplate>

3. Define the DataTemplate for the group item template in the Resources of the page:

<Style x:Key="ButtonStyle_XClose" TargetType="telerik:RadButton">
    <Setter Property="Text" Value="&#x2715;" />
    <Setter Property="FontFamily" Value="Arial" />
    <Setter Property="FontSize" Value="{OnPlatform MacCatalyst=18, WinUI=14, iOS=12, Android=10}" />
    <Setter Property="FontAttributes" Value="Bold" />
    <Setter Property="WidthRequest" Value="{OnPlatform Default=36, Android=26, iOS=26}" />
    <Setter Property="HeightRequest" Value="{OnPlatform Default=16, Android=30, iOS=30}" />
    <Setter Property="BorderWidth" Value="0" />
    <Setter Property="BackgroundColor" Value="Transparent" />
    <Setter Property="TextColor" Value="#000000" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Margin" Value="2, 0" />
</Style>

<DataTemplate x:Key="GroupingPanelItemTemplate">
    <telerik:RadBorder BorderColor="#80CBC4"
                       BorderThickness="{OnPlatform Default=0, iOS=1, Android=1}"
                       Margin="{OnPlatform Default='0, 2', Android='0, 4, 4, 4'}"
                       CornerRadius="2">
        <Grid>
            <telerik:RadBorder BackgroundColor="#80CBC4"
                               Opacity="{OnIdiom Desktop=1, Phone=0.7}" />
            <HorizontalStackLayout>
                <Label Text="{Binding DisplayContent}"
                       TextColor="#000000"
                       FontSize="{OnPlatform Android=14, iOS=17, MacCatalyst=Default, WinUI=14}"
                       VerticalOptions="Center"
                       Margin="10, 0, 2, 0" />
                <telerik:RadButton Command="{Binding RemoveCommand, Source={RelativeSource AncestorType={Type telerik:DataGridGroupingPanel}}}"
                                   CommandParameter="{Binding}"
                                   Style="{StaticResource ButtonStyle_XClose}" />
            </HorizontalStackLayout>
        </Grid>
    </telerik:RadBorder>
</DataTemplate>

4. Define the properties in the DataGrid:

<telerik:RadDataGrid x:Name="dataGrid"
                     UserGroupMode="Enabled"
                     ItemsSource="{Binding Data}"
                     CanUserReorderColumns="True"
                     ColumnHeaderDragVisualTemplate="{StaticResource HeaderDragTemplate}"
                     GroupingPanelItemTemplate="{StaticResource GroupingPanelItemTemplate}"
                     ColumnReorderIndicatorTemplate="{StaticResource ReorderIndicatorTemplate}">
    <telerik:RadDataGrid.BindingContext>
        <local:ViewModel />
    </telerik:RadDataGrid.BindingContext>
</telerik:RadDataGrid>

5. Add the telerik namespace:

xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"

6. Define sample data:

public class PersonDetails
{
    public string Name { get; set; }
    public int Age { get; set; }
    public double Weight { get; set; }
    public Gender Gender { get; set; }
}

7. Define a sample ViewModel:

public class ViewModel : NotifyPropertyChangedBase
{
    private bool isReorderingEnabled = true;

    public ViewModel()
    {
        this.Data = new ObservableCollection<PersonDetails>
        {
            new PersonDetails { Name = "Juan", Age = 21, Gender = Gender.Male, Weight = 94.2 },
            new PersonDetails { Name = "Larry", Age = 22, Gender = Gender.Male, Weight = 68.9 },
            new PersonDetails { Name = "Tiffany", Age = 34, Gender = Gender.Female, Weight = 83 },
            new PersonDetails { Name = "Sebastian", Age = 16, Gender = Gender.Other, Weight = 72 },
            new PersonDetails { Name = "Bojidara", Age = 42, Gender = Gender.Female, Weight = 52 },
        };
    }

    public ObservableCollection<PersonDetails> Data { get; set; }

    public bool IsReorderingEnabled
    {
        get => this.isReorderingEnabled;
        set => this.UpdateValue(ref this.isReorderingEnabled, value);
    }
}

The result on mobile:

DataGrid Reordering Indicator Phone

For the runnable DataGrid Drag Templates example, see the SDKBrowser Demo Application and go to DataGrid > Columns.

See Also

In this article