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
将调用 ToString
并在 TextCell
中为每一行显示结果。 若要自定义数据的显示方式,请参阅单元格外观。
由于 ItemsSource
已发送到数组,因此当基础列表或数组发生更改时,内容将不会更新。 如果在基础列表中添加、删除和更改项时希望 ListView 自动更新,则需要使用 ObservableCollection
。 ObservableCollection
在 System.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>
,设置为ListView
ItemsSource
列表,并填充数据:
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 示例定义一个包含 ListView
的 ContentPage
。 可通过 ItemsSource
属性设置 ListView
的数据源。 在 ListView.ItemTemplate
元素内定义 ItemsSource
中每一行的布局。 其结果如以下屏幕截图所示:
警告
ObservableCollection
不是线程安全的。 修改 ObservableCollection
会导致 UI 更新发生在执行修改的同一线程上。 如果线程不是主 UI 线程,则将导致异常。
绑定 SelectedItem
通常,你需要绑定到 ListView
的选定项,而不是使用事件处理程序来响应更改。 若要在 XAML 中执行此操作,请绑定 SelectedItem
属性:
<ListView x:Name="listView"
SelectedItem="{Binding Source={x:Reference SomeLabel},
Path=Text}">
…
</ListView>
假设 listView
的 ItemsSource
是字符串列表,SomeLabel
会将其 Text
属性绑定到 SelectedItem
。