Xamarin.Forms - Cross-Platform ListView Control

ListView is a view for presenting a list of data, especially the long list that requires scrolling. Xamarin.Forms provides ListView control that can be used for displaying scrollable lists of data. ListView supports context actions and data binding if you are following MVVM (Model View View Model) approach. ListView control is best for homogeneous data.
 
ListView has a number of components to implement the native functionality on each platform.
  • Headers and Footers 
    To display at the beginning and at the end of the list.

  • Groups 
    Data in a ListView can be grouped for easier navigation.

  • Cells 
    Cells represent the row for each data being listed. There are built-in rows and you can even create your own custom rows according to your application's design requirement. 
Those readers who are not familiar with the process of project creation using Visual Studio, can follow the process explained on Xamarin official site
 
The following sample example explains the step by step implementation of a simple ListView Control to display the employee directory with their names and department grouped according to their names alphabetically.
 
Step 1

Create an Employee model class in PCL (Portable Class Library) and set the required properties for an employee.
 
Employee.cs
  1. using System;  
  2. namespace ListViewDemo  
  3. {  
  4.     public class Employee  
  5.     {  
  6.         public string FirstName { getset; }  
  7.         public string LastName { getset; }  
  8.         public string FullName { get { return FirstName + " " + LastName; } }  
  9.         public string Department { getset; }  
  10.     }  
  11. }  
Step 2

Create a static DataSource file which will return a list of static data for the employees to bind in the ListView.
 
DataSource.cs 
  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace ListViewDemo  
  5. {  
  6.     public class DataSource  
  7.     {  
  8.         public static List<Employee> GetList()  
  9.         {  
  10.             var l = new List<Employee>();  
  11.   
  12.             l.Add(new Employee() { FirstName = "Anderson", LastName = "Martin", Department = "Developer Evangelist" });  
  13.             l.Add(new Employee() { FirstName = "Adam", LastName = "Dev", Department = "Web Developer" });  
  14.             l.Add(new Employee() { FirstName = "Bob", LastName = "Harry", Department = "Customer Success Engineer" });  
  15.             l.Add(new Employee() { FirstName = "Brooke", LastName = "Clancy", Department = "Marketing" });  
  16.             l.Add(new Employee() { FirstName = "Bella", LastName = "Jo", Department = "Developer Evangelist" });  
  17.             l.Add(new Employee() { FirstName = "Charlie", LastName = "James", Department = "Director of Education" });  
  18.             l.Add(new Employee() { FirstName = "Carla", LastName = "Buckner", Department = "Product Manager" });  
  19.             l.Add(new Employee() { FirstName = "Dev", LastName = "Anand", Department = "CTO" });  
  20.             l.Add(new Employee() { FirstName = "Fried", LastName = "Hardy", Department = "CEO" });  
  21.             l.Add(new Employee() { FirstName = "Harry", LastName = "Jacob", Department = "COO" });  
  22.             l.Add(new Employee() { FirstName = "Hannah", LastName = "Icaza", Department = "Support" });  
  23.             l.Add(new Employee() { FirstName = "Michael", LastName = "Nikon", Department = "Database" });  
  24.             l.Add(new Employee() { FirstName = "Maria", LastName = "Shara", Department = "HR" });  
  25.             l.Add(new Employee() { FirstName = "Orla", LastName = "Jackson", Department = "Designer" });  
  26.             l.Add(new Employee() { FirstName = "Perry", LastName = "Butler", Department = "HR" });  
  27.             l.Add(new Employee() { FirstName = "Simons", LastName = "Foster", Department = "Developer" });  
  28.             l.Add(new Employee() { FirstName = "Timmy", LastName = "Niklas", Department = "Designer" });  
  29.             l.Add(new Employee() { FirstName = "Utham", LastName = "Nigam", Department = "Accounts" });  
  30.             l.Add(new Employee() { FirstName = "Valerie", LastName = "Xander", Department = "Developer" });  
  31.             l.Add(new Employee() { FirstName = "Zaccheus", LastName = "Bing", Department = "Testing" });  
  32.   
  33.             return l;  
  34.         }  
  35.     }  
  36. }  
Step 3

Create an observable group collection class to group the employees directory according to their First name, alphabetically.
 
