Pull To Refresh in MAUI DataGrid (SfDataGrid)
7 Jul 202613 minutes to read
Pull To Refresh
To enable the pull-to-refresh option in the data grid, set the SfDataGrid.AllowPullToRefresh property to true. This allows the control to refresh the data source at runtime when the pull-to-refresh gesture is performed.
The data grid refreshes its data by executing an ICommand bound to the SfDataGrid.PullToRefreshCommand property. When the pull-to-refresh gesture is performed and the progress bar reaches 100%, this command is triggered to update the records in view.
To indicate that a refresh operation is in progress, set the SfDataGrid.IsBusy property to true before starting the refresh. Once the refresh is complete, set this property back to false.
The following code example demonstrates how to enable and implement pull-to-refresh:
<syncfusion:SfDataGrid x:Name="DataGrid"
ItemsSource="{Binding Orders}"
AllowPullToRefresh="True"
PullToRefreshCommand="{Binding RefreshCommand}">
</syncfusion:SfDataGrid>public partial class MainPage : ContentPage
{
SfDataGrid dataGrid;
OrderInfoViewModel viewModel;
public MainPage()
{
InitializeComponent();
dataGrid = new SfDataGrid();
viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AllowPullToRefresh = true;
dataGrid.PullToRefreshCommand = new Command(ExecutePullToRefreshCommand);
this.Content = dataGrid;
}
private async void ExecutePullToRefreshCommand()
{
dataGrid.IsBusy = true;
await Task.Delay(new TimeSpan(0, 0, 5));
viewModel.ItemsSourceRefresh();
dataGrid.IsBusy = false;
}
}
Transition Type
To customize the progress view animation, adjust the SfDataGrid.TransitionType property. By default, the transition type is set to SlideOnTop.
Available Transition Types:
- SlideOnTop (default): Draws the refresh indicator on top of the data grid
- Push: Moves only the scrollable content while the header remains fixed
The following code snippet demonstrates how to change the transition type to Push:
<syncfusion:SfDataGrid x:Name="DataGrid"
ItemsSource="{Binding Orders}"
AllowPullToRefresh="True"
TransitionType="Push"
PullToRefreshCommand="{Binding RefreshCommand}">
</syncfusion:SfDataGrid>public partial class MainPage : ContentPage
{
SfDataGrid dataGrid;
OrderInfoViewModel viewModel;
public MainPage()
{
InitializeComponent();
dataGrid = new SfDataGrid();
viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AllowPullToRefresh = true;
dataGrid.TransitionType = Syncfusion.Maui.PullToRefresh.PullToRefreshTransitionType.Push;
dataGrid.PullToRefreshCommand = new Command(ExecutePullToRefreshCommand);
this.Content = dataGrid;
}
private async void ExecutePullToRefreshCommand()
{
dataGrid.IsBusy = true;
await Task.Delay(new TimeSpan(0, 0, 5));
viewModel.ItemsSourceRefresh();
dataGrid.IsBusy = false;
}
}
Customization
For advanced customization of the progress indicator, access the internal SfPullToRefresh control via the DataGrid.DataGridLoaded event. You can customize properties such as ProgressColor, ProgressBackground, ProgressThickness, PullingThreshold, and RefreshViewThreshold.
using Syncfusion.Maui.DataGrid;
using Syncfusion.Maui.PullToRefresh;
public partial class MainPage : ContentPage
{
SfDataGrid dataGrid;
OrderInfoViewModel viewModel;
public MainPage()
{
InitializeComponent();
dataGrid = new SfDataGrid();
viewModel = new OrderInfoViewModel();
dataGrid.ItemsSource = viewModel.Orders;
dataGrid.AllowPullToRefresh = true;
dataGrid.TransitionType = Syncfusion.Maui.PullToRefresh.PullToRefreshTransitionType.Push;
dataGrid.PullToRefreshCommand = new Command(ExecutePullToRefreshCommand);
dataGrid.DataGridLoaded += DataGrid_DataGridLoaded;
this.Content = dataGrid;
}
private async void ExecutePullToRefreshCommand()
{
dataGrid.IsBusy = true;
await Task.Delay(new TimeSpan(0, 0, 5));
viewModel.ItemsSourceRefresh();
dataGrid.IsBusy = false;
}
private void DataGrid_DataGridLoaded(object? sender, EventArgs e)
{
SfPullToRefresh refreshView = dataGrid.Children.OfType<SfPullToRefresh>().First();
if (refreshView != null)
{
refreshView.ProgressColor = Color.FromArgb("#e76f51");
refreshView.ProgressBackground = Color.FromArgb("#219ebc");
refreshView.ProgressThickness = 4;
refreshView.RefreshViewThreshold = 10;
refreshView.PullingThreshold = 120;
}
}
}
For more customization options of SfPullToRefresh, refer to the PullToRefresh customization documentation.
Host .NET MAUI DataGrid as pullable content
The SfPullToRefresh control supports wrapping any custom control (including DataGrid) as pullable content. This approach provides more flexibility for refresh behavior and visual customization compared to the built-in approach.
- Add Assembly References: Ensure both DataGrid and PullToRefresh assemblies are referenced in your project.
- Import Namespaces: Add the required namespaces to your XAML page as follows.
- Define the DataGrid as PullableContent: Wrap the DataGrid inside SfPullToRefresh.PullableContent.
- Handle Refresh Events: Subscribe to the Refreshing event to update data when pull-to-refresh is triggered.
- Customize Properties: Configure DataGrid and PullToRefresh properties as needed.
xmlns:sfgrid="clr-namespace:Syncfusion.Maui.DataGrid;assembly=Syncfusion.Maui.DataGrid"
xmlns:pulltoRefresh="clr-namespace:Syncfusion.Maui.PullToRefresh;assembly=Syncfusion.Maui.PullToRefresh"using Syncfusion.Maui.DataGrid;
using Syncfusion.Maui.PullToRefresh;Here is the complete implementation for hosting a DataGrid control as pullable content:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataGridUGDemo"
xmlns:sfgrid="clr-namespace:Syncfusion.Maui.DataGrid;assembly=Syncfusion.Maui.DataGrid"
xmlns:pulltoRefresh="clr-namespace:Syncfusion.Maui.PullToRefresh;assembly=Syncfusion.Maui.PullToRefresh"
x:Class="DataGridUGDemo.MainPage">
<ContentPage.Behaviors>
<local:PullToRefreshBehavior />
</ContentPage.Behaviors>
<Grid>
<pulltoRefresh:SfPullToRefresh x:Name="PullToRefresh"
TransitionMode="SlideOnTop">
<pulltoRefresh:SfPullToRefresh.PullableContent>
<sfgrid:SfDataGrid x:Name="DataGrid"
ItemsSource="{Binding Orders}">
</sfgrid:SfDataGrid>
</pulltoRefresh:SfPullToRefresh.PullableContent>
</pulltoRefresh:SfPullToRefresh>
</Grid>
</ContentPage>using Syncfusion.Maui.PullToRefresh;
public class PullToRefreshBehavior : Behavior<ContentPage>
{
private OrderInfoViewModel? viewModel;
private SfPullToRefresh? pullToRefresh;
protected override void OnAttachedTo(ContentPage bindable)
{
this.viewModel = new OrderInfoViewModel();
bindable.BindingContext = this.viewModel;
this.pullToRefresh = bindable.FindByName<SfPullToRefresh>("PullToRefresh");
if (this.pullToRefresh != null)
{
this.pullToRefresh.Refreshing += this.PullToRefresh_Refreshing;
}
base.OnAttachedTo(bindable);
}
private async void PullToRefresh_Refreshing(object? sender, EventArgs e)
{
this.pullToRefresh!.IsRefreshing = true;
await Task.Delay(new TimeSpan(0, 0, 3));
this.viewModel!.ItemsSourceRefresh();
this.pullToRefresh.IsRefreshing = false;
}
protected override void OnDetachingFrom(ContentPage bindable)
{
if (this.pullToRefresh != null)
{
this.pullToRefresh.Refreshing -= this.PullToRefresh_Refreshing;
}
base.OnDetachingFrom(bindable);
}
}Transition Mode
The TransitionMode property specifies the mode of the animations. It has the following two modes:
The default transition is SlideOnTop that draws the RefreshView on top of the DataGrid.
<pulltoRefresh:SfPullToRefresh x:Name="PullToRefresh"
TransitionMode="SlideOnTop">
<pulltoRefresh:SfPullToRefresh.PullableContent>
<sfgrid:SfDataGrid x:Name="DataGrid"
ItemsSource="{Binding Orders}">
</sfgrid:SfDataGrid>
</pulltoRefresh:SfPullToRefresh.PullableContent>
</pulltoRefresh:SfPullToRefresh>The following code example shows how to set the TransitionMode as Push to SfPullToRefresh. This transition moves only the refresh content and the header is fixed.
<pulltoRefresh:SfPullToRefresh x:Name="PullToRefresh"
TransitionMode="Push">
<pulltoRefresh:SfPullToRefresh.PullableContent>
<sfgrid:SfDataGrid x:Name="DataGrid"
ItemsSource="{Binding Orders}">
</sfgrid:SfDataGrid>
</pulltoRefresh:SfPullToRefresh.PullableContent>
</pulltoRefresh:SfPullToRefresh>
For detailed information about additional SfPullToRefresh properties and customization options, refer to the PullToRefresh customization documentation.