大多数应用都显示数据列表(如联系人列表、库中的图像或电子邮件收件箱的内容)。这些列表可以从数据库、Web 或 JSON 数据源获取其数据。 适用于 JavaScript 的 Windows 库提供可用来显示数据的ListView 控件。
先决条件
我们假设你可以创建使用 Windows JavaScript 库控件且使用 JavaScript 为 Windows 构建的基本 Windows 应用商店应用。有关如何开始使用 Windows JavaScript 库控件的说明,请参阅快速入门:添加 WinJS 控件和样式。
什么是 ListView?
ListView 是一种适用于 JavaScript 的 Windows 库控件,它以可自定义的列表或网格形式显示来自IListDataSource 的数据。 适用于 JavaScript 的 Windows 库提供了以下几种类型的IListDataSource 对象:
- 你可使用 List 从一个数组创建 IListDataSource。
- 你可使用 StorageDataSource 访问有关文件和目录的信息。
还可以创建自定义数据源,以便连接到某些其他类型的数据提供程序,如 Web 服务或数据库。有关的详细说明,请参阅如何创建自定义数据源。
创建 ListView
创建 ListView
-
将指向适用于 JavaScript 的 Windows 库的引用添加到你的 HTML 文件(如果文件中还没有这些引用)。
<!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
此示例展示了你在 Microsoft Visual Studio Express 2012 for Windows 8 中创建新的“空白应用”项目时生成的 default.html 文件的 HTML。
<!-- default.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ListViewExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <!-- ListViewExample references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> </head> <body> <p>Content goes here</p> </body> </html>
此示例使用浅色样式表而不是深色样式表,所以如果你想要你的应用符合这些示例,请将此引用:
<!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet">
...更改为:
<!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet">
- 在 HTML 文件中,创建一个 div 元素并将它的 data-win-control 属性设置为“WinJS.UI.ListView”。
<div id="basicListView" data-win-control="WinJS.UI.ListView"> </div>
-
在 HTML 文件附带的 JavaScript 代码中,当加载 HTML 时调用 WinJS.UI.processAll 函数。
JavaScriptWinJS.UI.processAll();
下一示例展示了当你创建新的“空白应用程序”项目时所创建的 default.html 文件附带的 default.js 文件。
JavaScript(function () { "use strict"; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; WinJS.strictProcessing(); app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; app.start(); })();
当你将 ListView 添加到起始页 (default.html) 后此示例才生效。如果将 ListView 添加到Page 控件,则无需调用WinJS.UI.processAll,因为该 Page 控件将为你执行调用。如果要向你自己的自定义 HTML 中添加ListView,可以使用 DOMContentLoaded 事件来调用 WinJS.UI.processAll。有关激活控件的详细信息,请参阅快速入门:添加 WinJS 控件和样式。
此代码会创建空的 ListView。如果现在运行该应用,尚且看不到任何内容。在下一部分中,为 ListView 创建一些用于显示的数据。
定义数据
使用代码在单独的 JavaScript 文件中创建数据源,这样可使数据源更易于维护。在此部分中,你可以了解如何为数据创建 JavaScript 文件,如何创建List 以及如何使用WinJS.Namespace.define 函数使得其余应用可以访问该数据。
- 使用 Visual Studio Express 2012 for Windows 8 将数据文件添加到项目中。在解决方案资源管理器中,右键单击项目的
js
文件夹,然后选择“添加”>“新项目”。即会出现“添加新项目”对话框。 - 选择“JavaScript 文件”。为其命名为 "dataExample.js"。 单击“添加”以创建文件。Visual Studio Express 2012 for Windows 8 会创建名为 dataExample.js 的空 JavaScript 文件。
- 打开 dataExample.js。创建一个匿名函数并打开严格模式。
如为基本应用编写代码中所述,通过在匿名函数中包装 JavaScript 代码来封装该代码是一个好方法,并且使用严格模式同样也是一个好的编程做法。
JavaScript(function () { "use strict"; })();
- 创建数据数组。以下示例将创建一个对象数组。每个对象都有三个属性:title、text 和 image。
JavaScript
(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; })();
注意 如果你要按照你的代码操作,则可以将图片更改为你的本地计算机上的文件,也可以通过下载 ListView 入门示例(它与此处的示例不是同一个示例,但它们使用相同的图像)来获取图片。你还可以在不添加图像的情况下运行此示例。它仍将运行。
- 使用数组创建 List 对象。
JavaScript
(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; var dataList = new WinJS.Binding.List(dataArray); })();
- 通过声明命名空间并添加 List 作为其公共成员来公开 List。
由于你刚编写的代码封装在一个匿名函数中,因此该代码的任何部分都不能公开访问。这就是为什么使用匿名函数的部分原因:为了使专用数据保持私有。为了使你的 ListView 能够访问 List,你必须使其可公开访问。实现此目的的一种方法就是使用 WinJS.Namespace.define 函数创建一个命名空间并添加 List 作为它的一个成员。
WinJS.Namespace.define 函数采用两个参数:要创建的命名空间的名称和包含一个或多个属性/值对的对象。每个属性是成员的公用名称,而每个值是在私有代码中要公开的基础变量、属性或函数。
以下示例创建一个名为 DataExample 的命名空间,该命名空间公开一个名为 itemList 且返回 List 的公共成员。
JavaScript(function () { "use strict"; var dataArray = [ { title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" }, { title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }, { title: "Brilliant banana", text: "Frozen custard", picture: "images/60banana.png" }, { title: "Orange surprise", text: "Sherbet", picture: "images/60orange.png" }, { title: "Original orange", text: "Sherbet", picture: "images/60orange.png" }, { title: "Vanilla", text: "Ice cream", picture: "images/60vanilla.png" }, { title: "Very vanilla", text: "Frozen custard", picture: "images/60vanilla.png" }, { title: "Marvelous mint", text: "Gelato", picture: "images/60mint.png" }, { title: "Succulent strawberry", text: "Sorbet", picture: "images/60strawberry.png" } ]; var dataList = new WinJS.Binding.List(dataArray); // Create a namespace to make the data publicly // accessible. var publicMembers = { itemList: dataList }; WinJS.Namespace.define("DataExample", publicMembers); })();
你创建了一个可以由你的 ListView 访问的数据源。 接着,需要将该数据连接到 ListView。
将数据连接到 ListView
- 在 ListView 所在 HTML 文件的 head 部分中,将引用添加到刚创建的数据文件 (dataExample.js) 中:
JavaScript
<head> <meta charset="utf-8"> <title>ListViewExample</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet"> <script src="//Microsoft.WinJS.1.0/js/base.js"></script> <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> <!-- ListViewExample references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> <!-- Your data file. --> <script src="/js/dataExample.js"></script> </head>
- 使用在上一部分中创建的数据设置 ListView 控件的 itemDataSource 属性。
itemDataSource 属性接受IListDataSource 对象。List 对象不是IListDataSource,但该对象确实具有 dataSource 属性,该属性返回自身的 IListDataSource 版本。
若要连接数据,请将 ListView 控件的 itemDataSource 属性设置为
DataExample.itemList.dataSource
:JavaScript<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource }"> </div>
运行该应用。ListView 显示数据源中的属性和值:
这完全不是我们想要的外观。我们只想显示标题和文本字段的值,而且希望显示实际图像(而不是指向图像的路径)。若要获取我们所需的呈现外观,需要定义 Template。下一个步骤会显示方法。
定义项模板
此时,ListView 具备所需的数据,但不了解如何显示该数据。为此,你需要一个项模板,其中包含要用来显示每个列表项的标记。项模板可以包含大多数其他控件(有关详细信息,请参阅添加交互元素部分),但不能包含FlipView 或另一个ListView。
创建模板的方式有以下两种:可以使用标记定义 WinJS.Binding.Template,也可以创建模板化功能。此示例会创建标记模板。有关创建模板函数的信息,请参阅itemTemplate 属性。
WinJS.Binding.Template 可轻松创建:定义要用于显示每个列表项的标记,然后指示每个数据字段的显示位置。
-
在 HTML 中,创建 WinJS.Binding.Template 控件并为其分配 ID。以下示例使用 ID "mediumListIconTextTemplate"。
HTML<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> </div>
注意 你必须先定义模板然后才能使用它,因此请在你的 ListView 的 HTML 之前添加我们的模板的 HTML。
- WinJS.Binding.Template 必须具有单个根元素。创建用作模板父内容的 div 元素。
HTML
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div> </div> </div>
-
创建 ListView 将为其包含的每个数据项生成的标记。 在上一步中创建的数据包含图像位置、标题和文本,因此,请创建以下元素:
- 用于显示图片字段的 img 元素。
- 用于显示标题字段的 h4 元素。
- 用于显示文本字段的 h6 元素。
HTML<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div> <!-- Displays the "picture" field. --> <img src="#" /> <div> <!-- Displays the "title" field. --> <h4></h4> <!-- Displays the "text" field. --> <h6></h6> </div> </div> </div>
- 为了确保属性布局,请始终指定模板中根元素和 img 元素的大小。
HTML
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" /> <div> <!-- Displays the "title" field. --> <h4></h4> <!-- Displays the "text" field. --> <h6></h6> </div> </div> </div>
-
为显示数据的每个元素设置 data-win-bind 属性。data-win-bind 属性使用以下语法:
data-win-bind="propertyName: dataFieldName"
例如,若要将 img 的 src 属性绑定到 "picture" 字段,使用以下语法:
HTML<img data-win-bind="src : picture" />
若要设置多个属性,可以使用分号将其分隔:
data-win-bind="property1Name: dataField1Name; property2Name:dataField2Name"
此示例将模板中的项绑定到其相应的数据字段中。
HTML<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" data-win-bind="alt: title; src: picture" /> <div> <!-- Displays the "title" field. --> <h4 data-win-bind="innerText: title"></h4> <!-- Displays the "text" field. --> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div>
-
若要使用项模板,请使用 select 语法将 ListView 的 itemTemplate 属性设置为你的项模板。
HTML<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template"> <div style="width: 150px; height: 100px;"> <!-- Displays the "picture" field. --> <img src="#" style="width: 60px; height: 60px;" data-win-bind="alt: title; src: picture" /> <div> <!-- Displays the "title" field. --> <h4 data-win-bind="innerText: title"></h4> <!-- Displays the "text" field. --> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div> <div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate')}"> </div>
如果立即运行应用,则绑定的数据会出现在列表中。
设置 ListView 的样式
ListView 不会动态调整其高度以适应你的内容。为了使ListView 能够呈现,你必须为其指定绝对的高度值。适用于 JavaScript 的 Windows 库的样式表将 ListView 控件的高度设置为 400px。但是通过用你自己的 CSS 替代默认样式可以很轻松地指定自己的高度。将此 CSS 添加到你的应用的 CSS 文件可以设置ListView 的高度和宽度并为其提供边框。
.win-listview { height: 500px; width: 500px; border: 2px solid gray; }
win-listview 是一个由适用于 JavaScript 的 Windows 库定义的类,可用来设置 ListView 的样式。刚刚看到的示例更改每个 ListView 的高度、宽度和边框。若要仅更改一个ListView,请将托管 div 元素的 ListView 控件的 ID 添加到选择器中:
#basicListView.win-listview { height: 500px; width: 500px; border: 2px solid gray; }
运行该应用。现在,ListView 足够大,可以显示所有的项。
你可以替代适用于 JavaScript 的 Windows 库的样式表所定义的 CSS 类,从而自定义适用于 JavaScript 的 Windows 库控件的外观。用于ListView 的 CSS 类包括:
有关完整的列表,请参阅 ListView reference page。
此示例定义的样式将在 ListView 中的每个项容器周围添加一个边距。
#basicListView.win-listview .win-container { margin: 10px; }
下一个示例定义的样式适用于处在悬停状态的 ListView 中的列表项。
#basicListView.win-listview .win-container:hover { background-color: red; border-color: red; }
注意
ListView 支持左边距、上边距和下边距,但是你不能指定右边距。一个解决方法就是添加一个具有所需宽度的元素,并将它的 style.visibility 属性设置为“none”,然后将该元素添加到 ListView 的右侧。
设置项的样式
上面的几个示例使用级联样式和适用于 JavaScript 的 Windows 库类来设置 ListView 及其各项的样式。你还可以使用 CSS 类来设置项模板的样式。下一个示例更新你在定义项模板部分中定义的模板。它将删除已定义的级联样式并添加一些 CSS 类。
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: none"> <div class="mediumListIconTextItem"> <img src="#" class="mediumListIconTextItem-Image" data-win-bind="src: picture" /> <div class="mediumListIconTextItem-Detail"> <h4 data-win-bind="innerText: title"></h4> <h6 data-win-bind="innerText: text"></h6> </div> </div> </div>
将以下样式添加到你的应用的 CSS 中:
.mediumListIconTextItem { width: 282px; height: 70px; padding: 5px; overflow: hidden; display: -ms-grid; } .mediumListIconTextItem img.mediumListIconTextItem-Image { width: 60px; height: 60px; margin: 5px; -ms-grid-column: 1; } .mediumListIconTextItem .mediumListIconTextItem-Detail { margin: 5px; -ms-grid-column: 2; }
现在,ListView 看上去如下所示:
你不必从头创建模板样式。 有关一组常用的模板及其相应的 CSS,请参阅列表布局的项模板和网格布局的项模板。
在列表布局和网格布局之间切换
ListView 元素有两个布局模式:列表和网格。
- 若要使用列表布局,请将 layout 属性设置为 WinJS.UI.ListLayout,如下所示:
HTML
<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout: {type: WinJS.UI.ListLayout}}"> </div>
- 若要使用网格布局,请将 layout 属性设置为 WinJS.UI.GridLayout,如下所示:
HTML
<div id="basicListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), layout: {type: WinJS.UI.GridLayout}}"> </div>
你可以随时更改 ListView 的布局,即使在创建它之后也可以进行更改。
对数据进行分组
可以对 ListView 中的项进行分组。下图显示按字母顺序分组的项:
若要了解具体做法,请参阅如何对 ListView 中的项进行分组。
向项模板中添加交互元素
项模板可以包含大多数其他控件,但不能包含 FlipView 或另一个 ListView。
通常,当用户与某个元素交互时,ListView 会捕捉该交互并使用它来确定用户是选择或调用了某个项目还是正在项目之间平移。为了使交互元素(如控件)接收输入,必须将win-interactive
类附加到交互元素或它的某个父元素。该元素及其子元素接收交互而且不再针对 ListView 触发事件。
当你将 win-interactive
附加到项模板中的某个元素时,请确保该元素不填满整个项目,否则用户将无法选择或调用该项目。
若要向项模板添加交互元素,我们建议你使用模板函数而非 WinJS.Binding.Template。 有关模板函数的详细信息,请参阅如何创建模板函数。