List Appearance
Customize ListViews using headers, footers, groups, and variable height cells.
- PDF for offline use:
- Related Samples:
Let us know how you feel about this.
0/250
last updated: 2016-03
ListView has options for controlling the presentation of the overall list, in addition to the underlying ViewCells. Options include:
- Grouping – group items in ListView for easier navigation and improved organization.
- Headers and Footers – display information at the beginning and end of the view that scrolls with the other items.
- Row Separators – show or hide separator lines between items.
- Variable Height Rows – by default all rows are the same height, but this can be changed to allow rows with differing heights to be displayed.
Grouping
Often, large sets of data can become unwieldy when presented in a continuously scrolling list. Enabling grouping can improve the user experience in these cases by better organizing the content and activating platform-specific controls that make navigating data easier.
When grouping is activated for a ListView, a header row is added for each group.
To enable grouping:
- Create a list of lists (a list of groups, each group being a list of elements).
- Set the
ListView'sItemsSourceto that list. - Set
IsGroupingEnabledto true. - Set
GroupDisplayBindingto bind to the property of the groups that is being used as the title of the group. - [Optional] Set
GroupShortNameBindingto bind to the property of the groups that is being used as the short name for the group. The short name is used for the jump lists (rigt-side column on iOS, tile grid on Windows Phone).
Start by creating a class for the groups:
public class PageTypeGroup : List<PageModel>
{
public string Title { get; set; }
public string ShortName { get; set; } //will be used for jump lists
public string Subtitle { get; set; }
private PageTypeGroup(string title, string shortName)
{
Title = title;
ShortName = shortName;
}
public static IList<PageTypeGroup> All { private set; get; }
}
In the above code, All is the list that will be given to our ListView as the
binding source. Title and ShortName are the properties that will be used for group headings.
At this stage, All is an empty list. Add a static constructor so that the list
will be populated at program start:
static PageTypeGroup()
{
List<PageTypeGroup> Groups = new List<PageTypeGroup> {
new PageTypeGroup ("Alfa", "A"){
new PageModel("Amelia", "Cedar", new switchCellPage(),""),
new PageModel("Alfie", "Spruce", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Ava", "Pine", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Archie", "Maple", new switchCellPage(), "grapefruit.jpg")
},
new PageTypeGroup ("Bravo", "B"){
new PageModel("Brooke", "Lumia", new switchCellPage(),""),
new PageModel("Bobby", "Xperia", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Bella", "Desire", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Ben", "Chocolate", new switchCellPage(), "grapefruit.jpg")
}
}
All = Groups; //set the publicly accessible list
}
In the above code we can also call Add on elements of groups,
which are instances of type PageTypeGroup. This is possible because
PageTypeGroup inherits from List<PageModel>. This is an example of the
list of lists pattern noted above.
Here is the XAML for displaying the grouped list:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DemoListView.GroupingViewPage"
<ContentPage.Content>
<ListView x:Name="GroupedView"
GroupDisplayBinding="{Binding Title}"
GroupShortNameBinding="{Binding ShortName}"
IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding Subtitle}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
This results in the following:

Note that we have:
- Set
GroupShortNameBindingto theShortNameproperty defined in our group class - Set
GroupDisplayBindingto theTitleproperty defined in our group class - Set
IsGroupingEnabledto true - Changed the
ListView'sItemsSourceto the grouped list
Customizing Grouping
Now that we've seen how to implement basic grouping in ListView, let's see how to customize the display of group headers.
Similar to how the ListView has an ItemTemplate for defining how rows are
displayed, ListView has a GroupHeaderTemplate. This is an example of the
ListView from above, with a customized group header template:

