.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.
The following properties are relted to the reordering feature:
CanUserReorderColumns
(bool
)—Defines whether the user can reorder theDataGridColumns
. The default value istrue
.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. TheColumnReorderStarting
event handler receives the following parameters:- A
sender
argument, which is of typeobject
, but can be cast to theRadDataGrid
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. TheIndex
is the index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofColumn.IsFrozen
.Cancel
(bool
)—Defines a value indicating whether the reordering operation is canceled.
- A
-
ColumnReordering
—Raised continuously while the column is being dragged. TheColumnReordering
event handler receives the following parameters:- A
sender
argument, which is of typeobject
, but can be cast to theRadDataGrid
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. TheOldIndex
is the old index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofColumn.IsFrozen
.NewIndex
(int
) —Gets the new potential index of the column that is being reordered. TheNewIndex
is the new index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofNewIsFrozen
.NewIsFrozen
(bool
)—Gets the new potentialTelerik.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 istrue
.
- A
-
ColumnReorderCompleting
—Raised when the user drops the column. This doesn't mean the column is reordered. TheColumnReorderCompleting
event handler receives the following parameters:- A
sender
argument, which is of typeobject
, but can be cast to theRadDataGrid
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. TheOldIndex
is the old index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofColumn.IsFrozen
.NewIndex
(int
) —Gets the new potential index of the column that is being reordered. TheNewIndex
is the new index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofNewIsFrozen
.NewIsFrozen
(bool
)—Gets the new potentialTelerik.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 itsIsFrozen
property and the drop at this location was not forbidden by setting theTelerik.Maui.Controls.DataGrid.ColumnReorderingEventArgs.CanDrop
property of theTelerik.Maui.Controls.DataGrid.ColumnReorderingEventArgs
tofalse
. The default value istrue
.Cancel
(bool
)—Defines a value indicating whether the reordering operation is canceled.
- A
-
ColumnReordered
—Raised when a column has been successfully reordered. TheColumnReordered
event handler receives the following parameters:- A
sender
argument which is of typeobject
, but can be cast to theRadDataGrid
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. TheOldIndex
is the old index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofOldIsFrozen
.OldIsFrozen
(bool
)—Gets the initialTelerik.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. TheNewIndex
is the new index of the item inside theFrozenColumns
orUnfrozenColumns
collection, depending on the value ofColumn.IsFrozen
.
- A
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.Windows[0].Page.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.Windows[0].Page.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.Windows[0].Page.DisplayAlert("", $"{(e.Column as DataGridTypedColumn).HeaderText} column was reordered!", "OK");
}
The result on mobile:
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="✕" />
<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:
For the runnable DataGrid Drag Templates example, see the SDKBrowser Demo Application and go to DataGrid > Columns.