Forum Xamarin.Forms

Pull down refresh indicator not stopping after complete loading

HarshitaHarshita INMember ✭✭✭✭
edited January 2018 in Xamarin.Forms

Here is my sample xaml

<ListView ItemsSource="{Binding EmployeeList}" HasUnevenRows="True" 
                          IsPullToRefreshEnabled="True" RefreshCommand="{Binding RefreshCommand}" IsRefreshing="{Binding IsBusy}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <StackLayout>
                                    <Label Text="{Binding Name}" TextColor="Black"/>
                                    <Label Text="{Binding Department}" TextColor="Black"/>
                                </StackLayout>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackLayout>
            <Image Source="{Binding GetSource}"/>

i want that when a user pull down on list view then it will load a image from URI(just playing around)

here is my view model

    public class MainViewModel : INotifyPropertyChanged
    {
        private List<Employee> _employeeList { get; set; }

        private string _source { get; set; }

        public string GetSource { get { return _source; } set { _source = value; OnPropertyChanged(); } }


        Command _refreshCommand;
        public Command RefreshCommand
        {
            get
            {
                return _refreshCommand;
            }
        }

        public List<Employee> EmployeeList
        {
            get { return _employeeList; }
            set { _employeeList = value;
                OnPropertyChanged();
            }
        }

        // class constractor
        public MainViewModel()
        {
            var employeeServices = new EmployeeServices();
            EmployeeList = employeeServices.GetEmployees();
            _refreshCommand = new Command(ShowImage);
        }

        private void ShowImage()
        {
            var imagesou = "https://www.hindustantimes.com/rf/image_size_640x362/HT/p2/2016/04/08/Pictures/_e76dfb4e-fd62-11e5-bced-6695953481e2.jpg";
            GetSource = imagesou;
        }

        #region PropertyChange
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName=null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
}

Problem is that when I pull down for refreshing,then it works fine,but after complete image loading the refresh indicator is not stopping,so how to do this?

Best Answer

Answers

  • SreeeeSreeee INMember ✭✭✭✭✭
    edited January 2018

    Can you add ViewCell.View after viewcell like below and test:

                   <ListView>
                      <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <ViewCell.View>
                                        <StackLayout/>
                                   </ViewCell.View>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
    

    Also, you forget to add the isbusy variable declaration in your viewmodel (IsRefreshing="{Binding IsBusy}"). In the following link isRefreshing is used instead of isbusy.

    Please refer the following link:
    https://xamarinhelp.com/pull-to-refresh-listview/

  • BillyMartinBillyMartin USMember ✭✭✭

    I had to set the binding to one way, because somehow it was changing the IsBusy property from the listview.

                    IsRefreshing="{Binding IsBusy, Mode=OneWay}"
    
  • DarrenKayDarrenKay GBUniversity ✭✭

    @BillyMartin said:
    I had to set the binding to one way, because somehow it was changing the IsBusy property from the listview.

                    IsRefreshing="{Binding IsBusy, Mode=OneWay}"
    

    I had everything right, this solved my problem. Thanks

  • Ashish_sharmaAshish_sharma INMember ✭✭✭
    edited July 2019

    @BillyMartin

    Thanks Its working for me

    Ex => Code into XAML

    <ListView  X:Name ="listview" IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsRefreshing, Mode=OneWay}" RefreshCommand="{Binding RefreshCommand}">
    </ListView>
    

    in Viewmodel

    //Refresh command
     public ICommand RefreshCommand
            {
                get
                {
                    return new Command(() =>
                    {
                        IsRefreshing = true;
    
                       put here your api method like eg.   EetEmployeeList();
                        IsRefreshing = false;
    
                    });
                }
            }
    
            /// <summary>
            /// ListView Refreshing
            /// </summary>
            private bool _isRefreshing = false;
            public bool IsRefreshing
            {
                get { return _isRefreshing; }
                set
                {
                    _isRefreshing = value;
                    OnPropertyChanged(nameof(IsRefreshing));
                }
            }
    

    Thank's

  • Ashish_sharmaAshish_sharma INMember ✭✭✭
    edited July 2019

    Xaml code is

      <ListView x:Name="listview"  IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsRefreshing, Mode=OneWay}" RefreshCommand="{Binding RefreshCommand}"  HasUnevenRows="true" SeparatorVisibility="None" >
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
    
    </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
    
  • BillyMartinBillyMartin USMember ✭✭✭

    NP. Glad it's working for everyone. Are you using Xamarin Essentials?

  • LaumaniaLaumania DKMember ✭✭✭
    edited October 2019

    I'm having the same issue, that the "loading spinner" sometimes keeps spinning.

    However, I have async commands in my app, as the normal data retrieval is often a "await GetDate();", which cascades up to commands.

    <ListView ItemsSource="{Binding LocalFeedItems}"
        IsPullToRefreshEnabled="true"
        IsRefreshing="{Binding IsRefreshingLocal, Mode=OneWay}"
        RefreshCommand="{Binding RefreshLocalCommand}"
        CachingStrategy="RecycleElement"
        HasUnevenRows="true"
        ItemTemplate="{StaticResource feedItemDataTemplateSelector}">
    </ListView>
    

    The command is setup like:

    this.RefreshLocalCommand = new Command(async () =>
    {
        if (IsRefreshingLocal)
            return;
    
        IsRefreshingLocal = true;
        await RefreshLocalData();
        IsRefreshingLocal = false;
    });
    

    I'm refreshing data like:

    private async Task RefreshLocalData()
    {
        var foundItems = await _dataService.GetFeed();
    
        if (foundItems != null)
        {
            this.LocalFeedItems.Clear();
            foreach (var item in foundItems)
            {
                this.LocalFeedItems.Add(item);
            }
        }
    }
    

    And my "IsBusy" looks like this:

    public bool IsRefreshingLocal
    {
        get
        {
            return _isRefreshingLocal;
        }
        set
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                _isRefreshingLocal = value;
                OnPropertyChanged();
            });
    
        }
    }
    

    As you can see I have tried MainThread from Xamarin Essentials as I was expecting it was something with async/threads what-ever, but it still doesn't work always.

    Any ideas?

  • bikuzbikuz Member

    I was having the same issue. Some how it was fixed when i added 'await Task.Delay(1000)' just before async function call.
    Hope it will works for you too.

    this.RefreshLocalCommand = new Command(async () =>
    {
        if (IsRefreshingLocal)
            return;
    
        IsRefreshingLocal = true;
    
        await Task.Delay(1000);  //this task delay has fixed my issue. 
    
        await RefreshLocalData();
        IsRefreshingLocal = false;
    });
    
Sign In or Register to comment.