View Appearance

The SfListView allows customizing appearance of the underlying data, and provides different functionalities to the end-user.

Item template

A template can be used to present the data in a way that makes sense for the application by using different controls. SfListView allows customizing appearance of view by setting the ItemTemplate property.

Data template selector

The SfListView allows customizing appearance of each item with different templates based on specific constraints by using the DataTemplateSelector. You can choose a DataTemplate for each item at runtime based on the value of data-bound property using DataTemplateSelector.

Here, an ItemsCacheLimit property maintains number of items reusing in the view. This cache limit is used to create and reuse the ListViewItem if different templates are used in DataTemplateSelector for better scrolling performance. Based on this value, SfListView creates number of ListViewItem for different templates in the view if new template is created while scrolling, and reuses it if same template is used for improving the scrolling performance.

Create a data template selector

Create custom class that inherits from DataTemplateSelector, and override the OnSelectTemplate method to return the DataTemplate for that item. At runtime, the SfListView invokes the OnSelectTemplate method for each item and passes the data object as parameter.

class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector
{

   private readonly DataTemplate incomingDataTemplate;
   private readonly DataTemplate outgoingDataTemplate;

   public MyDataTemplateSelector()
   {
      this.incomingDataTemplate = new DataTemplate(typeof(IncomingViewCell));
      this.outgoingDataTemplate = new DataTemplate(typeof(OutgoingViewCell));      
   }

   protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
   {
      var message = item as Message;
      if (message == null)
         return null;
      return message.IsIncoming ? this.incomingDataTemplate : this.outgoingDataTemplate;
   }

}

Applying the data template selector

Assign custom DataTemplateSelector to the ItemTemplate of the SfListView either in XAML or C#.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DataTemplateSelector.MainPage"
             xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
             xmlns:local="clr-namespace:DataTemplateSelector;assembly=DataTemplateSelector">
  <ContentPage.Resources>
    <ResourceDictionary>
      <local:MyDataTemplateSelector x:Key="MessageTemplateSelector" />
    </ResourceDictionary>
  </ContentPage.Resources>
  <Grid>
    <syncfusion:SfListView x:Name="ListView"
                           ItemTemplate="{StaticResource MessageTemplateSelector}"
                           ItemsSource="{Binding Messages}"
                           ItemSize="100">
    </syncfusion:SfListView>
  </Grid>
</ContentPage>
public class MainPageCs : ContentPage
{
   public MainPageCs()
   {
      var viewModel = new MainPageViewModel();
      BindingContext = viewModel;
      Content = new SfListView()
      {
          ItemSize = 100,
          ItemsSource = viewModel.Messages,
          ItemTemplate = new MyDataTemplateSelector()
      };
   }
}

You can also download the entire source code of this demo here.

Xamarin.Forms listview with item template customize

Horizontal ListView

The SfListView allows you to layout every item in the SfListView.ItemsSource property either in vertical or horizontal orientation by setting the SfListView.Orientation. The default orientation is Vertical.

<syncfusion:SfListView x:Name="listView" Orientation="Horizontal" />
listView.Orientation = Orientation.Horizontal;

Xamarin.Forms listview items in horizontal orientation

The SfListView allows you to layout the items like TabView in the horizontal direction by setting the Orientation property as Horizontal using the ItemTapped event. It brings any desired view above the horizontal list as follows.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
    <ContentPage.Content>
        <Grid x:Name="GridView">
            <Label Text="Tap image to expand"/>
            <Grid>
                <Image Source="{Binding ContactImage}" />
                <Label Text="{Binding ContactName}" />
                <Label Text="{Binding ContactNumber}" />
            </Grid>
            <syncfusion:SfListView x:Name="listView" ItemTapped="list_ItemTapped" ItemSize="70" ItemsSource="{Binding ContactsInfo}">
                <syncfusion:SfListView.ItemTemplate>
                    <DataTemplate x:Name="ItemTemplate"  x:Key="ItemTemplate" >
                        <ViewCell>
                            <ViewCell.View>
                                    <Image Source="{Binding ContactImage}" />
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </syncfusion:SfListView.ItemTemplate>
            </syncfusion:SfListView>
        </Grid>
    </ContentPage.Content>