ObservableGroupCollection.cs 
  1. using System;  
  2. using System.Collections.ObjectModel;  
  3. using System.Linq;  
  4.   
  5. namespace ListViewDemo  
  6. {  
  7.     public class ObservableGroupCollection<K,T> : ObservableCollection<T>  
  8.     {  
  9.         private readonly K _key;  
  10.   
  11.         public ObservableGroupCollection(IGrouping<K, T> group)  
  12.             : base(group)  
  13.         {  
  14.             _key = group.Key;  
  15.         }  
  16.   
  17.         public K Key  
  18.         {  
  19.             get { return _key; }  
  20.         }  
  21.     }  
  22. }  
To understand the concept and use of observable group collection, refer to this article. 
 
Step 4

Create an XAML View page and bind the employee directory data to the ListView Control. 
 
EmployeeDirectoryView.xaml 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"   
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
  4.              x:Class="ListViewDemo.EmployeeDirectoryView"  
  5.              BackgroundColor="White">  
  6.   
  7.     <ContentPage.Padding>  
  8.         <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />  
  9.     </ContentPage.Padding>  
  10.       
  11.     <ContentPage.Content>  
  12.         <StackLayout Spacing="0">  
  13.             <ListView x:Name="empListView"  
  14.                 ItemsSource="{Binding}"  
  15.                 GroupShortNameBinding = "{Binding Key}"  
  16.                 GroupDisplayBinding = "{Binding Key}"  
  17.                 IsGroupingEnabled = "true"                    
  18.                 HasUnevenRows="True"  
  19.                 SeparatorVisibility="Default">  
  20.             <ListView.ItemTemplate>  
  21.                 <DataTemplate>  
  22.                     <ViewCell>                                        
  23.                     <StackLayout Spacing="2" Orientation="Vertical">  
  24.                         <Label Text="{Binding FullName}" FontSize="Medium" LineBreakMode="NoWrap" Margin="10,0,0,0"/>  
  25.                         <Label Text="{Binding Department}" FontSize="Small" LineBreakMode="NoWrap" Margin="10,0,0,0"/>  
  26.                     </StackLayout>       
  27.                     </ViewCell>  
  28.                 </DataTemplate>  
  29.             </ListView.ItemTemplate>  
  30.             <ListView.GroupHeaderTemplate>  
  31.                 <DataTemplate>  
  32.                     <ViewCell Height="23">  
  33.                         <StackLayout BackgroundColor="#808080">  
  34.                             <Label Text="{Binding Key}"  
  35.                                    TextColor="White"  
  36.                                    FontSize="Small"  
  37.                                    VerticalOptions="CenterAndExpand"  
  38.                                    Margin="10,0,0,0"/>  
  39.                         </StackLayout>  
  40.                     </ViewCell>  
  41.                 </DataTemplate>  
  42.             </ListView.GroupHeaderTemplate>  
  43.             </ListView>  
  44.         </StackLayout>  
  45.     </ContentPage.Content>  
  46.   
  47. </ContentPage>  
Step 5

Now, from the code behind file of XAML View page, we need to pass the grouped employee directory data to the ListView Control.
 
EmployeeDirectoryView.xaml.cs 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Collections.ObjectModel;  
  4. using System.Linq;  
  5. using Xamarin.Forms;  
  6.   
  7. namespace ListViewDemo  
  8. {  
  9.     public partial class EmployeeDirectoryView : ContentPage  
  10.     {  
  11.         public EmployeeDirectoryView()  
  12.         {  
  13.             InitializeComponent();  
  14.   
  15.             var empList = DataSource.GetList();  
  16.   
  17.             var groupedData =  
  18.                 empList.OrderBy(e => e.FirstName)  
  19.                     .GroupBy(e => e.FirstName[0].ToString())  
  20.                     .Select(e => new ObservableGroupCollection<string, Employee>(e))  
  21.                     .ToList();  
  22.   
  23.             BindingContext = new ObservableCollection<ObservableGroupCollection<string, Employee>>(groupedData);  
  24.         }  
  25.     }  
  26. }  
After following the above implementation steps, you will get the following output screen on Android as well as iOS, as shown below.