Tag Archives: Xamarin Forms Custom ListView

Oki Dokie… Let’s try out our Xamarin Forms AwesomeListView…

Hope you guy’s recall my previous post on Xamarin Forms Custom Listview with some added awesomeness… 😉 Where I unveiled a listview that is actually awesome ? 😀 Well as promised here is the article about the sample application I will be developing using my AwesomeListView.

Now for this article we will create a small Xamarin Forms app, which is going to load a bunch of dummy contacts to a listview… 😀

Let’s begin…

So this is how it’s all gonna stack up,

capture

As you can see above you need to create a Xamarin Forms project solution. And within that I have separated the code based on MVVM pattern, whereas we will be using the ObservableObject class as the base for handling properychanged and command events. Contacts Page shall be our View which we are gonna fit in our awesome-listview 😉 !

And yes hereby I’m gonna call it AwesomeListView ! 😀

Setting up the Data Source…

First create a Modal class called Contacts. This shall be the modal class for our Contacts items for the listview.

namespace WhateverYourNamespace.Models
{
    public class Contact
    {
        public String Name{ get; set; }
        public String Phone { get; set; }
    }
}

 

Now we need to create a tiny repository class, which will return a bunch of dummy data to be populated in out listview. Well don’t worry ! obviously I wasn’t going to hardcode that by myself, I’m a engineer for my degree certificate’s sake 😛 lol

So we are going to be using this tiny awesome library to generate our dummy data, Faker.Net.Portable ! Surprisingly enough its a pretty cool library which can populate real-like dummy data with ease. You can read all about it on my blog post about it, https://theconfuzedsourcecode.wordpress.com/2015/11/07/wanna-create-an-awesome-dummy-data-set/

Anyways go ahead and add that library to your project from Nuget Package Manager, to your PCL, Xam.Android, Xam.iOS and Xam.WinPhone…

With that now we can set up our data source repository as follows.

namespace WhateverYourNamespace.DataAccess
{
    public class ContactsRepository
	{
        public static List<Contact> FakeContactsList = new List<Contact>();

        public ContactsRepository() 
        {
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    // Generating dummy data and adding to the list 

                    var name = Faker.Name.FullName();
                    var phone = Faker.Phone.CellNumber();

                    FakeContactsList.Add(new Contact { Name = name, Phone = phone });
                }
                catch (Exception)
                {

                }
            }
        }
    }
}

 

In our ContactsRepository class we are going to be having a List items source with a static reference, and in the runtime we will populate our fake data in the constructor and add them to the static list.. Pretty straight forward ! 😀

Setting up the ViewModel…

Now we need to set up our ViewModel classes for the Listview to be used, therefore we shall begin by creating the base ObservableObject class which is going to be an abstract with the INotifyPropertyChanged handlers.

namespace WhateverYourNamespace.Core
{
    public abstract class ObservableObject : INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

 

Now let’s dive into our ViewModel, whereas we shall be creating the ContactsPageViewModel which is to be used with the Awesome-Listview of ours. 😉 Now just for the case of article, I will provide you with section by section of the whole ViewModel as shown below… So if you are already writing the code while reading this article, I suggest you keep including the code snippets which will be given in this article, step by step just as it is.. 😉

Constructor and Private Values for the ViewModel

Below is the constructor and the private values to  be used in our ViewModel…

namespace WhateverYourNamespace.ViewModels
{
    class ContactsPageViewModel : ObservableObject
    {
        private readonly INavigation _navigation;
        private List<Contact> _repository;
        private ObservableCollection<Contact> _contactsList;
        private bool _isBusy;
        private bool _isFree;
        private bool _isLoadMoreEnabled;
        private bool _isDataListEmpty;
        private string _filterBy;
        private int _loadedCount;
        private Contact _selectedContact;

        public ContactsPageViewModel(List<Contact> repository, INavigation navigation)
        {
            LoadMoreContactsCommand = new Command(LoadMoreContacts);

            _repository = repository;
            _navigation = navigation;
            _loadedCount = 0;
            _filterBy = "FILTER1";
            IsBusy = false;
            _isDataListEmpty = false;
            _isLoadMoreEnabled = true;

            LoadMoreContacts();
        }
		
	// Properties Section //
		
	// Commands Section //
		