</ContentPage>
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        list.BindingContext = new ContactsViewModel();

        var grid = new Grid();
        var label = new Label();
        label.Text = "Tap image to expand";
        var grid1 = new Grid();
        var image = new Image();
        image.SetBinding(Image.SourceProperty, new Binding("ContactImage"));
        var label1 = new Label();
        label.SetBinding(Label.TextProperty, new Binding("ContactName"));
        var label2 = new Label();
        label1.SetBinding(Label.TextProperty, new Binding("ContactNumber"));
        grid1.Children.Add(image);
        grid1.Children.Add(label1);
        grid1.Children.Add(label2);

        var listView = new SfListView();
        ContactsViewModel contactsViewModel = new ContactsViewModel();
        listView.ItemsSource = contactsViewModel.ContactsInfo;
        listView.ItemSize = 70;
        listView.ItemTapped += ListView_ItemTapped;
        listView.ItemTemplate = new DataTemplate(() =>
        {
            var viewCell = new ViewCell();
            var image1 = new Image();
            image1.SetBinding(Image.SourceProperty, new Binding("ContactImage"));
            viewCell.View = image1;
            return viewCell;
        });

        grid.Children.Add(label);
        grid.Children.Add(grid1);
        grid.Children.Add(listView);

    }

    private void list_ItemTapped(object sender, Syncfusion.ListView.XForms.ItemTappedEventArgs e)
    {
        GridView.BindingContext = e.ItemData;
    }
}

Download the entire source code from GitHub here.

Xamarin.Forms listview with tabview

Horizontal list inside vertical list

The SfListView allows you to layout the items in horizontal list inside the vertical list. You can load the nested SfListView by customizing the ItemTemplate of outer SfListView.

You should define the size for each inner SfListView or set the AutoFitMode of inner SfListView as Height, and define the ItemSize for outer SfListView.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
  <ContentPage.BindingContext>
    <local:ListViewModel x:Name="viewModel"/>
  </ContentPage.BindingContext>
    <Grid>
        <syncfusion:SfListView x:Name="listView" ItemsSource="{Binding OuterList}" ItemSize="100">
            <syncfusion:SfListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Label Text="{Binding Label}" />
                        <syncfusion:SfListView ItemsSource="{Binding InnerList}" ItemSize="100" Orientation="Horizontal">
                            <syncfusion:SfListView.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Image Source="{Binding Image}"/>
                                    </Grid>
                                </DataTemplate>
                            </syncfusion:SfListView.ItemTemplate>
                        </syncfusion:SfListView>
                    </Grid>
                </DataTemplate>
            </syncfusion:SfListView.ItemTemplate>
        </syncfusion:SfListView>
    </Grid>
</ContentPage>
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        var grid = new Grid();
        var label1 = new Label();
        label.SetBinding(Label.TextProperty, new Binding("Label"));
        var listView = new SfListView();
        listView.ItemsSource = OuterList;
        listView.ItemSize = 100;
        listView.ItemTemplate = new DataTemplate(() =>
        {
            var InnerListView = new SfListView();
            InnerListView.ItemSize = 100;
            InnerListView.ItemsSource = InnerList;
            InnerListView.Orientation = Orientation.Horizontal;
            listView.ItemTemplate = new DataTemplate(() =>
            {
                var grid1 = new Grid();
                var image = new Image();
                image.SetBinding(Image.SourceProperty, new Binding("Image"));
                grid1.Children.Add(image);
            }
            
            return InnerListView;
        });

        grid.Children.Add(label1);
        grid.Children.Add(listView);
    }

}

Download the entire source code from GitHub here.

Vertical listview with horizontal items

Item size

The SfListView allows customizing the size of items by setting the ItemSize property. The default value of this property is 40. This property can be customized at runtime.

<syncfusion:SfListView x:Name="listView" ItemSize="60" />
listView.ItemSize = 60;

NOTE

For vertical orientation, the item size is considered as height. For horizontal orientation, it will be considered as width.

Item spacing

The SfListView allows specifying space between each item in the list by setting the ItemSpacing property. Generate the space around the item. The default value of this property is 0. This property can be customized at runtime.

<syncfusion:SfListView x:Name="listView" ItemSpacing="5,0,0,0" />
listView.ItemSpacing = new Thickness(5, 0, 0, 0)

Spacing between items in listview

Alternate row styling

The SfListView allows applying alternate row styling for items by finding the index of the underlying object using IValueConverter.

<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:IndexToColorConverter x:Key="IndexToColorConverter"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <syncfusion:SfListView x:Name="listView" ItemsSource="{Binding Items}" ItemSize="50">
            <syncfusion:SfListView.ItemTemplate>
                <DataTemplate>
                    <Grid BackgroundColor="{Binding .,Converter={StaticResource IndexToColorConverter},ConverterParameter={x:Reference Name=listView}}">
                        <Label Text="{Binding ContactName}" />
                        <Label Text="{Binding ContactNumber}" />
                    </Grid>
                </DataTemplate>
            </syncfusion:SfListView.ItemTemplate>
        </syncfusion:SfListView>
    </ContentPage.Content>
