= $u_time + 86400) { $modifiedDate = get_the_modified_time('F jS, Y'); echo 'Última modificación: '.$modifiedDate.''; } }?>

Dynamic Load for a ListView para Xamarin Forms

He creado un ListView que carga dinamicamente los items según la BindableProperty “ItemsPerPage”.

dynamic-list-scrolling

Es una lista de tipos genéricos, por lo que a la hora de agregarla en xaml hay que especificar el tipo de la siguiente manera:

...

xmlns:myModel="clr-namespace:XamarinFormsDemo.Model;assembly=XamarinFormsDemo"
x:Class="XamarinFormsDemo.View.InfiniteScrollingPage"

...

<customControls:DynamicListView x:TypeArguments="myModel:MyColor"
     FullItemsSource="{Binding ColorsList}"
     ItemsPerPage="5"
     ItemTemplate="{....}">

 

La BindableProperty FullItemsSource es la encargada de guardar todos nuestros items, mientras que la propiedad ItemSource mostrará los items que se vayan cargando a medida que se vaya haciendo scroll.

 public class DynamicListView<T> : ListView where T : class
    {
        private readonly ObservableCollection<T> observableList;

        public DynamicListView()
        {
            this.observableList = new ObservableCollection<T>();
            this.ItemsSource = this.observableList;
            this.ItemAppearing += this.OnItemAppearing;
        }

        public IList<T> FullItemsSource
        {
            get
            {
                return (IList<T>)this.GetValue(FullItemsSourceProperty);
            }
            set
            {
                this.SetValue(FullItemsSourceProperty, value);
            }
        }

        public string ItemsPerPage
        {
            get
            {
                return (string)this.GetValue(ItemsPerPageProperty);
            }
            set
            {
                this.SetValue(ItemsPerPageProperty, value);
            }
        }

        private static void OnFullItemsSourceChanged(BindableObject bindableElement, object oldvalue, object newvalue)
        {
            var listView = bindableElement as DynamicListView<T>;
            listView?.OnFullItemsSourceChanged(listView);
        }

        private void OnFullItemsSourceChanged(DynamicListView<T> listView)
        {
            var numberOfItems = int.Parse(listView.ItemsPerPage);
            if(numberOfItems <= 0)
            {
                this.observableList.Clear();
            }
            else
            {
                if(numberOfItems > listView.FullItemsSource.Count)
                {
                    numberOfItems = listView.FullItemsSource.Count;
                }
                var items = listView.FullItemsSource.ToList().GetRange(0, numberOfItems);
                foreach(var elem in items)
                {
                    observableList.Add(elem);
                }
            }
        }

        private void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
        {
            var listView = sender as DynamicListView<T>;
            if(listView?.FullItemsSource == null || (this.observableList.Count == listView.FullItemsSource.Count))
            {
                return;
            }

            var indexOfItem = this.observableList.IndexOf((T)e.Item);
            var numberOfItems = int.Parse(listView.ItemsPerPage);

            if((indexOfItem > -1) && (e.Item == this.observableList.LastOrDefault()))
            {
                var observableItemsCount = this.observableList.Count;
                var fullItemsCount = listView.FullItemsSource.Count;

                if(numberOfItems > listView.FullItemsSource.Count)
                {
                    numberOfItems = listView.FullItemsSource.Count;
                }

                if(numberOfItems > fullItemsCount - observableItemsCount)
                {
                    numberOfItems = fullItemsCount - observableItemsCount;
                }

                var items = listView.FullItemsSource.ToList().GetRange(this.observableList.Count, numberOfItems);
                foreach(var elem in items)
                {
                    observableList.Add(elem);
                }
            }
        }

        public static BindableProperty FullItemsSourceProperty = BindableProperty.Create
            (
                nameof(FullItemsSource), typeof(IList<T>), typeof(DynamicListView<T>), default(IList<T>), BindingMode.OneWay, null,
                OnFullItemsSourceChanged);

        public static BindableProperty ItemsPerPageProperty = BindableProperty.Create
            (nameof(ItemsPerPage), typeof(string), typeof(DynamicListView<T>), string.Empty);
    }

Si haceis una carga de datos de manera extraña (invocando a algún pokemon o desde el navigationService u otra manera arcana…) es posible que la primera vez que se muestra la página, los elementos de la lista no sean visibles; para ello podéis “arreglarlo” añadiendo las siguientes líneas al método OnItemAppearing (antes de la comprobación del índice del item):

if(!this.observableList.Any())
{
this.ItemsSource = this.observableList;
this.OnFullItemsSourceChanged(listView);
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *