ListView 数据源

Xamarin.FormsListView 用于显示数据列表。 本文介绍如何使用数据填充 ListView 以及如何将数据绑定到所选项。

ItemsSource

使用 ItemsSource 属性通过数据填充 ListView,该属性可接受实现 IEnumerable 的任何集合。 填充 ListView 的最简单方法包括使用字符串数组:

<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>

等效 C# 代码如下:

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

显示字符串列表的 ListView

此方法将使用字符串列表填充 ListView。 默认情况下,ListView 将调用 ToString 并在 TextCell 中为每一行显示结果。 若要自定义数据的显示方式,请参阅单元格外观

由于 ItemsSource 已发送到数组,因此当基础列表或数组发生更改时,内容将不会更新。 如果在基础列表中添加、删除和更改项时希望 ListView 自动更新,则需要使用 ObservableCollectionObservableCollectionSystem.Collections.ObjectModel 中定义,就像 List 一样,只是它可通知 ListView 任何更改:

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"});

数据绑定

数据绑定是将用户界面对象的属性绑定到某个 CLR 对象(例如视图模型中的类)的属性的“粘合剂”。 数据绑定非常有用,因为它通过替换大量枯燥的样板代码来简化用户界面的开发。

数据绑定的工作原理是在对象的绑定值发生更改时保持对象同步。 不必在每次控件的值更改时都编写事件处理程序,而可在视图模型中建立绑定并启用绑定。

有关数据绑定的详细信息,请参阅 Xamarin.Forms XAML 基础知识文章系列的第四部分“数据绑定基础知识”

绑定单元格

单元格的属性(及单元格的子级)可绑定到 ItemsSource 中对象的属性。 例如,可使用 ListView 显示员工列表。

员工类:

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

创建一个ObservableCollection<Employee>,设置为ListViewItemsSource列表,并填充数据:

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"});
}

警告

虽然 ListView 将更新以响应其基础 ObservableCollection 中的更改,但如果向原始 ObservableCollection 引用分配了不同的 ObservableCollection 实例(例如 employees = otherObservableCollection;),则 ListView 将不会更新。

以下代码片段演示了一个绑定到员工列表的 ListView

<?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>

此 XAML 示例定义一个包含 ListViewContentPage。 可通过 ItemsSource 属性设置 ListView 的数据源。 在 ListView.ItemTemplate 元素内定义 ItemsSource 中每一行的布局。 其结果如以下屏幕截图所示:

使用数据绑定功能的 ListView

警告

ObservableCollection 不是线程安全的。 修改 ObservableCollection 会导致 UI 更新发生在执行修改的同一线程上。 如果线程不是主 UI 线程,则将导致异常。

绑定 SelectedItem

通常,你需要绑定到 ListView 的选定项,而不是使用事件处理程序来响应更改。 若要在 XAML 中执行此操作,请绑定 SelectedItem 属性:

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

假设 listViewItemsSource 是字符串列表,SomeLabel 会将其 Text 属性绑定到 SelectedItem