แชร์ผ่าน


ListView Data Sources

A Xamarin.Forms ListView is used for displaying lists of data. This article explains how to populate a ListView with data and how to bind data to the selected item.

ItemsSource

A ListView is populated with data using the ItemsSource property, which can accept any collection implementing IEnumerable. The simplest way to populate a ListView involves using an array of strings:

<ListView>
      <ListView.ItemsSource>
          <x:Array Type="{x:Type x:String}">
            <x:String>mono</x:String>
            <x:String>monodroid</x:String>
            <x:String>monotouch</x:String>
            <x:String>monorail</x:String>
            <x:String>monodevelop</x:String>
            <x:String>monotone</x:String>
            <x:String>monopoly</x:String>
            <x:String>monomodal</x:String>
            <x:String>mononucleosis</x:String>
          </x:Array>
      </ListView.ItemsSource>
</ListView>

The equivalent C# code is:

var listView = new ListView();
listView.ItemsSource = new string[]
{
  "mono",
  "monodroid",
  "monotouch",
  "monorail",
  "monodevelop",
  "monotone",
  "monopoly",
  "monomodal",
  "mononucleosis"
};

ListView Displaying List of Strings

This approach will populate the ListView with a list of strings. By default, ListView will call ToString and display the result in a TextCell for each row. To customize how data is displayed, see Cell Appearance.

Because ItemsSource has been sent to an array, the content will not update as the underlying list or array changes. If you want the ListView to automatically update as items are added, removed and changed in the underlying list, you'll need to use an ObservableCollection. ObservableCollection is defined in System.Collections.ObjectModel and is just like List, except that it can notify ListView of any changes:

ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
listView.ItemsSource = employees;

//Mr. Mono will be added to the ListView because it uses an ObservableCollection
employees.Add(new Employee(){ DisplayName="Mr. Mono"});

Data Binding

Data binding is the "glue" that binds the properties of a user interface object to the properties of some CLR object, such as a class in your viewmodel. Data binding is useful because it simplifies the development of user interfaces by replacing a lot of boring boilerplate code.

Data binding works by keeping objects in sync as their bound values change. Instead of having to write event handlers for every time a control's value changes, you establish the binding and enable binding in your viewmodel.

For more information on data binding, see Data Binding Basics which is part four of the Xamarin.Forms XAML Basics article series.

Binding Cells

Properties of cells (and children of cells) can be bound to properties of objects in the ItemsSource. For example, a ListView could be used to present a list of employees.

The employee class:

public class Employee
{
    public string DisplayName {get; set;}
}

An ObservableCollection<Employee> is created, set as the ListView ItemsSource, and the list is populated with data:

ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
public ObservableCollection<Employee> Employees { get { return employees; }}

public EmployeeListPage()
{
    EmployeeView.ItemsSource = employees;

    // ObservableCollection allows items to be added after ItemsSource
    // is set and the UI will react to changes
    employees.Add(new Employee{ DisplayName="Rob Finnerty"});
    employees.Add(new Employee{ DisplayName="Bill Wrestler"});
    employees.Add(new Employee{ DisplayName="Dr. Geri-Beth Hooper"});
    employees.Add(new Employee{ DisplayName="Dr. Keith Joyce-Purdy"});
    employees.Add(new Employee{ DisplayName="Sheri Spruce"});
    employees.Add(new Employee{ DisplayName="Burt Indybrick"});
}

Warning

While a ListView will update in response to changes in its underlying ObservableCollection, a ListView will not update if a different ObservableCollection instance is assigned to the original ObservableCollection reference (e.g. employees = otherObservableCollection;).

The following snippet demonstrates a ListView bound to a list of employees:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:constants="clr-namespace:XamarinFormsSample;assembly=XamarinFormsXamlSample"
             x:Class="XamarinFormsXamlSample.Views.EmployeeListPage"
             Title="Employee List">
  <ListView x:Name="EmployeeView"
            ItemsSource="{Binding Employees}">
    <ListView.ItemTemplate>
      <DataTemplate>
        <TextCell Text="{Binding DisplayName}" />
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

This XAML example defines a ContentPage that contains a ListView. The data source of the ListView is set via the ItemsSource attribute. The layout of each row in the ItemsSource is defined within the ListView.ItemTemplate element. This results in the following screenshots:

ListView using Data Binding

Warning

ObservableCollection is not thread safe. Modifying an ObservableCollection causes UI updates to happen on the same thread that performed the modifications. If the thread is not the primary UI thread, it will cause an exception.

Binding SelectedItem

Often you'll want to bind to the selected item of a ListView, rather than use an event handler to respond to changes. To do this in XAML, bind the SelectedItem property:

<ListView x:Name="listView"
          SelectedItem="{Binding Source={x:Reference SomeLabel},
          Path=Text}">
 …
</ListView>

Assuming listView's ItemsSource is a list of strings, SomeLabel will have its Text property bound to the SelectedItem.