In Part 4 of this series we created a new Master/Detail project. In this part, we’re going to zero in on one view on one page… but what a view it is!
This series is based on my Pluralsight Course: Building Your First Mobile Application with Xamarin.Forms and Visual Studio 2017
ListView
Because we are using the out of the box Master/Detail project, and because that project uses some advanced techniques, taking it apart won’t be simple, but it will be valuable.
At the top of the file, we see a Title, bound to a property, and we see a ToolbarItem. We’re going to ignore all of that for now, and focus on the StackLayout that contains our ListView
<?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="BookStore.ItemsPage"
Title="{Binding Title}"
x:Name="BrowseItemsPage">
<ContentPage.ToolbarItems>
<ToolbarItem
Text="Add"
Clicked="AddItem_Clicked" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView
The ListView element in this example has a number of properties,
<ListView
x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
Let’s take them one at a time.
- x:Name assigns a name to the ListView so that we can refer to this particular ListView in code
- ItemsSource refers to a collection of data that we’ll be listing in the ListView. We’ll come back to this but notice that the ItemsSource is bound to a property (in this case a collection) in the BindingContext.
- Vertical Options is set to FillAndExpand. This is one of an enumerated list of VerticalOptions. FillAndExpand makes sense on a StackLayout but is identical to Fill in an individual element. In either case, here FillAndExpand means to provide enough room for the element vertically.
- HasUnevenRows is a critical property – it means that the data will be displayed in such a way that some rows will be larger than others. Over time, we’ll come back to this one, but failing to set this can cause your list not to appear at all.
- RefreshCommand and IsPullToRefreshCommand have to do with pulling the list down to refresh it. We’ll come back to that much later in this series
- CachingStrategy has to do with how items in the list are cached (for memory management) and is also something we’ll come back to later in the course
- ItemSelected points to an event handler that is invoked when an item in the list is selected
Within the body of the list element is a template. The template instructs the list how to display each element in the collection (pointed to by the ItemsSource property.)
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Padding="10">
<!-- ... -->
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
The ItemTemplate has a DataTemplate which can contain one of a variety of types of Cells. We’ll, again, come back to the various types of Cells, but the most flexible is the ViewCell. When using a ViewCell you must define the layout of each cell, but you have great flexibility in what goes into the Cell. Here, we’re saying that each cell will be held in a stackLayout (with a padding of 10 around all sides of the cell)
Within the stacklayout (and thus within every cell for each item in the list) are two labels, the first bound to the Text property, and the second bound to the Description label.
<Label
Text="{Binding Text}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
FontSize="16" />
<Label
Text="{Binding Description}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
FontSize="13" />
Finally, the Style refers to XAML styling, a topic that will receive a post of its own. Let’s return to the top of the ListView where we found the ItemsSource was bound to a property Items.
We know that this property will be in the class that is defined as the BindingContext in the code behind. Sure enough, if we go to ItemsPage.xaml.cs we find that the BindingContext is set to ItemsViewModel:
BindingContext = viewModel = new ItemsViewModel();
If we go to ItemsViewModel.cs and look in the constructor, we find that the property Items is defined to be an ObservableRangeCollection of Item
public ObservableRangeCollection<Item> Items { get; set; }
Once again, we’ll come back to an ObservableRangeCollection, but for now it is a type of ObservableCollection; that is a collection that raises an event when an object is added to or removed from the collection.
The Item that it holds is defined in the Model class Item,
public class Item : ObservableObject {
string id = string.Empty;
[JsonIgnore]
public string Id {
get { return id; }
set { SetProperty( ref id,value ); }
}
string text = string.Empty;
public string Text {
get { return text; }
set { SetProperty( ref text,value ); }
}
string description = string.Empty;
public string Description {
get { return description; }
set { SetProperty( ref description,value ); }
}
}
The part we care about here is that, sure enough, the Item class has a property Text and a property Description, which are the properties the two labels bind to.
There is much more detail to dive into, but you’ve seen the essentials of using a ListView in Xamarin.Forms.
To populate this list, a dummy list of data is stored in the file MockDataStore,
var _items = new List<Item>
{
new Item { Id = Guid.NewGuid().ToString(), Text = "First item", Description="This is a nice description"},
new Item { Id = Guid.NewGuid().ToString(), Text = "Second item", Description="This is a nice description"},
new Item { Id = Guid.NewGuid().ToString(), Text = "Third item", Description="This is a nice description"},
new Item { Id = Guid.NewGuid().ToString(), Text = "Fourth item", Description="This is a nice description"},
new Item { Id = Guid.NewGuid().ToString(), Text = "Fifth item", Description="This is a nice description"},
new Item { Id = Guid.NewGuid().ToString(), Text = "Sixth item", Description="This is a nice description"},
};
The ItemList page displays the data in two labels, using the styles defined in the template,
More detail to come in upcoming posts.