Here's how to accomplish that design in XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DemoListView.GroupingViewPage">
<ContentPage.Content>
<ListView x:Name="GroupedView"
GroupDisplayBinding="{Binding Title}"
GroupShortNameBinding="{Binding ShortName}"
IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding Subtitle}"
TextColor="#f35e20"
DetailColor="#503026" />
</DataTemplate>
</ListView.ItemTemplate>
<!-- Group Header Customization-->
<ListView.GroupHeaderTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding ShortName}"
TextColor="#f35e20"
DetailColor="#503026" />
</DataTemplate>
</ListView.GroupHeaderTemplate>
<!-- End Group Header Customization
</ListView>
</ContentPage.Content>
</ContentPage>
Headers and Footers
It is possible for a ListView to present a header and footer that scroll with the elements of the list. The header and footer can be strings of text or a more complicated layout. Note that this is separate from section groups.
You can set the Header and/or Footer to a simple string value,
or you can set them to a more complex layout.
There are also HeaderTemplate and
FooterTemplate properties that let you create more complex
layouts for the header and footer that support data binding.
To create a simple header/footer, just set the Header or Footer properties to the text you want to display. In code:
ListView HeaderList = new ListView() {
Header = "Header",
Footer = "Footer"
};
In XAML:
<ListView x:Name="HeaderList" Header="Header" Footer="Footer"></ListView>

To create a customized header and footer, define the Header and Footer views:
<ListView.Header>
<StackLayout Orientation="Horizontal">
<Label Text="Header"
TextColor="Olive"
BackgroundColor="Red" />
</StackLayout>
</ListView.Header>
<ListView.Footer>
<StackLayout Orientation="Horizontal">
<Label Text="Footer"
TextColor="Gray"
BackgroundColor="Blue" />
</StackLayout>
</ListView.Footer>

Row Separators
Separator lines are displayed between ListView elements by default on iOS and Android. Windows Phone does not support separator lines, per that platforms UX guidelines. If you'd prefer to hide the separator lines on iOS and Android, set the SeparatorVisibility property on your ListView. The options for SeparatorVisibility are:
- Default - shows a separator line on iOS and Android.
- None - hides the separator on all platforms.
Default Visibility:
C#:
SepratorDemoListView.SeparatorVisibility = SeparatorVisibility.Default;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorVisibility="Default" />

None:
C#:
SepratorDemoListView.SeparatorVisibility = SeparatorVisibility.None;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorVisibility="None" />

You can also set the color of the separator line via the SeparatorColor property:
C#:
SepratorDemoListView.SeparatorColor = Color.Green;
XAML:
<ListView x:Name="SeparatorDemoListView" SeparatorColor="Green" />

NOTE: setting either of these properties on Android after
loading the ListView incurs a large performance penalty.
Row Heights
All rows in a ListView have the same height by default. ListView has two properties that can be used to change that behavior:
HasUnevenRows–true/falsevalue, rows have varying heights if set totrue. Defaults tofalse.RowHeight– sets the height of each row whenHasUnevenRowsisfalse.
You can set the height of all rows by setting the RowHeight property on the ListView.
Custom Fixed Row Height
C#:
RowHeightDemoListView.RowHeight = 100;
XAML:
<ListView x:Name="RowHeightDemoListView" RowHeight="100" />

Uneven Rows
If you'd like individual rows to have different heights, you can set the
HasUnevenRows property to true.
Note that row heights don't have to be manually set once HasUnevenRows has
been set to true, because the heights will be automatically calculated by Xamarin.Forms.
C#:
RowHeightDemoListView.HasUnevenRows = true;
XAML:
<ListView x:Name="RowHeightDemoListView" HasUnevenRows="true" />

HasUnevenRows feature requires iOS 7 or later.
Runtime Resizing of Rows
Individual ListView rows can be programmatically resized at runtime, provided that the HasUnevenRows property is set to true. The Cell.ForceUpdateSize method updates a cell's size, even when it isn't currently visible, as demonstrated in the following code example:
void OnImageTapped (object sender, EventArgs args)
{
var image = sender as Image;
var viewCell = image.Parent.Parent as ViewCell;
if (image.HeightRequest < 250) {
image.HeightRequest = image.Height + 100;
viewCell.ForceUpdateSize ();
}
}
The OnImageTapped event handler is executed in response to an Image in a cell being tapped, and increases the size of the Image displayed in the cell so that it's easily viewed.

Note that there is a strong possibility of performance degradation if this feature is overused.
Let us know how you feel about this.
0/250
Xamarin Workbook
If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.