Lately, I have been seeing members of the community asking around for custom views for different use cases, so I have decided to make a series of 3 parts, In which I will be creating different custom controls to demonstrate how Xamarin gives us the power to customize and add all the functionality we may need to the basic controls we already have available, giving you the ability complimented with some time to have some thoughts on how to create some really interesting and useful components for your apps.
The Use cases we will be talking about through this series will be the following:
- Endless Scrolling + ItemTapped (ExtendedListView)
- Custom Stepper + Carousel view (SliderView)
- Timeline of Events (TimeLineView)
Our first use case to dive into creating custom controls will be the Endless Scrolling Listview
We will be using some goodies to simplify our work on the sample project:
(The first post of our series might seem a little long, but its just because I want to explain every detail of how we are going to be working and after you get the hang of it you will notice that the other 2 post will be fairly short, so hang in there you got this 😎!)
MVVM is a Development pattern that allows us to isolate really well our code for our app into Views(UI), ViewModels (Business Logic), and Models(Data) to make our app more scalable and easy to work with, it’s pretty simple we are just going to use all of the tools Xamarin Forms already gives us out of the box and define this structure for our project:
To Bind our Page to our corresponding ViewModel we simply need to add the following line to our XAML page:
Fody Property Changed Nugget Package:
Basically allows us to notify out of the box any changes that happen to the properties of our classes, reducing the boilerplate code you need to add yourself otherwise, the setup is pretty simple just add the nugget package to all of your projects > create a XAML file called FodyWeavers with this structure and copy and paste in root of all the projects:
Benefits of this control:
This is a great functionality to add to your listviews if you are loading a large list of data from your backend server, since the bigger the data your app needs to load the longer it will take to actually download on your device.
So imagine you call your server and request the data for the list to display, and it replies to you with 100K Data items, you could say hey at least I don’t need to load them anymore and I have them all locally, yes that true but then you start asking yourself a bunch of worrying questions:
- How long did that operation take to complete and how much data from your user’s plan did you just use just to load a list, imagine doing this each time they go to the screen?
- Was it really worth it when you know that the user device will only be able to show around 10 – 12 data items at a time?
- will he ever go through all the 100k items on a single use of the app?
The short answer is no. . . it’s not worth loading 100k items worth of data each time you access a screen of your app, just to use less than 10% of it each time, its more effective to load the data bit by bit depending on a predetermined size you consider is decent lets say something around 20 – 25 items per call, and if the user needs to load more data make another call to the backend server and request the new items (20 – 25 items) as needed, this greatly improves the data consumption and loading time for your app and listview.
So let’s get to work!🙌☺
To create our custom control to enable us to control the view, react to it, and add extra functionality to it, We will need to know a little about the following topics:
- Bindable Properties
The purpose of bindable properties is to provide a property system that supports data binding, styles, templates, and values set through parent-child relationships. In addition, bindable properties can provide default values, validation of property values, and callbacks that monitor property changes. [More Info Here]
Common samples of bindable properties:
It’s basically a Xamarin.Forms Functionality that allows data bindings to make method calls directly to a ViewModel. [More Info Here]
- Handlings and Raising Events
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a button click, or it could be raised by some other program logic, such as changing a property’s value. The object that raises the event is called the event sender. The event sender doesn’t know which object or method will receive (handle) the events it raises. [More Info Here]
Creating the ExtendedListViewClass
I have decided to call my custom ListView, ExtendedListView you can name it whatever you like but for the sake of this post, this will be the name we will use to refer to this custom view. In this class is where we will be adding all the extra functionality we wish to support on my special listview throughout my app.
Step 1 – Create controls folders and add OUR NEW class file
Since we are going to be creating custom controls in our app’s from now on for our different use cases, it’s always good to keep our project nice and tidy. I personally like to create a new File Directory on the Shared Project (this can also apply to the iOS and Android project if needed), Called “Controls” inside this directory is where I create all my custom controls, your file structure should look like this now:
step 2 – let’s ADD THE CODE FOR OUR custom control
The first thing we want to do is extend from the ListView class since we are going to be creating a custom variation of the ListView Xamarin Forms component:
And now Guys *drumrolls*🥁! we have our very own Custom Listview Controller! :O waoo that was easy? haha. Ok so now to the fun part! we need our new control to do some extra work for us when we use it directly from our XAML, but how can I tell my custom listview what new things I want to support? Well, that is what BindableProperties are for! now that you know about BindableProperties we have the power to tell our custom control from our XAML anything we would like example (Set a command for loading more data, Set a command to get notified if there is a new item appearing on my Listview or if someone taps one of my items, and much more!).
So let’s add all the bindable properties we will need to enable the Endless Scrolling functionality on my control:
As you can see we simply added 2 Bindable Properties that allow us to bind 2 commands to our ViewModel from our control:
- LoadMoreCommandProperty: Binds to a Command and will be in charge of notifying me directly on my ViewModel that we need to load more data from the backend server.
- ItemAppearingCommandProperty: Binds to a Command, will be in charge of notifying me if there’s a new item appearing on the screen, and allows me to react to it on my ViewModel (Just a nice to have if you wish to do something on this scenario in your app).
Structure of our Bindable Properties
STEP 3 – let’s add our event handler
After we have the data we need coming into our Control and the way to notify of any events our control generates with our BindableProperties, the only step left to do is to implement the logic for our new functionality and to do so we will be using EventHandlers, since our functionality is basically: listening to when a new item is appearing on our screen, verifying if this new item is the last item of the data source and if it is, simply load more data from our server!
To do this we add the following code to our control constructor, which basically allows us to attach a listener to our extended listview ItemsAppearing event handler:
We then proceed to create our listener method OnItemAppearing with the logic for each case and launch our LoadMoreCommand so we can get notified on the ViewModel that we need to load more data.
STEP 4 – Adding the business logic to our commands
Great job so far Guys!💪, now that we have our extended listview up and running we only need to react to our commands and load our data in our ViewModel, my recommendation is receiving the results paginated directly from your backend server, allowing you to send to the API endpoint the page you are currently on and the number of items you wish to see, so you can load the new data dynamically while the user scrolls through his screen.
STEP 5 – let’s USE OUR new control
Now we simply need to add our ExtendedListView to our page, to do so we simply add a new namespace which contains the custom views we have created on our Controls folder, after this, we can start using our controls as any other normal view in our XAML page:
Adding ItemTappedCommand to our ExtendedListView
Now that we have our ExtendedListView new functionality working correctly, let’s add another nice to have to our listview which is the ability to receive ItemTapped notifications directly in our ViewModels, with the use of a simple Command Binding, the steps to add this are exactly the same as before so let’s get to work!
Step 1 – CREATE the BINDABLE PROPERTY
STEP 2 – CREATE the EVENT HANDLER
STEP 3 – Adding the business logic to our command
STEP 4 – USING OUR NEW PROPERTY
Ce finito Guys!🎉 now we have an ExtendedListView that allows us to have endless scrolling, and even react directly on our ViewModel to ItemTaps with a single binding, making our app more efficient when we need to load data from our server, but the most important lesson is that we now have the power to play and customize our common Xamarin Controls at our own will and make some really interesting stuff!
Full Source Code for the sample App can be found on my Github Repo [ExtendedListViewExample]
PD: Remember guys common use cases like the one we just coded, may already have solutions made by the community so you don’t need to redo this work over and over, in this particular case there are other alternatives for implementing Endless Scrolling listviews, and there is even a really good plugin that gives support to it, you can find it here Infinite Scrolling Plugin Xamarin, A member from our Xamarin community Houssem Dellai has a great video on his youtube channel where he explains how to use this plugin to implement infinite scrolling on your listviews.
Made with ❤ by Pujols.