	// Methods Section //
     }
}

 

As you can see, we shall be passing in a List of Contacts as the Item Repository, which is to be used for providing data for each loading cycle of the list view. I have also instantiated a Command property there in the constructor, which shall be explained in the coming paragraphs of this article. And as for the rest of Private variables and their default values, you will get the idea in the next section…

// Properties // for the ViewModel

Below are the Properties which should be included in the above ViewModel class (right underneath the Constructor would be idea 😉 )

#region Properties

/// <summary>
/// Gets or Sets the ContactsList value
/// </summary>
public ObservableCollection<Contact> ContactsList
{
	get { return _contactsList ?? (_contactsList = new ObservableCollection<Contact>()); }
}

/// <summary>
/// Gets or Sets the Filter String value, used for filtering the loaded results...
/// </summary>
public string FilterBy
{
	get { return _filterBy; }
	set
	{
		_filterBy = value;
		FilterAndReLoadContacts();
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets the currently loaded items count
/// </summary>
public int LoadedCount
{
	get { return _loadedCount; }
	set
	{
		_loadedCount = value;
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets the Selected Contact Item in the list
/// </summary>
public Contact SelectedContact
{
	get { return _selectedContact; }
	set
	{
		_selectedContact = value;
		GoToContactDisplayPage();
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets the IsBusy value, used for disabling any UI Control while loading data...
/// </summary>
public bool IsBusy
{
	get { return _isBusy; }
	set
	{
		_isBusy = value;
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets the IsFree value, used for re-enabling any UI Control after loading data (opposite of IsBusy) ...
/// </summary>
public bool IsFree
{
	get { return _isFree; }
	set
	{
		_isFree = value;
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets IsLoadMoreEnabled value, used for disabling Load More button when no results available
/// </summary>
public bool IsLoadMoreEnabled
{
	get { return _isLoadMoreEnabled; }
	set
	{
		_isLoadMoreEnabled = value;
		OnPropertyChanged();
	}
}

/// <summary>
/// Gets or Sets the IsDataListEmpty value, used For displaying empty result set.
/// </summary>
public bool IsDataListEmpty
{
	get { return _isDataListEmpty; }
	set
	{
		_isDataListEmpty = value;
		OnPropertyChanged();
	}
}

#endregion

 

Those are the properties as said, and I have given a small description for each property and its use, so I hope I wouldn’t have to give much of an explanation here… 🙂 I hope those above properties may solve the mystery regarding the private methods used in the Constructor.

// Commands // for the ViewModel

Below is the command that we will be implementing in the ViewModel.

#region Commands

public ICommand LoadMoreContactsCommand { get; set; }

#endregion

 

Hope you remember we instantiated a command in the Constructor of our ViewModel, yes this is the command we are using there.

If you are done including the Commands let’s move into the Methods implementation.

// Methods // for the ViewModel

Below are the set of methods which should be included in the ViewModel.

#region Methods

private async void LoadMoreContacts()
{
	if (IsBusy)
	{
		return;
	}

	IsBusy = true;
	IsFree = false;

	try
	{
		await Task.Delay(2000);

		// Check if the data source is empty 
		if (_repository.Count == 0)
		{
			IsDataListEmpty = true;
			IsLoadMoreEnabled = false;

			IsBusy = false;
			IsFree = true;

			return;
		}

		// Check if all the items in the source are loaded to UI
		if (ContactsList.Count == _repository.Count)
		{
			IsLoadMoreEnabled = false;

			IsBusy = false;
			IsFree = true;

			return;
		}


		int LoadBeginIndex = 0;
		int LoadEndIndex = 10;

		// Setting the Begin Index for 2nd hit and forward
		if (ContactsList.Count != 0)
		{
			LoadBeginIndex = ContactsList.Count;
		}

		// Check if the Current Loading Rage is with in the data set size
		if (LoadEndIndex > (_repository.Count - ContactsList.Count))
		{
			LoadEndIndex = (_repository.Count - ContactsList.Count);
		}

		// Loading the selected data set to the UI
		var characters = _repository.GetRange(LoadBeginIndex, LoadEndIndex);
		foreach (var character in characters)
		{
			ContactsList.Add(character);
		}

		LoadedCount = ContactsList.Count;
	}
	catch (Exception ex)
	{

	}

	IsBusy = false;
	IsFree = true;
}

private async void FilterAndReLoadContacts()
{
	if (IsBusy)
	{
		return;
	}

	IsBusy = true;
	IsFree = false;

	try
	{
		// Include your Filtering algorithm ...

		// You could filter the ContactsList in 
		// any order you wish and reset it back to it
	}
	catch (Exception ex)
	{

	}

	IsBusy = false;
	IsFree = true;
}

private async void GoToContactDisplayPage()
{
	if (SelectedContact == null)
		return;

	//Code to navigate the user to any other new Page to view details of the selected item
}

#endregion 

 

Now as you can see above, LoadMoreContacts() is used for loading the next set of results from the Repository object and setting to the ListView. There you can see we are using IsBusy and IsFree properties which is to notify the interface that the background processing is happening, which you could use to wire up to some UI controllers and use them as you wish. 🙂 Also you may have noticed the Await Timers inside the method, well that was just to simulate the waiting of the data loading, just for this sample app.

Then I have included the FilterAndReLoadContacts() method just as a skeleton method for you to implement your  own Filtering mechanism.

GoToContactDisplayPage() method will be used to pop up the detailed view of the selected item, which will be called through the SelectedContact property value change.

That’s all for the ViewModel for our Awesome-ListView, next make sure you have set up my AwesomeList in your project…

Setting up the AwesomeListView …

Well if you haven’t yet set up my AwesomeListView, then you better head into my previous article and do that right now and come back to this article to continue. https://theconfuzedsourcecode.wordpress.com/2015/11/10/xamarin-forms-custom-listview-with-some-added-awesomeness/

Alright ! if that’s set up then let’s dive into the MVVM’s “View” code…

Setting up the View …

So we need to set up the View for our MVVM implementation right ? I suggest we create a small ContentPage and include our AwesomeListView in it and do the necessary bindings with the above ViewModel…

Go ahead and create ContactsPage view in your Views folder as follows.

namespace WhateverYourNamespace.Views
{
    class ContactsPage : ContentPage
    {
        ContactsPageViewModel _viewModel;

        AwesomeListView ListView_Contacts = new AwesomeListView(true);

        public ContactsPage()
        {
	    // Defining UI Controls and setting up Bindings
            
            this.Appearing += ContactsPage_Appearing;
        }

        private void ContactsPage_Appearing(object sender, EventArgs e)
        {
            if (ListView_Contacts.ItemsSource == null)
            {
                // Populating the data in Repository
                ContactsRepository repo = new ContactsRepository();

                // Creating the ViewModel with necessary parameters
                _viewModel = new ContactsPageViewModel(ContactsRepository.FakeContactsList, this.Navigation);

                // Setting the created ViewModel to this View
                this.BindingContext = _viewModel;
            }
        }
    }
}

 

Yes we need to create an instance of the ContactsPageViewModel and also an instance of our AwesomeListView. There you can see I’m passing in ‘true’ value to the contructor, which means I’m going to be using the ListView with a ‘Load More’ footer button. 😀

I recommend that inside the Page.Appearing method only we should be setting up our BindingContext as we can make sure that all the UI Controls are loaded, whereas you can see there in the ContactsPage_Appearing() method I’m creating the Datasource – ContactsRepository and passing it into the ViewModel’s constructor. Thereby ending the execution with setting the BindingContext to it.

Nope we are not done yet, we need to Initialization the UI controls inside the Constructor right ? including our AwesomeListView as follow… So replace the above Constructor with the following code snippet.

public ContactsPage()
{
	var ListItemTemplate = new DataTemplate(typeof(TextCell));
	ListItemTemplate.SetBinding(TextCell.TextProperty, "Name");
	ListItemTemplate.SetBinding(TextCell.DetailProperty, "Phone");

	ListView_Contacts.SetBinding(AwesomeListView.ItemsSourceProperty, "ContactsList");
	ListView_Contacts.SetBinding(AwesomeListView.SelectedItemProperty, "SelectedContact");
	ListView_Contacts.SetBinding(AwesomeListView.IsEnabledProperty, "IsFree");
	ListView_Contacts.SetBinding(AwesomeListView.IsBusyProperty, "IsBusy");
	ListView_Contacts.SetBinding(AwesomeListView.IsLoadMoreItemsPossibleProperty, "IsLoadMoreEnabled");
	ListView_Contacts.ItemTemplate = ListItemTemplate;

	ListView_Contacts.SetBinding(AwesomeListView.LoadMoreItemsFooterCommandProperty, "LoadMoreContactsCommand");

	Label lbl_ContactsEmptyAlert = new Label()
	{
		Text = "Sorry ! Contacts list is currently empty... Please check back later...",
		HorizontalOptions = LayoutOptions.CenterAndExpand,
		VerticalOptions = LayoutOptions.CenterAndExpand,
		FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
		XAlign = TextAlignment.Center
	};
	lbl_ContactsEmptyAlert.SetBinding(Label.IsVisibleProperty, "IsDataListEmpty");
	StackLayout StackLayout_ContactsEmptyAlert = new StackLayout
	{
		Children = { lbl_ContactsEmptyAlert },
		Padding = new Thickness(10, 0, 10, 5),
	};
	StackLayout_ContactsEmptyAlert.SetBinding(StackLayout.IsVisibleProperty, "IsDataListEmpty");
	
	Label lbl_LoadedCount = new Label()
	{
		FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
	};
	lbl_LoadedCount.SetBinding(Label.TextProperty, "LoadedCount", BindingMode.TwoWay, null, "Loaded {0} items ...");

	if (Device.OS != TargetPlatform.WinPhone)
	{
		this.Padding = new Thickness(5, Device.OnPlatform(5, 0, 0), 5, 5);
	}

	this.Content = new StackLayout
	{
		Children = 
		{
			StackLayout_ContactsEmptyAlert,
			new StackLayout
			{
				Children = 
				{ 
					lbl_LoadedCount
				},
				Padding = new Thickness(10, 0, 0, 0),
			},
			ListView_Contacts
		}
	};

	this.Appearing += ContactsPage_Appearing;
}

 

First we will be creating a small DataTemplate of TextCell, then we shall be initializing our AwesomeListView with the necessary bindings. As you can see above I have set up all the Bindable Properties of our AwesomeListView to the ViewModel’s properties and commands. ItemsSourceProperty, SelectedItemProperty, IsEnabledProperty are quite ordinary properties of a generic ListView, then you can see our custom properties being binded such as, IsBusyProperty, IsLoadMoreItemsPossibleProperty, LoadMoreItemsFooterCommandProperty which are the extra features provided by our AwesomeListView.

The lbl_ContactsEmptyAlert is a label that will show up when the Datasource is empty, based on the IsDataListEmpty property of the ViewModel. I have created a small Label lbl_LoadedCount to show how many items have been loaded to the ListView which also binded to the ViewModel’s LoadedCount property.

Now that should set up everything perfectly, let’s fire it up then…

Finally let’s FIRE IT UP… ! 😉

If you had implemented everything properly, there should be no compilation errors, therefore just hit 5 and watch the magic… 😀

// Here we go…

2

// While loading the data to ListView…

1

// After it reaches the end of the Data source…

3

// When the Data source is empty…

4

Some Wisdom…

Now after everything worked out beautifully, it’s all up to your how you are going to use this and improve it to display in your own App’s… 😉 Just a matter of your Imagination !

As I have mentioned I left the Filtering code blank for you to write your own algorithm, but if you find it hard, here is just a tip, set up a couple of buttons in the View and have them set the value of FilterBy in the ViewModel, where as in the Set event, we are calling the filtering method right ? there catch the certain string value and do the filtering based on that for the ContactsList in the ViewModel.

Inside the LoadMoreContacts() method you could even call a webservice of your choice and have a tiny pagination algorithm set up so you could load the data set by set…

Like I said it’s all just a matter of your Imagination ! 😉

Well there it goes folks, hope this post was helpful for you and prolly saved you some time… 🙂 Please share this among other developers as this may become handy for another developer as well, and you may save their precious time as well…

Cheers folks ! Stay Awesome ! 😀

 

Xamarin Forms Custom Listview with some added awesomeness… ;)

Let me make it obvious, are you looking for a Xamarin Forms Listview that could have awesome features such as Infinite Scrolling, Load More footer button, Activity Indicator, Data Source awareness, and so on ? Alrighto ! then keep on reading my friend… 😉

It’s about to go down! 😛

So there was this one day, I came across implementing a simple Listview with an infinite data loading, whereas when the user reaches the end of the listview scroll, it should automatically load more items to the listview and so on. And easy enough I recalled some article I read through Xamarin Weekly Newsletter sometime back, so my lazy self wanted to look it up and check out the implementation. http://www.codenutz.com/lac09-xamarin-forms-infinite-scrolling-listview/ and yes it was a great tutorial indeed, I ended up finishing the implementation in few hours.
But my boss man wanted me to add a “Load More items” button at the bottom of the listview, instead of having to load items automatically while scrolling.

Well well, it seemed like no more lazing around, and just to make it fun, I took this as an opportunity to create an awesome-Listview with both those capabilities included and few more added sweetness… 😉 So here I am sharing my code as usual… 😀

And yes I must admit that I got inspired by the www.codenutz.com infinite scroll listview and I used his implementation of infinite loading method code in my own improved listview, so a big shout out for the developer of that listview. 🙂 You can check his github from here. Codenutz.XF.InfiniteListView

behold the AwesomeListView …

Now I shall reveal the Awesome-ListView of mine… 😀 and yes of course I literally named it the AwesomeListView ! lol

Instead of chunks of the code, I shall post the entire code at once, so anyone could easily use it upon their wish.. 😉

namespace WhateverYourNamespace.Controls
{
    /// <summary>
    /// A simple listview that exposes a bindable command to allow infinite loading behaviour.
    /// Along with Footer 'Load more' items button functionality and Auto Disable functionality
    /// </summary>
    public class AwesomeListView : ListView
    {
        Button btn_LoadMoreItems;

        ActivityIndicator ActivityIndicator_LoadingContacts;

        /// <summary>
        /// Constructor - Pass in true/false to visible/hide Listview Footer 'Load more' items button
        /// </summary>
        /// <param name="IsLoadMoreFooterVisible"></param>
        public AwesomeListView(bool IsLoadMoreItemsFooterVisible = false)
        {
            ActivityIndicator_LoadingContacts = new ActivityIndicator
            {
                Color = Color.FromHex("#FF3300"),
                IsRunning = true,
                HorizontalOptions = LayoutOptions.FillAndExpand,
            };
            
            if (IsLoadMoreItemsFooterVisible)
            {
                // Setting up 'Load More' items footer

                btn_LoadMoreItems = new Button
                {
                    Text = "Load More... ",
                    TextColor = Color.White,
                    BackgroundColor = Color.FromHex("#0066FF"),
                    BorderRadius = 0,
                    BorderWidth = 0,
                    BorderColor = Color.FromHex("#0066FF"),
                    VerticalOptions = LayoutOptions.EndAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                };
                btn_LoadMoreItems.Clicked += btn_LoadMoreItems_Clicked;

                this.IsLoadMoreItemsPossible = true;

                this.Footer = new StackLayout
                {
                    Orientation = StackOrientation.Vertical,
                    Children = { ActivityIndicator_LoadingContacts, btn_LoadMoreItems },
                    Padding = new Thickness(0,5,0,5)
                };
            }
            else
            {
                // Setting up 'Infinite Scrolling' items

                ItemAppearing += AwesomeListView_ItemAppearing;

                this.Footer = new StackLayout
                {
                    Orientation = StackOrientation.Vertical,
                    Children = { ActivityIndicator_LoadingContacts },
                    Padding = new Thickness(0, 5, 0, 5)
                };
            }
        }

        #region UI Control Events

        /// <summary>
        /// Click event of Listview Footer 'Load More' items button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_LoadMoreItems_Clicked(object sender, EventArgs e)
        {
            if (LoadItemsMoreFooterCommand != null && LoadItemsMoreFooterCommand.CanExecute(null))
                LoadItemsMoreFooterCommand.Execute(null);
        }

        /// <summary>
        /// List View ItemAppearing event for infinite scrolling
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AwesomeListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
        {
            // Checking whether its possible to load more items
            if (!IsLoadMoreItemsPossible)
            {
                return;
            }

            var items = ItemsSource as IList;

            if (items != null && e.Item == items[items.Count - 1])
            {
                if (LoadMoreInfiniteScrollCommand != null && LoadMoreInfiniteScrollCommand.CanExecute(null))
                    LoadMoreInfiniteScrollCommand.Execute(null);
            }
        }

        #endregion

        #region Bindable Properties

        /// <summary>
        /// Gets or sets the property binding that defines whether the list has reached the 
        /// end of the items source thereby declaring its not possible to load more itmes... 
        /// </summary>
        public static BindableProperty IsLoadMoreItemsPossibleProperty = BindableProperty.Create<AwesomeListView, bool>(ctrl => ctrl.IsLoadMoreItemsPossible,
        defaultValue: false,
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanging: (bindable, oldValue, newValue) =>
        {
            var ctrl = (AwesomeListView)bindable;
            ctrl.IsLoadMoreItemsPossible = newValue;
        });

        /// <summary>
        /// Gets or sets the property binding that defines whether the listview is busy 
        /// loading items in the background to the UI
        /// </summary>
        public static BindableProperty IsBusyProperty = BindableProperty.Create<AwesomeListView, bool>(ctrl => ctrl.IsBusy,
        defaultValue: false,
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanging: (bindable, oldValue, newValue) =>
        {
            var ctrl = (AwesomeListView)bindable;
            ctrl.IsBusy = newValue;
        });

        /// <summary>
        /// Respresents the command that is fired to ask the view model to load additional data bound collection.
        /// </summary>
        public static readonly BindableProperty LoadMoreInfiniteScrollCommandProperty = BindableProperty.Create<AwesomeListView, ICommand>(bp => bp.LoadMoreInfiniteScrollCommand, default(ICommand));

        /// <summary>
        /// Respresents the command that is fired to ask the view model to load additional data bound collection.
        /// </summary>
        public static readonly BindableProperty LoadMoreItemsFooterCommandProperty = BindableProperty.Create<AwesomeListView, ICommand>(bp => bp.LoadItemsMoreFooterCommand, default(ICommand));

        #endregion

        #region Propertries

        /// <summary>
        /// Gets or sets the property value that defines whether the list has reached the 
        /// end of the items source thereby declaring its not possible to load more itmes...
        /// </summary>
        public bool IsLoadMoreItemsPossible
        {
            get { return (bool)GetValue(IsLoadMoreItemsPossibleProperty); }
            set
            {
                SetValue(IsLoadMoreItemsPossibleProperty, value);

                // Setting the value to button if it is available
                if (btn_LoadMoreItems != null)
                {
                    btn_LoadMoreItems.IsEnabled = value;

                    // Setting grey color for the button background in disabled state
                    if (!btn_LoadMoreItems.IsEnabled)
                    {
                        if (Device.OS == TargetPlatform.Android || Device.OS == TargetPlatform.iOS)
                        {
                            btn_LoadMoreItems.BackgroundColor = Color.FromHex("#C0C0C0");
                            btn_LoadMoreItems.BackgroundColor = Color.FromHex("#C0C0C0");
                        }
                    }
                    else
                    {
                        if (Device.OS == TargetPlatform.Android || Device.OS == TargetPlatform.iOS)
                        {
                            btn_LoadMoreItems.BackgroundColor = Color.FromHex("#0066FF");
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the property value that defines whether listview is busy loading
        /// items in the background or not
        /// </summary>
        public bool IsBusy 
        {
            get { return (bool)GetValue(IsBusyProperty); }
            set
            {
                SetValue(IsBusyProperty, value);

                // Setting the value to ActivityIndicator
                if (ActivityIndicator_LoadingContacts != null)
                {
                    ActivityIndicator_LoadingContacts.IsVisible = value;
                }
            }
        }

        #endregion

        #region Commands

        /// <summary>
        /// <summary>
        /// Gets or sets the command binding that is called whenever the listview is reaching the bottom items area
        /// </summary>
        public ICommand LoadMoreInfiniteScrollCommand
        {
            get { return (ICommand)GetValue(LoadMoreInfiniteScrollCommandProperty); }
            set { SetValue(LoadMoreInfiniteScrollCommandProperty, value); }
        }

        /// <summary>
        /// <summary>
        /// Gets or sets the command binding that is called whenever user clicks on the 'Load More' footer button in the ListView
        /// </summary>
        public ICommand LoadItemsMoreFooterCommand
        {
            get { return (ICommand)GetValue(LoadMoreItemsFooterCommandProperty); }
            set { SetValue(LoadMoreItemsFooterCommandProperty, value); }
        }

        #endregion
    }
}

 

Alright, I shall discuss some of it’s added awesomeness from one after the other…

Constructor – As you can see above in our  AwesomeListView’s constructor I have defined a boolean parameter, which defines whether you need to use the ListView with the infinite scrolling enabled ? or whether you want to use the ListView with the Load More footer button enabled. This is very easy to use based up on your choice… 😉 When you pass in true it will enable the button and add it to the footer of the listview, along with its button clicks and commands. If not it will use the infinite scrolling feature.

UI Control Events – There are two event handlers, btn_LoadMoreItems_Clicked is for handling the click event of the footer button and the next one AwesomeListView_ItemAppearing is for handling the infinite scrolling. Inside that we have the logic for checking the appearance of the last item in the listview, and based on that the Load more command is fired. Also you may have noticed that it’s checking for a boolean value inside the event, which is to check whether the datasource has the capability to provide more items for the ListView to display. This can also be externally wired up by the ViewModel, and it’s very useful because the ListView won’t be wasting anytime firing up unnecessary data loading calls to the viewmodel when the datasource has no more data to provide.

Bindable Properties – We will be using those Bindable Propoerties to wire up the necessary functionality of this ListView to the outside code. IsLoadMoreItemsPossibleProperty defines whether it’s possible to load more data to the listview or not, based on the values provided by the ViewModel and IsBusyProperty is for defining whether the ListView is busy loading data in the background. And then comes the LoadMoreInfiniteScrollCommandProperty and LoadMoreItemsFooterCommandProperty, which are the Command Properties you could use for binding the ListView commands whether you need to call them based on infinite scroll or from the footer button command. You need to use the command property upon your  choice whether you need the infinite scroll listview or the footer button enabled listview. 😉

Propertries – I have defined a IsLoadMoreItemsPossible property which defines whether its possible to load more items from the data source in the viewmodel. This could be wired up through the above explained bindable property. There you may have noticed that in the setter method I’m setting the value directly to the footer button’s enable property, so that when the ViewModel informs the listview there are no more items to load in the data source, then the Footer load more items button will be disabled automatically. 😀 Then we have the IsBusy property which denotes whether the ListView is busy (actually the ViewModel) loading data from the background service or from the datasource to the UI. This is also used to make visible or hide the ActivityIndicator based on the passed in value of the ViewModel.

CommandsLoadMoreInfiniteScrollCommand and LoadItemsMoreFooterCommand, These are the Commands that will be used for loading data based on whether you have chosen the infinite scroll listview or the footer button enabled listview. These commands will be communicating through the bindable properties I have described above.

How to ?

Here is how you could use this in your own application if you ever find it confusing to implement this AwesomeListView… 😉

// Pass in the parameter defining whether you need the Infinite scroll or load more footer enabled
AwesomeListView ListView_Contacts = new AwesomeListView(true);

// Whatever your item template
var ListItemTemplate = new DataTemplate(typeof(TextCell));
ListItemTemplate.SetBinding(TextCell.TextProperty, "Name");
ListItemTemplate.SetBinding(TextCell.DetailProperty, "Phone");

// Setting the bindings for the AwesomeListView from your ViewModel as you please..
ListView_Contacts.SetBinding(AwesomeListView.ItemsSourceProperty, "ContactsList");
ListView_Contacts.SetBinding(AwesomeListView.SelectedItemProperty, "SelectedContact");
ListView_Contacts.SetBinding(AwesomeListView.IsEnabledProperty, "IsFree");
ListView_Contacts.SetBinding(AwesomeListView.IsBusyProperty, "IsBusy");
ListView_Contacts.SetBinding(AwesomeListView.IsLoadMoreItemsPossibleProperty, "IsLoadMoreEnabled");
ListView_Contacts.ItemTemplate = ListItemTemplate;

ListView_Contacts.SetBinding(AwesomeListView.LoadMoreItemsFooterCommandProperty, "LoadMoreContactsCommand");

 

Now how about you wanted to use the infinite scrolling functionality in our AwesomeListView ? It’s quite simple enough…

// Pass in the parameter defining whether you need the Infinite scroll or load more footer enabled
AwesomeListView ListView_Contacts = new AwesomeListView(false);

// Setting the bindings for the AwesomeListView from your ViewModel as you please..
ListView_Contacts.SetBinding(AwesomeListView.LoadMoreInfiniteScrollCommandProperty, "LoadMoreContactsCommand");

 

Change the constructor parameter to false and wire up the LoadMoreInfiniteScrollCommandProperty to your ViewModel. 😀

Here’s some screenshots of our AwesomeListView in action…

Untitled design

Anyhow I shall write another complete article along with a full example implementation of my AwesomeListView according to the MVVM pattern. Stay tuned fellas ! 😀

Well there it goes folks, hope this post was helpful for you and prolly saved you a lot of time if you were ever intrigued by the same situation I went through… 🙂 Please share this among other developers and you may save another developer’s time as well… 😉

Cheers ! Stay Awesome ^_^ !