</ContentPage>
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        ContactsViewModel viewModel = new ContactsViewModel();
        var listView = new SfListView();
        listView.ItemsSource = viewModel.Items;
        listView.ItemSize = 50;
        listView.ItemTemplate = new DataTemplate(() =>
        {
            var grid = new Grid();
            var label1 = new Label();
            label1.SetBinding(Label.TextProperty, new Binding("ContactName"));
            var label2 = new Label();
            label2.SetBinding(Label.TextProperty, new Binding("ContactNumber"));
            grid.SetBinding(Grid.BackgroundColorProperty, new Binding(".", BindingMode.Default, new IndexToColorConverter(), listView));

            return grid;
        });
    }
}
  • c#
  • public class IndexToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var listview = parameter as SfListView;
            var index = listview.DataSource.DisplayItems.IndexOf(value);
    
            if (index % 2 == 0)
                return Color.LightGray;
            return Color.Aquamarine;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
        }
    }

    Download the entire source code from GitHub here.

    Alternate row style in listview

    Rounded corner on items

    The SfListView allows customizing the item appearance like rounded corner by using the Frame layout in the ItemTemplate property. By defining the CornerRadius property of frame layout, you can perform the rounded corner for items.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
        <ContentPage.Content>
            <syncfusion:SfListView x:Name="listView" ItemSize="60" ItemsSource="{Binding customerDetails}">
                <syncfusion:SfListView.ItemTemplate>
                    <DataTemplate>
                        <Frame x:Name="frame" CornerRadius="10" >
                            <StackLayout>
                                    <Label Text="{Binding ContactName}" />
                                    <Label Text="{Binding ContactNumber}" />
                                    <Label Text="{Binding ContactType}" />
                            </StackLayout>
                        </Frame>
                    </DataTemplate>
                </syncfusion:SfListView.ItemTemplate>
            </syncfusion:SfListView>
        </ContentPage.Content>
    </ContentPage>
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
    
            var listView = new SfListView();
            listView.ItemsSource = customerDetails;
            listView.ItemSize = 60;
            listView.ItemTemplate = new DataTemplate(() =>
            {
                var frame = new Frame();
                frame.CornerRadius = 10;
                var stackLayout = new StackLayout();
                var label1 = new Label();
                label.SetBinding(Label.TextProperty, new Binding("ContactName"));
                var label2 = new Label();
                label.SetBinding(Label.TextProperty, new Binding("ContactName"));
                var label3 = new Label();
                label1.SetBinding(Label.TextProperty, new Binding("ContactType"));
                stackLayout.Children.Add(label1);
                stackLayout.Children.Add(label2);
                stackLayout.Children.Add(label3);
                frame.Children.Add(stackLayout);
    
                return frame;
            });
        }
    }

    Download the entire source code from GitHub here.

    Rounded corners on items in listview

    Drop shadow effect on items

    The SfListView allows customizing the item appearance like shadow effect for items by setting the shadow property of frame as true in ItemTemplate property.

    NOTE

    Define the frame within any view inside ItemTemplate with around some margin.

    <ContentPage  xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
        <ContentPage.Content>
            <syncfusion:SfListView x:Name="listView" ItemSize="60" ItemsSource="{Binding customerDetails}">
                <syncfusion:SfListView.ItemTemplate>
                    <DataTemplate>
                        <Grid Padding="2" Margin="2" >
                            <Frame x:Name="frame" HasShadow="True" Padding="2" Margin="2">
                                <StackLayout>
                                    <Label Text="{Binding ContactName}" /> 
                                    <Label Text="{Binding ContactNumber}" />
                                    <Label Text="{Binding ContactType}" />
                                </StackLayout>
                            </Frame>
                        </Grid>
                    </DataTemplate>
                </syncfusion:SfListView.ItemTemplate>
            </syncfusion:SfListView>
        </ContentPage.Content>
    </ContentPage>
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
    
            var listView = new SfListView();
            listView.ItemsSource = customerDetails;
            listView.ItemSize = 60;
            listView.ItemTemplate = new DataTemplate(() =>
            {
                var grid = new Grid();
                grid.Padding = 2;
                grid.Margin = 2;
                var frame = new Frame();
                frame.Padding = 2;
                frame.Margin = 2;
                frame.HasShadow = "True";
                var stackLayout = new StackLayout();
                var label1 = new Label();
                label.SetBinding(Label.TextProperty, new Binding("ContactName"));
                var label2 = new Label();
                label.SetBinding(Label.TextProperty, new Binding("ContactName"));
                var label3 = new Label();
                label1.SetBinding(Label.TextProperty, new Binding("ContactType"));
                stackLayout.Children.Add(label1);
                stackLayout.Children.Add(label2);
                stackLayout.Children.Add(label3);
                frame.Children.Add(stackLayout);
                grid.Children.Add(frame);
    
                return grid;
            });
        }
    }

    Download the entire source code from GitHub here.

    Frame shadow effect in listview

    ListViewItem customization

    The SfListView allows customizing the ListViewItem based on the ItemType. To customize the Header, Footer, GroupHeader, LoadMore, and ListViewItem follow the code example.

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            this.listView.ItemGenerator = new ItemGeneratorExt(this.listView);
        }
    }

    Extension class for ItemGenerator

    public class ItemGeneratorExt : ItemGenerator
    {
        public SfListView listView;
    	
        public ItemGeneratorExt(SfListView listView) : base(listView)
        {
            this.listView = listView;
        }
    
        protected override ListViewItem OnCreateListViewItem(int itemIndex, ItemType type, object data = null)
        {
            if (type == ItemType.Header)
                return new HeaderItemExt(this.listView);
            else if (type == ItemType.Footer)
                return new FooterItemExt(this.listView);
            else if (type == ItemType.GroupHeader)
                return new GroupHeaderItemExt(this.listView);
            else if (type == ItemType.LoadMore)
                return new LoadMoreItemExt(this.listView);
            else if (type == ItemType.Record)
                return new ListViewItemExt(this.listView);
            return base.OnCreateListViewItem(itemIndex, type, data);
        }
    }

    Extension class for HeaderItem

    public class HeaderItemExt : HeaderItem
    {
        private SfListView listView;
    
        public HeaderItemExt(SfListView listView)
        {
            this.listView = listView
        }
    
        protected override void OnItemAppearing()
        {
            base.OnItemAppearing();
            this.BackgroundColor = Color.Yellow;
        }
    }

    Extension class for FooterItem

    public class FooterItemExt : FooterItem
    {
        private SfListView listView;
    
        public FooterItemExt(SfListView listView)
        {
            this.listView = listView
        }
    
        protected override void OnItemAppearing()
        {
            base.OnItemAppearing();
            this.BackgroundColor = Color.Yellow;
        }
    }

    Extension class for GroupHeaderItem

    public class GroupHeaderItemExt : GroupHeaderItem
    {
        private SfListView listView;
    
        public GroupHeaderItemExt(SfListView listView)
        {
            this.listView = listView
        }
    
        protected override void OnItemAppearing()
        {
            base.OnItemAppearing();
            this.BackgroundColor = Color.Yellow;
        }
    }

    Extension class for LoadMoreItem

    public class LoadMoreItemExt : LoadMoreItem
    {
        private SfListView listView;
    
        public LoadMoreItemExt(SfListView listView)
        {
            this.listView = listView
        }
    
        protected override void OnItemAppearing()
        {
            base.OnItemAppearing();
            this.BackgroundColor = Color.Yellow;
        }
    }

    Extension class for ListViewItem

    public class ListViewItemExt : ListViewItem
    {
        private SfListView listView;
    
        public ListViewItemExt(SfListView listView)
        {
            this.listView = listView
        }
    
        protected override void OnItemAppearing()
        {
            base.OnItemAppearing();
            this.BackgroundColor = Color.Yellow;
        }
    }

    Accordion view

    The SfListView supports accordion view to display a list of items. Each item can be expanded or stretched to reveal the content associated with that item. There can be zero expanded items, exactly one item, or more than one item can be expanded at a time depending on the configuration.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
      <ContentPage.Behaviors>
        <local:SfListViewAccordionBehavior />
      </ContentPage.Behaviors>
      <ContentPage.Content>
        <Grid x:Name="mainGrid" BackgroundColor="#F0F0F0" Padding="4">
          <syncfusion:SfListView x:Name="listView" AutoFitMode="Height" SelectionMode ="None" IsScrollBarVisible="False" ItemSpacing="0">
            <syncfusion:SfListView.ItemTemplate>
              <DataTemplate>
                <ViewCell>
                  <ViewCell.View>
                    <Grid Padding="2" Margin="1" BackgroundColor="#F0F0F0" >
                      <Frame x:Name="frame" CornerRadius="2" Padding="1" Margin="1" OutlineColor="White">
                        <Grid VerticalOptions="FillAndExpand" BackgroundColor="White" HorizontalOptions="FillAndExpand">
                          <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                          </Grid.RowDefinitions>
                          <Grid x:Name="grid" >
                            <Grid.RowDefinitions>
                              <RowDefinition Height="60" />
                            </Grid.RowDefinitions>
                            <Grid RowSpacing="0">
                              <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="60" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="50" />
                              </Grid.ColumnDefinitions>
                              <Image Grid.Row="0" Grid.Column="0" Source="{Binding ContactImage}" VerticalOptions="Center"/>
                              <Grid Grid.Row="0" Grid.Column="1" VerticalOptions="CenterAndExpand">
                                <Grid.RowDefinitions>
                                  <RowDefinition Height="*" />
                                  <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Label Grid.Row="0" LineBreakMode="NoWrap" TextColor="#474747" Text="{Binding ContactName}" />
                                <Label Grid.Row="1" TextColor="#474747" LineBreakMode="NoWrap" Text="{Binding CallTime}" />
                              </Grid>
                              <Grid Grid.Row="0" Grid.Column="2" HorizontalOptions="Center" VerticalOptions="Center">
                                <Image Source="{Binding PhoneImage}" HeightRequest="20" WidthRequest="20" HorizontalOptions="Center" VerticalOptions="Center" />
                              </Grid>
                            </Grid>
                          </Grid>
                          <Grid IsVisible="{Binding IsVisible, Mode=TwoWay}" ColumnSpacing="0" RowSpacing="0" Grid.Row="1" BackgroundColor="White"
                                HorizontalOptions="FillAndExpand" Padding="5" VerticalOptions="FillAndExpand">
                            <Grid.RowDefinitions>
                              <RowDefinition Height="1" />
                              <RowDefinition Height="40" />
                              <RowDefinition Height="40" />
                              <RowDefinition Height="40" />
                              <RowDefinition Height="40" />
                              <RowDefinition Height="40" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions >
                              <ColumnDefinition Width="50" />
                              <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <BoxView Grid.Row="0" Grid.Column="0" BackgroundColor="LightGray" />
                            <Image Grid.Row="1" Grid.Column="0" Source="{Binding NewContact}"  />
                            <Image Grid.Row="2" Grid.Column="0" Source="{Binding AddContact}" />
                            <Image Grid.Row="3" Grid.Column="0" Source="{Binding SendMessage}"  />
                            <Image Grid.Row="4" Grid.Column="0" Source="{Binding BlockSpan}"  />
                            <Image Grid.Row="5" Grid.Column="0" Source="{Binding CallDetails}" />
                            <BoxView Grid.Row="0" Grid.Column="1" BackgroundColor="LightGray" />
                            <Label Grid.Row="1" Grid.Column="1" Text="Create new contact" TextColor="#000000" />
                            <Label Grid.Row="2" Grid.Column="1" Text="Add to a contact" TextColor="#000000"/>
                            <Label Grid.Row="3" Grid.Column="1" Text="Send a message" TextColor="#000000" />
                            <Label Grid.Row="4" Grid.Column="1" Text="Block/report Spam" TextColor="#000000" />
                            <Label Grid.Row="5" Grid.Column="1" Text="Call details" TextColor="#000000" />
                          </Grid>
                        </Grid>
                      </Frame>
                    </Grid>
                  </ViewCell.View>
                </ViewCell>
              </DataTemplate>
            </syncfusion:SfListView.ItemTemplate>
          </syncfusion:SfListView>
        </Grid>
      </ContentPage.Content>
    </ContentPage>

    Accordion view can be displayed by defining two different ItemTemplates. The ItemTemplates can be enabled or disabled in the ItemTapped event.

    internal class SfListViewAccordionBehavior : Behavior<ContentPage>
    {
        #region Fields
    
        private Contact tappedItem;
        private Syncfusion.ListView.XForms.SfListView listview;
        private AccordionViewModel AccordionViewModel;
    
        #endregion
    
        #region Properties
        public SfListViewAccordionBehavior()
        {
            AccordionViewModel = new AccordionViewModel();
        }
    
        #endregion
    
        #region Override Methods
    
        protected override void OnAttachedTo(ContentPage bindable)
        {
            listview = bindable.FindByName<Syncfusion.ListView.XForms.SfListView>("listView");
            listview.ItemsSource = AccordionViewModel.ContactsInfo;
            listview.ItemTapped += ListView_ItemTapped;
        }
    
        #endregion
    
        #region Private Methods
        using Syncfusion.ListView.XForms.Control.Helpers;
        private void ListView_ItemTapped(object sender, Syncfusion.ListView.XForms.ItemTappedEventArgs e)
        {
            if (tappedItem != null && tappedItem.IsVisible)
            {
                var previousIndex = listview.DataSource.DisplayItems.IndexOf(tappedItem);
    
                tappedItem.IsVisible = false;
    
                if (Device.RuntimePlatform != Device.macOS)
                    Device.BeginInvokeOnMainThread(() => { listview.RefreshListViewItem(previousIndex, previousIndex, false); });
            }
    
            if (tappedItem == (e.ItemData as Contact))
            {
                if (Device.RuntimePlatform == Device.macOS)
                {
                    var previousIndex = listview.DataSource.DisplayItems.IndexOf(tappedItem);
                    Device.BeginInvokeOnMainThread(() => { listview.RefreshListViewItem(previousIndex, previousIndex, false); });
                }
    
                tappedItem = null;
                return;
            }
    
            tappedItem = e.ItemData as Contact;
            tappedItem.IsVisible = true;
    
            if (Device.RuntimePlatform == Device.macOS)
            {
                var visibleLines = this.listview.GetVisualContainer().ScrollRows.GetVisibleLines();
                var firstIndex = visibleLines[visibleLines.FirstBodyVisibleIndex].LineIndex;
                var lastIndex = visibleLines[visibleLines.LastBodyVisibleIndex].LineIndex;
                Device.BeginInvokeOnMainThread(() => { listview.RefreshListViewItem(firstIndex, lastIndex, false); });
            }
            else
            {
                var currentIndex = listview.DataSource.DisplayItems.IndexOf(e.ItemData);
                Device.BeginInvokeOnMainThread(() => { listview.RefreshListViewItem(currentIndex, currentIndex, false); });
            }
        }
    
        #endregion
    
        protected override void OnDetachingFrom(ContentPage bindable)
        {
            listview.ItemTapped -= ListView_ItemTapped;           
        }
    }

    The IsVisible model property which is bound to the second template will be enabled when tapping the item and disabled when tapping again the same item.

    Download the entire source code from GitHub here.

    Xamarin.Forms listview with Accordion

    show busy indicator on list view

    The SfListView allows displaying the SfBusyIndicator when loading the bounded items. The busy indicator can be enabled and disabled by using IsBusy property.

    Create a IsLoading boolean property in view model and bind it to the IsBusy property. By setting the value to IsLoading property, the busy indicator will be enabled and disabled into the view till the items loaded in the SfListView.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
                 xmlns:busyIndicator="clr-namespace:Syncfusion.SfBusyIndicator.XForms;assembly=Syncfusion.SfBusyIndicator.XForms">
        <Grid>
            <syncfusion:SfListView x:Name="listView" 
                                 ItemsSource="{Binding ContactInfo}" 
                                 ItemSize="110">
            </syncfusion:SfListView>
            <busyIndicator:SfBusyIndicator x:Name="busyIndicator" InputTransparent="True"
                                           AnimationType="SingleCircle" 
                                           IsBusy="{Binding IsLoading, Mode=TwoWay}" 
                                           TextColor="Magenta"
                                           ViewBoxWidth="50"
                                           ViewBoxHeight="50"/>
        </Grid>
    </ContentPage>
    public class ViewModel : INotifyPropertyChanged
    {
        private bool isLoading = false;
    
        public bool IsLoading
        {
            get { return isLoading; }
            set
            {
                this.isLoading = value;
                OnPropertyChanged("IsLoading");
            }
        }
    
        private async void GenerateItems()
        {
            IsLoading = true;
            await Task.Delay(5000);
            for (int i = 0; i < 30; i++)
            {
                var contact = new Model(CustomerNames[i], ContactNumber[i]);
                ContactInfo.Add(contact);
            }
            IsLoading = false;
        }
    }

    NOTE

    When both SfBusyIndicator and ListView loaded with same row and column, you need to set InputTransparent as True to SfBusyindicator in order to pass touch interaction to listview in iOS platform.

    Download the entire source code from GitHub here.

    Busy indicator to load listview Loaded listview items

    show busy indicator on list view items

    The SfListView allows displaying an activity indicator for an item when its data is being loaded in the background. To perform this, load both ActivityIndicator and a Button in the same row of a Grid element inside the ItemTemplate of the SfListView. The busy indicator and button can be enabled and disabled by using properties IsButtonVisible and IsIndicatorVisible respectively in the model class.

    public class BookInfo : INotifyPropertyChanged
    {
        private string bookName;
        private string bookDescription;
        public bool isDescriptionVisible;
        public bool isButtonVisible;
        public bool isIndicatorVisible;
    
        public BookInfo()
        {
        }
    
        public string BookName
        {
            get { return bookName; }
            set
            {
                bookName = value;
                OnPropertyChanged("BookName");
            }
        }
    
        public bool IsDescriptionVisible
        {
            get { return isDescriptionVisible; }
            set
            {
                isDescriptionVisible = value;
                OnPropertyChanged("IsDescriptionVisible");
            }
        }
    
        public string BookDescription
        {
            get { return bookDescription; }
            set
            {
                bookDescription = value;
                OnPropertyChanged("BookDescription");
            }
        }
    
        public bool IsButtonVisible
        {
            get { return isButtonVisible; }
            set
            {
                isButtonVisible = value;
                OnPropertyChanged("IsButtonVisible");
            }
        }
    
        public bool IsIndicatorVisible
        {
            get { return isIndicatorVisible; }
            set
            {
                isIndicatorVisible = value;
                OnPropertyChanged("IsIndicatorVisible");
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void OnPropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    Disable the visibility of Description and ActivityIndicator initially while adding items into collection.

    public class BookInfoRepository : INotifyPropertyChanged
    {
        private ObservableCollection<BookInfo> newBookInfo;
        public event PropertyChangedEventHandler PropertyChanged;
    
        public ObservableCollection<BookInfo> NewBookInfo
        {
            get { return newBookInfo; }
            set { this.newBookInfo = value; }
        }
    
        public void OnPropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    
        public BookInfoRepository()
        {
            GenerateNewBookInfo();
        }
    
        private void GenerateNewBookInfo()
        {
            NewBookInfo = new ObservableCollection<BookInfo>();
            NewBookInfo.Add(new BookInfo() { BookName = "Machine Learning Using C#", BookDescription = "You’ll learn several different approaches to applying machine learning", IsIndicatorVisible = false, IsButtonVisible = true, IsDescriptionVisible = false });
            NewBookInfo.Add(new BookInfo() { BookName = "Object-Oriented Programming in C#", BookDescription = "Object-oriented programming is the de facto programming paradigm", IsIndicatorVisible = false, IsButtonVisible = true, IsDescriptionVisible = false });
            NewBookInfo.Add(new BookInfo() { BookName = "C# Code Contracts", BookDescription = "Code Contracts provide a way to convey code assumptions", IsIndicatorVisible = false, IsButtonVisible = true, IsDescriptionVisible = false });
        }
    }

    Bind the bool values for the IsVisible properties to switch between indicator and button while loading the description.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">  
        <ContentPage.BindingContext>
            <local:BookInfoRepository x:Name="ViewModel" />
        </ContentPage.BindingContext>
        <sync:SfListView x:Name="listView" AutoFitMode="Height" BackgroundColor="#d3d3d3" SelectionMode="None" ItemsSource="{Binding NewBookInfo}">
            <sync:SfListView.ItemTemplate>
                <DataTemplate>
                    <Frame HasShadow="True" Margin="5,5,5,0">
                    <Grid Padding="5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="2*" />
                        </Grid.RowDefinitions>
                        <Label Text="{Binding BookName}" FontAttributes="Bold" FontSize="19" />
                        <Button Grid.Row="1" Clicked="Button_Clicked" Text="Load Description" IsVisible="{Binding IsButtonVisible}" HorizontalOptions="Center" VerticalOptions="Center"/>
                        <Label Grid.Row="1" Text="{Binding BookDescription}" FontSize="15" IsVisible="{Binding IsDescriptionVisible}" />
                        <ActivityIndicator Grid.Row="1" IsEnabled="True" IsRunning="True" IsVisible="{Binding IsIndicatorVisible}" />
                    </Grid>
                    </Frame>
                </DataTemplate>
            </sync:SfListView.ItemTemplate>
        </sync:SfListView>
    </ContentPage>

    In the Clicked event of the Button, get the row data from its BindingContext and alter the bool values accordingly.

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    
        private async void Button_Clicked(object sender, EventArgs e)
        {
            var model = ((sender as Button).BindingContext as BookInfo);
            model.IsIndicatorVisible = true;
            model.IsButtonVisible = false;
            await Task.Delay(2000);
            model.IsDescriptionVisible = true;
            model.IsIndicatorVisible = false;
        }
    }

    Download the entire source code from GitHub here.

    Busy indicator to load listview items Loaded listview

    Show busy indicator on list view items using toggle switch

    The SfListView allows to display ActivityIndicator for an item when loading its data in the background. To do this, load both ActivityIndicator and a toggle switch in the same row of a Grid element inside the ItemTemplate of SfListView. The busy indicator and toggle switch can be enabled and disabled by using the IsButtonVisible and IsIndicatorVisible properties respectively in the model class. The ActivityIndicator remains visible when the toggle switch is enabled.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
        <ContentPage.BindingContext>
            <local:ContactInfoRepository x:Name="ViewModel" />
        </ContentPage.BindingContext>
        <syncfusion:SfListView x:Name="listView" AutoFitMode="Height" BackgroundColor="#d3d3d3" SelectionMode="None" ItemsSource="{Binding NewContactInfo}">
            <syncfusion:SfListView.ItemTemplate>
                <DataTemplate>
                    <Frame HasShadow="True" Margin="5,5,5,0">
                    <Grid Padding="5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Label Text="{Binding ContactName}" FontAttributes="Bold" FontSize="19" />
                      <Switch Grid.Row="1" Grid.Column="1" IsVisible="{Binding IsButtonVisible}" IsToggled="{Binding IsChecked}" Toggled="Switch_Toggled"/>
    
                      <Label Grid.Row="1" Text="{Binding ContactNo}" FontSize="15" IsVisible="{Binding IsDescriptionVisible}" />
                        <ActivityIndicator Grid.Row="1" IsEnabled="True" IsRunning="True" IsVisible="{Binding IsIndicatorVisible}" />
                    </Grid>
                    </Frame>
                </DataTemplate>
            </syncfusion:SfListView.ItemTemplate>
        </syncfusion:SfListView>
    </ContentPage>

    In the Toggled event of the switch, get the row data from its BindingContext and alter the Bool values accordingly.

    public partial class MainPage : ContentPage
    {
      private Random random = new Random();
      public MainPage()
      {
         InitializeComponent();
      }
    
      private async void Switch_Toggled(object sender, ToggledEventArgs e)
      {
        var model = ((sender as Switch).BindingContext as ContactInfo);
        if (model.IsChecked == true)
        {
            model.ContactNo = random.Next(100, 400).ToString() + "-" + random.Next(500, 800).ToString() + "-" + random.Next(1000, 2000).ToString();
            model.IsDescriptionVisible = false;
            model.IsIndicatorVisible = true;
            await Task.Delay(2000);
            model.IsDescriptionVisible = true;
            model.IsIndicatorVisible = false;
            model.IsChecked = false;
        }
        else
        {
            model.IsIndicatorVisible = false;
        }
      }
    }

    Download the entire source code from GitHub here.

    Xamarin.Forms listview with switch on Xamarin.Forms listview with switch off

    Item animation on appearing

    The SfListView supports animating the items by using an OnItemAppearing virtual method. It is raised when the items appearing in the view on scrolling, loading, and navigating from one page to another page. To apply the animation effect for items, follow the steps:

    Extension of ItemGenerator

    public class ItemGeneratorExt : ItemGenerator
    {
        public SfListView listView;
    	
        public ItemGeneratorExt(SfListView listView) : base(listView)
        {
            this.listView = listView;
        }
    
        protected override ListViewItem OnCreateListViewItem(int itemIndex, ItemType type, object data = null)
        {
            if (type == ItemType.Record)
                return new ListViewItemExt(this.listView);
            return base.OnCreateListViewItem(itemIndex, type, data);
        }
    }

    Initialize and assign ItemGenerator extension to ListView

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            this.listView.ItemGenerator = new ItemGeneratorExt(this.listView);
        }
    }

    Extension of ListViewItem

    To apply the animation for items while appearing, override the OnItemAppearing method.

    public class ListViewItemExt : ListViewItem
    {
        private SfListView listView;
    
        public ListViewItemExt(SfListView listView)
        {
            this.listView = listView;
            this.PropertyChanged += ListViewItemExt_PropertyChanged; 
        }
    
        private void ListViewItemExt_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
        { 
            if (e.PropertyName == "Visibility") 
            { 
                if (!this.Visibility) 
                    this.AbortAnimation("FadeTo"); 
            } 
        } 
    
        protected override void OnItemAppearing()
        {
            this.Opacity = 0;
            this.FadeTo(1, 400, Easing.SinInOut);
            base.OnItemAppearing();
        }
    }

    Here FadeTo animation is applied for ListViewItem, when comes in the view.
    Download the entire source code from GitHub here.

    Xamarin.Forms listview with animation

    Right to left(RTL)

    ListView supports to change the flow of text to the right-to-left direction by setting the FlowDirection property. ListView supports RTL in Xamarin.Forms version 3.0 and above.

    <ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms">
      <syncfusion:SfListView x:Name="listView"
                     ItemsSource="{Binding Products}"
                     FlowDirection="RightToLeft"/>
    </ContentPage>
    this.FlowDirection = FlowDirection.RightToLeft;

    In UWP platform, the ScrollView is not changed when RTL is enabled (framework issue). To overcome this issue, set the FlowDirection property in constructor of MainPage in UWP renderer as demonstrated in the following code example.

    public MainPage()
    {
        
        SfListViewRenderer.Init();
        this.FlowDirection = FlowDirection.RightToLeft;
        LoadApplication (new App ());
        
    }

    NOTE

    When a label is loaded in the ItemTemplate, the right-to-left direction is not applied due to the framework issue. It has been reported to the Xamarin team; for more details about this, refer to this link. To overcome this issue, set the HorizontalOptions to StartAndExpand in Label.

    Xamarin.Forms listview with right to left

    Limitations