DLToolkit.Forms.Controls icon indicating copy to clipboard operation
DLToolkit.Forms.Controls copied to clipboard

Infinite FlowListView

Open lowkicker opened this issue 6 years ago • 5 comments

Hi,

I Have a Problem with infinite flowlistview. The List show the first results but when i scroll to the bottom doesn't call the method to load more. My Code

View ` <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestingFlow" xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView" x:Class="TestingFlow.MainPage">

<StackLayout>
    <flv:FlowListView x:Name="flowListView" FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="false"
        FlowItemTappedCommand="{Binding ItemTappedCommand}" FlowLastTappedItem="{Binding LastTappedItem}"
        FlowItemsSource="{Binding Items}" FlowIsLoadingInfinite="{Binding IsLoadingInfinite}"
        FlowTotalRecords="{Binding TotalRecords}" FlowIsLoadingInfiniteEnabled="true"
        FlowLoadingCommand="{Binding LoadingCommand}">

        <flv:FlowListView.FlowLoadingTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label
                        HorizontalTextAlignment="Center"
                        VerticalTextAlignment="Center"
                        TextColor="Black"
                        Text="Loading..."
                    ></Label>
                </ViewCell>
            </DataTemplate>
        </flv:FlowListView.FlowLoadingTemplate>

        <flv:FlowListView.FlowColumnTemplate>
            <DataTemplate>
                <Label HorizontalOptions="Fill" VerticalOptions="Fill" 
                    XAlign="Center" YAlign="Center" Text="{Binding Title}"/>
            </DataTemplate>
        </flv:FlowListView.FlowColumnTemplate>

    </flv:FlowListView>
</StackLayout>
`

Xaml.Cs `using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms;

namespace TestingFlow { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new ViewModelMain();

    }
    protected async override void OnAppearing()
    {
        base.OnAppearing();
        await ((ViewModelMain)BindingContext).LoadMoreAsync();
    }
}

} `

ViewModel `using DLToolkit.Forms.Controls; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Drawing; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using Xamarin.Forms;

namespace TestingFlow { public class ViewModelMain : INotifyPropertyChanged { public string Name { get; set; } public ViewModelMain() {

        Items = new FlowObservableCollection<SimpleItem>();
        ItemTappedCommand = new Command((param) =>
        {

            var item = LastTappedItem as SimpleItem;
            if (item != null)
                System.Diagnostics.Debug.WriteLine("Tapped {0}", item.Title);

        });

        LoadingCommand = new Command(async (arg) =>
        {
            await LoadMoreAsync();
        });
       
    }

    private ObservableCollection<SimpleItem> _Items;
    public ObservableCollection<SimpleItem> Items { get
        {
            return _Items;
        }
        set
        {
            _Items = value;
            OnPropertyChanged(nameof(Items));
        } }

    public Command LoadingCommand { get; set; }

    public void ReloadData()
    {
        var exampleData = new List<object>();

        var howMany = 60;
        TotalRecords = 240;

        for (int i = 0; i < howMany; i++)
        {
            exampleData.Add(new SimpleItem() { Title = string.Format("Item nr {0}", i) });
        }


        Items = new ObservableCollection<SimpleItem>();
    }
    public Command ItemTappedCommand { get; set; }
    public object LastTappedItem  { get; set; }

    public bool IsLoadingInfinite { get; set; }

    public int TotalRecords { get; set; }

    public async Task LoadMoreAsync()
    {
        var oldTotal = Items.Count;

        await Task.Delay(3000);

        var howMany = 60;

        var items = new List<SimpleItem>();
        var list = new ObservableCollection<SimpleItem>();
        for (int i = oldTotal; i < oldTotal + howMany; i++)
        {
            list.Add(new SimpleItem() { Title = string.Format("Item nr {0}", i) });
        }
        Items = list;
        //Items.AddRange(items);

        IsLoadingInfinite = true;
    }

    public class SimpleItem  : INotifyPropertyChanged
    {
        string title;
        public string Title { get; set; }
        public System.Drawing.Color Color { get; set; } = System.Drawing.Color.Blue;

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }


    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

} `

What am I doing wrong?

lowkicker avatar Nov 09 '18 17:11 lowkicker

Hi: I have the same problem. Only reload one times!

HugoTruffe avatar Dec 11 '18 11:12 HugoTruffe

(Workaround) I used a manual way by listening to the event FlowItemAppearing. Just make sure you have a unique ID for each item and compare when items appear whether an item is the last item in your list, if it is, call command to add more items.

myXamlList.FlowItemAppearing += async (sender, e) => {
                if (VM.IsLoading || VM.myList.Count == 0) //skip in these cases
                    return;
                //is hit bottom!
                var s1 = (e.Item as myModel).ID.ToString();
                var s2= VM.myList[VM.myList.Count - 1].ID.ToString();
                if (s1.Equals(s2))
                {
                    VM.readMoreCommand.Execute(null); //load more items
                }
            };

Almazidi avatar Jan 11 '19 09:01 Almazidi

I have the same issue...

angelru avatar Jan 17 '19 18:01 angelru

I have the same issue

rredoh avatar Feb 11 '19 08:02 rredoh

Change Command to ICommand

public ICommand LoadMoreCommand { get; private set; }
public ViewModelMain()
{
      LoadMoreCommand = new Command(async () => { await LoadMoreData(); });
}

public async Task LoadMoreData()
{
     // Write your logic here
}

divyesh008 avatar Jun 17 '20 12:06 divyesh008