Xamarin Forms Pull To Refresh With ListView

The Xamarin Forms ListView control has the ability to allow the user to pull down from the top of the ListView to trigger a refresh command. I say a refresh command, because the pull to refresh, just triggers a command and you can do whatever you want in that command, including not updating the ListView.


There are 3 properties you need to be aware of to implement the pull to refresh functionality.

 <ListView ItemsSource="{Binding MyList}"
           RefreshCommand="{Binding RefreshCommand}"
           IsRefreshing="{Binding IsRefreshing}" />

Set IsPullToRefreshEnabled=”True” to enable the functionality, then create these 2 properties in your ViewModel.

private bool _isRefreshing = false;
public bool IsRefreshing { 
get { return _isRefreshing; }
set {
    _isRefreshing = value;
public ICommand RefreshCommand
    get {
        return new Command(async () =>
            IsRefreshing = true;
            await RefreshData();

            IsRefreshing = false;

Now when you pull down from the top of the listview, it will show a refresh animation, while IsRefreshing=”true”.

Pull To Refresh Android  Pull To Refresh iOS

Pull To Refresh Customization

On each platform we can customize a small part of the refresh animation.


Android uses the SwipeRefreshLayout control to display an animation while the ListView is being updated. The SwipeRefreshLayout is internal in the ListViewRenderer, hence you are not able to call any properties on it directly, unless you want to write a whole new ListViewRenderer. Hence, until this has some access given, it’s currently impossible to do, without writing your own ListViewRenderer.

However, there is a way, using reflection and a custom renderer, that this can be done. It’s not the best solution, but it works.

First create a new file in Resources > values in your Android project, called array.xml

<?xml version="1.0" encoding="utf-8"?>
    <color name="red">#FF0000</color> 
    <array name="SwipeRefreshColors"> 

Now create a custom renderer, to get this private field, and set the color.

[assembly: ExportRenderer(typeof(Xamarin.Forms.ListView), typeof(CustomListViewRenderer))]
namespace Mobile.Droid
    public class CustomListViewRenderer : ListViewRenderer 
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e) 
            if (e.NewElement != null) 
                FieldInfo[] fields = typeof(ListViewRenderer).GetFields( BindingFlags.NonPublic | BindingFlags.Instance);
                var refresh = (SwipeRefreshLayout)fields.First(x => x.Name == "_refresh").GetValue(this); 


In iOS the UIRefreshControl to display the animation while refreshing data. The UIRefreshControl has a TintColor and AttributedTitle, however unlike Android, we have a way to interact with this control. The ListViewRenderer has a ViewController, which is actually a UITableViewController. From here we can reach the RefreshControl.

[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRender))]
namespace Mobile.iOS
    public class ListViewRender: ListViewRenderer
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)

            ((UITableViewController)ViewController).RefreshControl.TintColor = UIColor.Red;


  • Not available on UWP, Android or Windows Phone 8.1
  • Not able to easily customize the refresh animation.
  • Only limited styling options available.


    1. Adam Pedley

      RefreshData is just a placeholder that I used in my example. You will need to create it yourself to get a new version of the data and bind it to the list.

    1. Adam Pedley

      OnPropertyChanged can be written yourself or may be part of your MVVM framework. To ensure that updates from your ViewModel to your View are recognized, your ViewModel should inherit INotifyPropertyChanged.

      This will then create an event called PropertyChanged.

      Then you create a function, to call this event. e.g.

      public class BaseViewModel : INotifyPropertyChanged
      public event PropertyChangedEventHandler PropertyChanged;

      public void OnPropertyChanged([CallerMemberName] string propertyName = “”)
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));