Appearance in Xamarin ListView (SfListView)
15 Jan 202424 minutes to read
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()
};
}
}
Download the entire source code from GitHub here.
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;
Navigate across views (like TabView)
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.
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.
Item size
The SfListView
allows customizing the size of items by setting the ItemSize property. The default value of this property is 40d
. 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. ForHorizontal
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)
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;
});
}
}
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.
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" HasShadow="False">
<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.
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.
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="DynamicHeight" 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)
{
var tappedItemData = obj as Contact;
if (tappedItem != null && tappedItem.IsVisible)
{
tappedItem.IsVisible = false;
}
if (tappedItem == tappedItemData)
{
tappedItem = null;
return;
}
tappedItem = tappedItemData;
tappedItem.IsVisible = true;
}
#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.
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}"
AutoFitMode="Height">
</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
andSfListView
loaded with same row and column, you need to setInputTransparent
asTrue
toSfBusyindicator
in order to pass touch interaction toSfListView
in iOS platform.
Download the entire source code from GitHub here.
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.
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.
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;
}
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.
Right to left(RTL)
SfListView
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 theHorizontalOptions
toStartAndExpand
in Label.
Limitations
-
SfListView
does not support the right-to-left(RTL) direction when SfListView.Orientation isHorizontal
.
NOTE
You can refer to our Xamarin ListView feature tour page for its groundbreaking feature representations. You can also explore our Xamarin.Forms ListView example to know how to render set of data items with Xamarin.Forms views or custom templates.
See also
How to set background color alternatively in Xamarin.Forms ListView (SfListView)
How to work with Material Visual for custom ListView in Xamarin.Forms (SfListView)
How to display URI images in Xamarin.Forms ListView (SfListView)
How to change selected image in Xamarin.Forms ListView (SfListView)
How to handle click action with tap command in Xamarin.Forms ListView (SfListView)