Windows10-开发秘籍-一-

127 阅读59分钟

Windows10 开发秘籍(一)

原文:Windows 10 Development Recipes

协议:CC BY-NC-SA 4.0

一、Windows 10 应用入门

Windows 10 是微软在 2015 年 7 月 29 日发布的新操作系统。自 Windows 8.1 以来,人们一直在期待它。对于应用开发者(商店和手机),Windows 8.1 和 Visual Studio 2013 给出了一种独特的编程模型,称为通用 Windows 8 应用。通用 Windows 应用能够从一个共享的代码库同时面向 Windows 和 Windows Phone。Windows 10 超越了 Windows 和 Windows Phone,引入了所谓的通用 Windows 平台(UWP)应用。有了这个新平台,你可以保证在不同的设备上有一个一致的核心 API 层。UWP 开发的单个软件包可以安装在多种设备和设备系列上。设备系列包括桌面操作系统、移动操作系统(手机和平板电脑)、Xbox 和物联网(IoT)设备以及无头设备系列。这意味着您的应用可以在任何设备上运行,包括手机、平板电脑、PC、Xbox 游戏机等。本章介绍 Windows 10 通用 Windows 平台应用开发。

1.1 检查通用 Windows 平台

问题

你决定开发一个面向 PC、手机、平板电脑和 Xbox 的通用 Windows 平台应用。您想要了解通用 Windows 平台—设备系列和通用控件。

解决办法

让我们来看看通用 Windows 平台的一些亮点。

一个 Windows 平台

Windows 10 带来了一个 Windows 平台(见图 1-1 )。在 Windows 10 中,操作系统已经过重构,现在具有跨不同 Windows 10 平台的通用核心。这意味着您拥有一个通用的 Windows 内核、一个文件 I/O 堆栈和一个应用模型。简单来说,通用 Windows 平台就是联系人和版本的集合。对于 Windows Phone 8.1 和 Windows 8.1 应用,您必须面向操作系统—Windows 或 Windows Phone,而对于通用 Windows 平台应用,您面向设备。

A978-1-4842-0719-2_1_Fig1_HTML.jpg

图 1-1。

Universal Windows Platform apps model

UWP 应用可以在各种具有不同外形和输入机制的设备上运行。当您开发 UWP 应用时,您需要确保为每台设备量身定制体验,并利用各自设备的功能。Windows 10 上有一个通用的核心或内核。每个设备都向基础层添加自己的 API。因此,要访问设备的独特 API,您需要编写条件代码来在您的应用中提供设备特定的功能。

设备系列

Windows 和 Windows Phone 是开发人员针对其 Windows 8.1 和 Windows Phone 8 应用的操作系统。但随着 Windows 10 现在在各种设备上可用,UWP 应用针对特定的设备家族。设备系列标识了该系列中设备的 API、特性和行为。它还决定了可以安装应用的设备集。图 1-2 展示了器件系列的层次结构。

A978-1-4842-0719-2_1_Fig2_HTML.jpg

图 1-2。

Universal device family hierarchy

一组 API 有一个名称和一个版本号。这是设备系列操作系统的基础。例如,个人电脑运行桌面操作系统,并基于桌面设备系列。另一方面,手机和平板电脑拥有基于移动设备家族的移动操作系统。我希望您现在对设备系列有一个确切的概念。

通用控件

借助 UWP,应用可以在不同的外形、屏幕分辨率、dpi 和其他设备特性上运行。应用必须适应这些不同的外形和分辨率。Windows 10 提供了新的通用控件、布局和工具,将帮助您根据运行应用的设备来调整应用 API。Windows 10 包括新的控件,如日历和拆分视图。专用于 Windows Phone 应用的 Pivot control 现在可用于通用 Windows 平台应用。

通用输入处理

通过 UWP 应用,通用控件现在支持各种输入,如鼠标、键盘、触摸、笔和控制器(如 Xbox 控制器)。该平台提供了一些核心 API,可以在您的应用中用来处理各种输入。下面是一些可以使用的输入 API。

  • CoreInput:允许您使用原始输入。
  • PointerInput:将原始触摸、鼠标和笔统一到一个一致的界面中。
  • PointerDevice:一个设备 API,允许您查询设备功能以了解可用的输入类型。

1.2 通用 Windows 平台的开发工具

问题

你想开始开发通用的 Windows 平台应用。您想知道应该使用哪些工具进行开发。

解决办法

您需要在开发计算机上安装 Windows 10 操作系统和 Visual Studio 2015 社区版。

要安装 Windows 10,请访问微软 http://windows.microsoft.com/en-us/windows/buy 。如果您已经安装了 Windows 操作系统,您可以免费将操作系统升级到 Windows 10。

要安装 Visual Studio 2015 (VS 2015)社区版,可以访问微软网站 https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs 。安装 VS 2015 时,需要确保选择了通用的 Windows app 开发工具(见图 1-3 )。这在可选功能列表中。

A978-1-4842-0719-2_1_Fig3_HTML.jpg

图 1-3。

Visual Studio 2015 Community Edition installation

1.3 创建通用 Windows 平台应用

问题

您想要创建一个简单的通用 Windows 平台应用。

解决办法

Visual Studio 2015 附带预安装的通用 Windows 平台应用项目模板。您将使用该模板创建您的第一个应用。

它是如何工作的

让我们看看如何使用 Visual Studio 2015 创建一个新的通用 Windows 平台应用。

Open Visual Studio 2015 Community edition. Select File ➤ New Project. In the New Project dialog window, select Templates ➤ JavaScript ➤ Windows ➤ Universal from the Installed Templates section. Select Blank App (Universal Windows) from the available project templates (see Figure 1-4). Provide a name and location for the app and click OK.

A978-1-4842-0719-2_1_Fig4_HTML.jpg

图 1-4。

New project template   Visual Studio will prepare the project. Figure 1-5 shows what the new solution looks like.

A978-1-4842-0719-2_1_Fig5_HTML.jpg

图 1-5。

Solution Explorer As part of the project template, you get css, images, js, and WinJS folders. You also have a pre-created default.html page to get started.

  • css文件夹是保存定制样式表(.css文件)的地方。
  • images文件夹包含您想在应用中使用的任何图像。
  • js是 JavaScript 文件夹,用于保存与应用相关的 js 文件。您会看到预先创建的default.js文件,其中包含以下代码。

(function () {         "use strict";         var app = WinJS.Application;         var activation = Windows.ApplicationModel.Activation;         app.onactivated = function (args) {                 if (args.detail.kind === activation.ActivationKind.launch) {                     if (args.detail.previousExecutionState !==                 activation.ApplicationExecutionState.terminated) {                             //App Initilization code                         } else {                                 //Restore app sessions state                         }                         args.setPromise(WinJS.UI.processAll());                 }         };         app.oncheckpoint = function (args) {             //save any app state here         };         app.start(); })();   The code creates a WinJS.Application object instance and starts the application.   Open default.html by double-clicking the file in Solution Explorer. Here is the default code you see in the file: <!DOCTYPE html> <html> <head>     <meta charset="utf-8" />     <title>Ch1R3</title>     <link href="WinJS/css/ui-dark.css" rel="stylesheet" />     <script src="WinJS/js/basejs"></script>     <link href="/css/default.css" rel="stylesheet" />     <script src="/js/default.js"></script> </head> <body class=”win-type-body”>     <p>Content goes here</p> </body> </html>   It’s pretty much empty with just one line of text that reads, “Content goes here.” Replace this text with “Hello World!” This will be our Hello World application with UWP ☺.   Press Ctrl+Shift+B on your keyboard or select Build ➤ Build solution. Visual Studio builds the project.  

1.4 运行通用 Windows 平台应用

问题

您已经创建了一个新的 UWP 应用,并希望运行该应用来查看它的运行情况。你想知道怎么做。

解决办法

Visual Studio 2015 提供了许多选项来运行您的 UWP 应用:

  • 在 Windows Phone 10 模拟器上运行应用
  • 在 Windows 10 模拟器上运行应用
  • 在本地机器上运行应用
  • 在设备上运行应用

它是如何工作的

当您安装 Visual Studio 2015 时,它还会安装 Windows Phone 10 模拟器和 Windows 10 模拟器。这些模拟器和仿真器模拟 Windows Phone 和 Windows 中不同的设备和屏幕大小。Visual Studio 2015 允许您选择其中一个选项来部署您的应用。您也可以直接从 Visual Studio 将应用部署到您的计算机上,并将其作为本地应用运行。让我们看一下所有这些选项,一次一个。

在 Windows Phone 10 模拟器上运行应用

在 Visual Studio 中,从目标组合框中选择一个可用的 Windows 10 模拟器。图 1-6 显示了可用仿真器的列表。

A978-1-4842-0719-2_1_Fig6_HTML.jpg

图 1-6。

Windows Phone 10 emulators target

按 F5 在选定的 Windows Phone 10 模拟器上运行应用。图 1-7 显示了 4 英寸 Windows Phone 10 上的截图。

A978-1-4842-0719-2_1_Fig7_HTML.jpg

图 1-7。

UWP app on Windows Phone 10 emulator

在 Windows 10 模拟器上运行应用

在 Visual Studio 中,从目标组合框中选择 Simulator。此选项允许您将应用部署到 Windows 10 模拟器(参见图 1-8 )。

A978-1-4842-0719-2_1_Fig8_HTML.jpg

图 1-8。

Windows 10 simulator target

按 F5 在 Windows 10 模拟器上运行应用。图 1-9 是该应用在模拟器上的截图。

A978-1-4842-0719-2_1_Fig9_HTML.jpg

图 1-9。

UWP app on Windows 10 simulator

在本地机器上运行应用

通常情况下,Windows 10 应用需要从 Windows Store 下载,然后安装在您的机器上。但是这个工作流程只适用于最终用户,不适用于开发人员。在应用开发期间,开发人员可以直接在他们的开发机器上部署和运行他们的应用。

在本地机器上运行应用之前,您需要在机器上启用开发人员模式。

在你的机器上,进入设置➤更新&开发者安全➤,如图 1-10 所示。

Select the Developer mode radio button.   In Visual Studio, select Local Machine from the target combo box, as shown in Figure 1-11.

A978-1-4842-0719-2_1_Fig11_HTML.jpg

图 1-11。

Local Machine target   Press F5 to run the app on your development machine. Figure 1-12 is a screenshot of the app running on a local machine.

A978-1-4842-0719-2_1_Fig12_HTML.jpg

图 1-12。

UWP app on local machine  

A978-1-4842-0719-2_1_Fig10_HTML.jpg

图 1-10。

Developer features settings

在设备上运行应用

如果你有 Windows 10 移动设备,你可以直接在上面部署和运行你的 UWP 应用。但是,在您可以将应用直接从 Visual Studio 部署到设备上之前,您需要启用您的手机,以允许在开发期间安装应用。这也被称为下载应用。这种模式被称为开发者模式,它是一种电话设置。在您的 Windows Phone 10 设备上,转到“设置”“➤更新与安全”“面向开发者的➤”。选择开发者模式,如图 1-13 所示。完成此步骤后,您的应用可以从 Visual Studio 直接部署到您的设备上。

A978-1-4842-0719-2_1_Fig13_HTML.jpg

图 1-13。

Developer Mode setting on Windows Phone device

在 Visual Studio 中,选择 Device 作为目标,如图 1-14 所示。

A978-1-4842-0719-2_1_Fig14_HTML.jpg

图 1-14。

Device target

接下来,按 F5 在您的设备上运行应用。输出应该类似于您在模拟器中看到的内容。

二、WinJS 基础知识

使用平台的库构建应用时,了解库提供的功能非常重要。在这一章中,你将看到 WinJS 为使用 JavaScript、HTML 和 CSS 构建 Windows 运行时应用提供的各种特性。这些特性包括名称空间、模块、承诺和查询选择器。几乎所有使用 WinJS 构建的应用都使用这些特性。通过利用名称空间和模块等特性,您可以使您的应用更容易维护,而不是在全局名称空间下添加所有内容。

2.1 JavaScript 中的名称空间

问题

使用 WinJS 库进行开发时,您需要对常见功能进行分组,并防止 JavaScript 代码中的命名冲突。

解决办法

名称空间允许开发人员更好地分组或组织公共功能。其他编程语言——c#、VB.NET、Java 等等——都提供了这个特性。许多 JavaScript 框架不支持名称空间,但是 WinJS 提供了一个特性,开发人员可以在他们的项目中使用名称空间。名称空间可以派上用场,尤其是当您的应用利用由不同开发人员编写的多个库时。

开发人员可以使用WinJS.Namespace.define方法来声明名称空间。

它是如何工作的

WinJS 库允许开发人员通过使用WinJS.Namespace.define方法来声明名称空间。

WinJS.Namespace.define方法有两个参数。

  • Name:这是第一个参数,代表新名称空间的名称。
  • Members:这是第二个参数,完全可选。此参数表示需要添加到正在定义的命名空间的对象列表。

以下是使用 WinJS 在 Windows 应用商店通用应用中创建新命名空间的步骤。

Launch Visual Studio 2015 and select File ➤ New Project. In the New Project dialog, select JavaScript ➤ Windows ➤ Universal from the Installed Templates sidebar. Select Blank App (Universal Windows) from the template and name the project ch2.1WinJSFundamentals. Click the OK button. This created the necessary files within the Visual Studio solution.   Add a new JavaScript file in the ch2.1WinJSFundamentals project by right-clicking the project’s js folder and selecting the Add ➤ New Item option. Select the JavaScript file from the Add New Item dialog and name the file WinJSFundamentals.js. Add the following code to the file.  

// Define the Namespace Developerpublish

WinJS.Namespace.define("DeveloperPublish");

// Utilities created in the DeveloperPublish Namespace

DeveloperPublish.Utilities = {

DisplayMessage: function () {

return "Message from DeveloperPublish Namespace";

}

};

// Define the Namespace Apress and create the Utilities under it.

WinJS.Namespace.define("Apress",

{

Utilities: {

DisplayMessage: function () {

return "Message from Apress Namespace";

}

}

});

console.log(DeveloperPublish.Utilities.DisplayMessage());

console.log(Apress.Utilities.DisplayMessage());

在前面的代码片段中,DeveloperPublish名称空间演示了带有单个参数的WinJS.Namespace.define方法的用法。对象被添加到命名空间中,命名空间后跟一个句点和对象的名称。

Apress 命名空间是用两个参数创建的。第一个参数是名称空间的名称 Apress 而第二个参数是作为 Apress 名称空间一部分的对象。

Open the default.html page and add the reference to the WinJSFundamentals.js file by using the following code snippet: <script src="js/WinJSFundamentals.js"></script>   Run the Windows app. You will notice that the string that is returned from DisplayMessage of the Utilities class is displayed in the console window, as shown in Figure 2-1.

A978-1-4842-0719-2_2_Fig1_HTML.jpg

图 2-1。

Display the string in the Visual Studio 2015 console window  

WinJS.Namespace是默认的名称空间,它提供如下功能

  • promise物体
  • 定义名称空间、logxhr的函数。

以下是属于 WinJS.Namespace 的对象和函数

  • 这个对象提供了在 JavaScript 代码中实现异步编程的机制。
  • validation:可以设置该属性来显示验证的结果。
  • define:这个函数用指定的名字定义一个新的名称空间。
  • defineWithParent:该函数在指定的父命名空间下定义一个具有指定名称的命名空间。
  • log:该函数将输出写入 Visual Studio 2015 中的 JavaScript 控制台窗口。
  • xhr:这个函数将对 XMLHttpRequest 的调用包装在一个承诺中。

请注意,您不应该在定义名称空间之前引用它。当您试图在命名空间定义之前访问它时,会收到“命名空间未定义”错误。

WinJS 库中包含了命名空间功能,以便更好地处理与作用域相关的问题。WinJS 中名称空间实现的源代码可以在项目的WinJS/js文件夹下的base.js文件中找到。

2.2 向现有名称空间添加名称空间

问题

您需要向现有的名称空间添加一个名称空间,并定义您的功能。

解决办法

使用WinJS.Namespace.defineWithParent方法将名称空间添加到 WinJS 中的现有名称空间。

它是如何工作的

WinJS.Namespace.defineWithParent方法允许开发人员向现有名称空间添加新的名称空间。这类似于define方法;它允许您在现有名称空间下创建一个新的名称空间。

WinJS.Namespace.defineWithParent方法接受三个参数:

  • 父名称空间:第一个参数是父名称空间的名称。
  • Name:这是要添加到父名称空间的名称空间的名称。
  • Members:要添加到新命名空间的对象列表。这是一个可选参数。

让我们使用配方 2.1 中创建的配方。打开项目中的WinJSFundamentals.js文件,并用下面的代码片段替换它。

WinJS.Namespace.define("Apress");

WinJS.Namespace.defineWithParent(Apress, "Books" ,

{

Utilities :

{

DisplayMessage: function () {

return "Message from Apress.Books Namespace";

}

}

}

);

console.log(Apress.Books.Utilities.DisplayMessage());

运行 Windows Store 项目,您应该会看到字符串“Message from Apress。Books Namespace "显示在 Visual Studio JavaScript 控制台窗口中,如图 2-2 所示。

A978-1-4842-0719-2_2_Fig2_HTML.jpg

图 2-2。

Display the string in the JavaScript console window in Visual Studio 2015

请注意,名称空间应该只包含类、函数、常数和其他名称空间。

2.3 在 WinJS 中创建类

问题

您需要在 Windows 运行时应用中用 JavaScript 代码创建一个类。

解决办法

使用WinJS.Class.define方法在 WinJS 中创建一个类。

它是如何工作的

C#和 VB.NET 是面向对象的语言。它们对语言中面向对象的概念有很好的实现和支持;其中一个功能是创建类。另一方面,JavaScript 没有创建类的内置支持。JavaScript 中的一切都被视为对象。

WinJS 允许开发人员创建类并在他们的应用中使用它们。

您可以使用WinJS.Class.define方法在 WinJS 中创建新类。

WinJS.Class.define方法有三个参数。

  • 构造函数:第一个参数让开发人员初始化一个新对象。
  • 实例成员:第二个参数是实例成员的集合,包括属性和方法。
  • 静态成员:第三个参数包括静态属性和静态方法。

打开项目中的WinJSFundamentals.js文件,并用下面的代码片段替换它。

// Create a class called Author

var Author = WinJS.Class.define(

function (name, title) {

this.name = name;

this.title = title;

},

{

_Name: undefined,

_title: undefined,

name : {

set :function(value)

{

this._Name = value;

},

get :function()

{

return this._Name;

}

},

title : {

set :function(value)

{

this._title = value;

},

get :function()

{

return this._title;

}

}

});

// instantiate the author class by invoking the constructor with 2 parameters

var author1 = new Author("Senthil", "WinJS recipes");

// display the name and the title  in the console window.

console.log(author1.name);

console.log(author1.title);

在前面的代码片段中,Author类是使用WinJS.Class.define方法创建的。该方法的第一个参数是构造函数,它接受两个参数并初始化名称和标题。

Author类有两个属性。

  • 标题与其backing field _title
  • 名称与其backing field _name

这两个属性都包含一个 getter 方法和一个 setter 方法。例如,看看下面的属性。

title : {

set :function(value)

{

this._title = value;

},

get :function()

{

return this._title;

}

}

title属性有一个set方法,它允许开发人员为该属性设置一个值。类似地,您可以使用带有get方法的title属性来检索_title的值。从开发人员的角度来看,调用<PropertyName>对象足以获取或设置值。

运行 Windows 项目。您应该看到实例化对象时使用的名称和标题,如图 2-3 所示。

A978-1-4842-0719-2_2_Fig3_HTML.jpg

图 2-3。

Displaying the name and title in the JavaScript console window in Visual Studio 2015

温家。类命名空间为定义类提供了以下帮助函数。

  • define:这个函数使用指定的构造函数和实例成员定义一个类。
  • derive:这个函数使用原型继承为指定的类创建一个子类。
  • mix:这个函数使用指定的构造函数定义一个类,并组合所有 mixin 对象指定的实例成员集合。

2.4 在 WinJS 中派生类

问题

您需要在 WinJS 应用中应用继承概念。

解决办法

在 WinJS 中使用WinJS.Class.derive方法从一个类派生另一个类。

它是如何工作的

WinJS 库提供了WinJS.Class.derive方法,允许开发人员应用继承来从一个类派生另一个类。WinJS.Class.derive方法采用以下参数。

  • 基类:当前类需要继承的类。
  • 构造函数:这个参数指的是可以用来初始化类成员的constructor函数。
  • 实例成员:该参数定义实例成员,包括属性和方法。
  • 静态成员:该参数定义静态属性和静态方法。

打开WinJSFundamentals.js文件,用下面的代码片段替换代码。

// Create a class called Employee

var Employee = WinJS.Class.define(

function () {

this.name = name;

this.type = "Employee";

},

{

_Name: undefined,

_type: undefined,

name : {

set :function(value)

{

this._Name = value;

},

get :function()

{

return this._Name;

}

},

type: {

set :function(value)

{

this._type = value;

},

get :function()

{

return this._type;

}

}

});

var ContractEmployee = WinJS.Class.derive(Employee,

function (name) {

this.name = name;

this.type = "Contract Employee";

});

var ContractEmployee1 = new ContractEmployee("Senthil");

// display the name and the title  in the console window.

console.log(ContractEmployee1.name);

console.log(ContractEmployee1.type);

这段代码片段创建了一个名为Employee的类。后来,创建了另一个名为ContractEmployee的类;它来自于Employee类。创建了一个契约雇员实例,其姓名和雇佣类型显示在控制台窗口中。

从 Visual Studio 运行 Windows 应用商店项目。这将在 JavaScript 控制台窗口中显示名称和类型,如图 2-4 所示。

A978-1-4842-0719-2_2_Fig4_HTML.jpg

图 2-4。

Displaying the name and type of employment in the JavaScript console window in Visual Studio 2015

WinJS.Class.derive函数的行为类似于WinJS.Class.define函数,除了它使用基类的原型使用Object.create函数来构造派生类。Object.create方法通过原型化父对象从一种类型派生出另一种类型;它还添加属于子对象的属性。

2.5 在 WinJS 中创建 Mixins

问题

您需要组合来自多个 JavaScript 对象的方法和属性,而不使用WinJS.Class.derive方法。

解决办法

使用WinJS.Class.mix方法组合 WinJS 中多个 JavaScript 对象的方法和属性。

它是如何工作的

WinJS.Class.derive方法使用原型继承,各有利弊。它需要额外的处理时间,并且会影响性能。这可以通过使用WinJS.Class.mix方法来克服。

WinJS.Class.mix方法有两个参数。

  • 构造函数:第一个参数,用于初始化类成员。
  • Mixin:第二个参数是接受 mixin 方法的数组

打开项目中的WinJSFundamentals.js文件,并用下面的代码片段替换它。

// Create a class called Employee

var Employee = WinJS.Class.define(

function () {

this.name = name;

this.type = "Employee";

},

{

_Name: undefined,

_type: undefined,

name : {

set :function(value)

{

this._Name = value;

},

get :function()

{

return this._Name;

}

},

type: {

set :function(value)

{

this._type = value;

},

get :function()

{

return this._type;

}

}

});

var ContractEmployee = WinJS.Class.mix(

function (name) {

this.name = name;

this.type = "Contract Employee";

},Employee);

var ContractEmployee1 = new ContractEmployee("Senthil");

// display the name and the title  in the console window.

console.log(ContractEmployee1.name);

console.log(ContractEmployee1.type);

在这个代码示例中,创建了一个Employee类,然后创建了另一个名为ContractEmployee的类;它继承自Employee类。请注意,您使用了mix方法,而不是derive方法。

嗯,代码可能看起来与使用derive方法的代码相似,但是 mixin 增加了更多的特性。其中一个特性是支持多重继承。由于mixin方法中的第二个参数是一个 mixins 数组,您可以让ContractEmployee类实现多个类的特性。

当您执行这个程序时,您会看到员工的姓名和类型,如图 2-5 所示。

A978-1-4842-0719-2_2_Fig5_HTML.jpg

图 2-5。

Displaying the name and employee type in the JavaScript console window in Visual Studio 2015

Mixins 可以用来给你的类型增加功能。Mixins 通常包含可以添加到 WinJS 中许多类型的实现函数。

在 WinJS 中,您可以使用以下 mixins 之一来管理事件和绑定。

  • 这个 mixin 可以用来给你定义的任何类型添加事件管理功能。它包括像WinJS.Utilities.eventMixin.addEventListenerWinJS.Utilities.eventMixin.removeEventListenerWinJS.Utilities.eventMixin.dispatchEvent这样的函数来引发和处理您定义的自定义事件。
  • WinJS.Binding.dynamicObservableMixin:该函数用于添加绑定管理功能,开发者可以将自定义对象绑定到一个控件上,该控件能够在属性值发生变化时通知监听器。

2.6 WinJS 中的封装

问题

您希望构建一个库,并且希望只向外部访问公开其中的一些方法。您需要支持 WinJS 应用中的封装。

解决办法

使用函数和名称空间的功能来实现这一点。变量可以有全局作用域或函数作用域。这个特性可以用来在 JavaScript 中引入封装功能。

它是如何工作的

当您创建自己的 JavaScript 库时,您可能希望同时创建公共和私有方法。公共方法可以作为 API 公开,并且可以由第三方开发人员使用。

这里的问题是 JavaScript 不支持访问修饰符。JavaScript 中的变量有以下范围。

  • 全局范围:这在整个应用中都是可用的。
  • 函数作用域:这仅在函数内部可用。

WinJS 中使用了函数作用域特性来隐藏方法,使其具有一定的私有性。通过手动将方法添加到命名空间,可以将方法公开为公共的。

设想一个场景,您正在编写一个库来跟踪页面浏览量并显示每百万成本(CPM)印象。您希望向用户公开GetPageViews方法,而不是GetCPMRate方法。这是你怎么做的…

打开共享项目中的WinJSFundamentals.js文件,并用下面的代码片段替换它。

(function (global) {

// public method

function GetPageViews()

{

return 1000;

}

//private method.

function GetCPMRate()

{

return 1;

}

WinJS.Namespace.define("DeveloperPublish",

{

GetPageViews: GetPageViews

});

})(this);

console.log(DeveloperPublish.GetPageViews());

自执行匿名函数有两种方法:GetPageViewsGetCPMRateDeveloperPublish名称空间用于公开或导出GetPageViews函数,并为其提供公共访问。GetCPMRate则相反,是一种私有的方法。您可以在全局范围方法中调用GetCPMRate方法,但不能使用DeveloperPublish名称空间。例如,下面的代码片段演示了使用DeveloperPublish名称空间公开GetPageViewsGetTotalRate函数的场景;GetCPMRate仅在GetTotalRate内使用。

(function (global) {

// public method

function GetPageViews() {

return 1000;

}

//private method.

function GetCPMRate() {

return 2;

}

function GetTotalRate() {

return GetPageViews() * GetCPMRate();

}

WinJS.Namespace.define("DeveloperPublish",

{

GetPageViews: GetPageViews,

GetTotalRate: GetTotalRate

});

})(this);

console.log(DeveloperPublish.GetPageViews());

console.log(DeveloperPublish.GetTotalRate());

运行 Windows 项目。在图 2-6 中,您会看到GetPageViews方法在 Visual Studio JavaScript 控制台窗口中显示 1000。

A978-1-4842-0719-2_2_Fig6_HTML.jpg

图 2-6。

Display the string in the JavaScript console window in Visual Studio 2015

当你试图访问自执行匿名函数之外的GetCPMRate方法时,你会得到下面的错误(也见图 2-7 )。

A978-1-4842-0719-2_2_Fig7_HTML.jpg

图 2-7。

Error when trying to access private methods

0x800a1391: JavaScript runtime error: 'GetCPMRate' is undefined.

这是一个有用的特性,尤其是当您正在构建一个库,并且希望限制对 WinJS 中某些方法的访问时。

2.7 在 WinJS 中使用 Promise

问题

您需要异步执行代码,以便 UI 响应更快。

解决办法

您可以在通用 Windows 应用中使用异步编程,这样某些方法的处理就可以异步完成。通过这种方式,你的应用的 UI 线程是免费的,并且可以响应用户的输入。

它是如何工作的

WinJS 和通用 Windows 应用中的异步 API 被表示为承诺。WinJS 中 promise 的一个常见实现是xhr函数,它将 XMLHttpRequest 包装在 promise 中。当您提供一个 URL 和响应类型时,xhr函数返回承诺,通过返回数据来实现,或者如果失败则返回一个错误。

在这个菜谱中,您将构建一个应用,它只是将 URL 作为输入,并尝试连接到它。结果是基于连接的成功或失败。

在 Visual Studio 2015 中,启动在之前的配方中构建的现有通用 Windows 应用。打开default.html页面,在 body 部分下添加以下div元素。这接受了inputurl文本框中的 URL,状态显示在输出div标签中。

<div>

<input id="inputurl"/>

</div>

<div id="output">

</div>

您需要将 change 事件处理程序添加到 input 元素中,当用户输入文本并按下 Enter 键时,将会触发该事件处理程序。您可以在default.js文件的app.onactivated事件处理程序的WinJS.Utilities.ready函数中添加这个,如下所示。

WinJS.Utilities.ready(function () {

var input = document.getElementById("inputurl");

input.addEventListener("change", changeEvent);

}, false);

下一步是添加changeEvent函数,需要通过传递用户输入的 URL 来调用xhr函数;这相应地更新了结果。xhr函数的返回类型是 promise,它允许开发人员使用 promise 的then函数异步更新 UI。

then函数最多有三个参数,包括

  • 如果承诺无误地实现,则执行的completed功能
  • 处理错误的error函数
  • progress功能显示承诺的进度

让我们在app.onactivated事件之后将changeEvent添加到default.js文件中,如下所示。

function changeEvent(e) {

var resultDiv = document.getElementById("output");

WinJS.xhr({ url: e.target.value }).then(function completed(result) {

if (result.status === 200) {

resultDiv.style.backgroundColor = "Green";

resultDiv.innerText = "Success";

}

},

function error(e) {

resultDiv.style.backgroundColor = "red";

resultDiv.innerText = e.statusText;

});

}

该代码包括承诺的completederror功能。它根据结果显示文本成功或错误,并改变输出div元素的颜色。

在本地机器上构建并运行应用,输入 URL,然后按回车键。如果 URL 有效,输出div标签变成绿色并显示成功消息。如果有错误,错误信息以红色背景显示,如图 2-8 所示。

A978-1-4842-0719-2_2_Fig8_HTML.jpg

图 2-8。

Using the xhr function to demonstrate the promise

您可以通过使用 promise 对象的cancel方法来停止当前正在执行的异步操作。

xhrPromise.cancel();

注意,您还可以通过调用前面的then函数返回的承诺上的then来链接承诺操作。

三、基本 WinJS 控件

本章概述了 WinJS 库中可用的控件,开发人员可以使用这些控件快速构建他们的 Windows 应用。它探讨了如何向页面添加 WinJS 控件,以及基本的 WinJS 控件,如 ToggleSwitch、Rating、DatePicker、TimePicker、tooltip、text 控件等。

WinJS 中有一些高级控件,可以用来在应用中列出记录、显示菜单或添加工具栏。(第四章介绍了 ListView、工具栏和 AppBar 等高级控件。)

3.1 在页面上声明 WinJS 控件

问题

您需要在 Windows 应用的页面上添加或声明 WinJS 控件。

解决办法

使用div标记中的data-win-control属性在页面上添加 WinJS 控件。

它是如何工作的

Create a new project using the Windows Universal (Blank App) template in Microsoft Visual Studio 2015. This creates a universal app that can be run on Windows tablets and Windows Mobile powered by Windows 10.   Open the default.html page from the project in Visual Studio Solution Explorer.   Declare a WinJS control on a page by using the data-win-control attribute. For example, to declare the Rating Control on a page, add the following div tag.  

<div id="rating" data-win-control="WinJS.UI.Rating"></div>

在这个代码片段中,div标记充当 WinJS 控件的占位符。data-win-control属性用于指示将要呈现的 WinJS 控件。

HTML 页面将如下所示。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe3.1</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe3.1 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

</head>

<body class="win-type-body">

<div id="rating" data-win-control="WinJS.UI.Rating"></div>

</body>

</html>

在页面上使用 WinJS 控件的主要要求是包含 JavaScript 和 CSS 文件。您应该在 HTML 页面的 head 部分添加以下引用。

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

WinJS 库提供了两个 CSS(层叠样式表)文件:ui-dark.cssui-light.css。通过分别切换到ui-light.cssui-dark.css,您可以在所有控件的亮主题和暗主题之间切换。

base.jsui.js文件是 JavaScript 文件,需要在 HTML 页面中引用以使用 WinJS 控件。WinJS 控件的 JavaScript 源代码在这些 JavaScript 文件之一中定义。

在调用WinJS.UI.processAll方法之前,WinJS 控件(在本例中,它是 Rating 控件)不会被呈现。该方法在项目的js文件夹下的default.js文件中定义。WinJS.UI.processAll方法的主要功能是解析 HTML 页面,用data-win-control识别属性,并相应地生成控件。

因此,有必要在页面上包含对default.js文件的引用。

现在,让我们构建通用应用,并在 Windows 10 和 Windows Mobile 模拟器上运行它。

图 3-1 展示了分级控件在 Windows 平板电脑上的外观。图 3-2 展示了分级控件在 Windows Mobile 上的外观。

A978-1-4842-0719-2_3_Fig2_HTML.jpg

图 3-2。

Rating control on Windows Mobile emulator

A978-1-4842-0719-2_3_Fig1_HTML.jpg

图 3-1。

Rating control on Windows 10

3.2 WinJS 控件的设置选项

问题

您希望为 HTML 页面上的 WinJS 控件设置附加选项或属性。

解决办法

使用data-win-options属性为控件设置附加选项或属性。

它是如何工作的

大多数 WinJS 控件支持设置 options 属性。例如,在页面上使用分级控件时,您可能希望限制用户可以提供的最高分级。

您可以用data-win-options属性来指定这一点。例如,下面的 HTML 代码演示了如何将分级控件的最高分级设置为 4。

<div id="rating" data-win-control="WinJS.UI.Rating"

data-win-options="{maxRating:4}">

</div>

data-win-options采用 JavaScript 选项;它与属性名一起传递,其值用花括号括起来。

在这里,maxRating是一个属性。也可以传递多个属性及其值。例如,如果您需要设置enableClear属性和MaxRating,您可以用data-win-options属性来设置它,如下所示。

<div id="rating" data-win-control="WinJS.UI.Rating"

data-win-options="{maxRating:4,enableClear:false}">

</div>

图 3-3 展示了窗口移动仿真器上的屏幕及其显示。

A978-1-4842-0719-2_3_Fig3_HTML.jpg

图 3-3。

Rating control with maximum rating of 4

如果enableClear属性设置为 true,那么用户可以滑动到控件的左侧来清除评级值。

3.3 从 JavaScript 代码添加 WinJS 控件

问题

您需要从 JavaScript 代码中添加一个 WinJS 控件,而不是将其添加到 HTML 页面中。

解决办法

您可以强制创建控件;即完全使用 JavaScript 来识别div元素并动态生成控件并添加到页面中。

它是如何工作的

Create a new project using the Windows Universal (Blank App) template in the Visual Studio 2015 Community. This creates a Windows universal app that can be run on Windows tablets or on Windows Mobile running in Windows 10.   Open the project’s default.html page from the project in Visual Studio Solution Explorer.   Add a div tag in the body section of the page where you want the control to be rendered. <div id="rating" >     </div>   Right-click the js folder within the project in the Solution Explorer. Select Add ➤ New JavaScript File and provide a name for the file. In this example, let’s name the file controldemo.js. This adds the controldemo.js file under the js folder of the project.   Add the following code to the controldemo.js file. This creates a new rating control and adds it to the rating div tag. (function () {     "use strict";     function AddControl()     {         var ratingDiv = document.getElementById("rating");         var ratingCtrl = new WinJS.UI.Rating(ratingDiv);     }     document.addEventListener("DOMContentLoaded", AddControl); })(); The preceding code creates a new instance of the WinJS.UI.Rating JavaScript class. It is created by passing the rating div element to the constructor of the Rating class.   Now you need to add a reference to the controldemo.js file in the HTML page. Open the default.html file and add the following code snippet to the head section of the page. <script src="/js/controldemo.js"></script>  

页面将包含代码,如下所示。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe3.3</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe3.3 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/controldemo.js"></script>

</head>

<body class="win-type-body">

<div id="rating">

</div>

</body>

</html>

让我们在 Windows Mobile 模拟器上运行应用。图 3-4 展示了 Windows Mobile 上的输出页面。

A978-1-4842-0719-2_3_Fig4_HTML.jpg

图 3-4。

Rating control added from the JavaScript code

控件的选项或属性也可以通过 JavaScript 代码强制设置。下面展示了如何从 JavaScript 代码中创建 Rating 控件的实例并设置maximumRating属性。

(function () {

"use strict";

function AddControl()

{

var ratingDiv = document.getElementById("rating");

var ratingCtrl = new WinJS.UI.Rating(ratingDiv);

ratingCtrl.maxRating = 4;

}

document.addEventListener("DOMContentLoaded", AddControl);

})();

这段代码片段展示了如何设置maxRating属性,而不在构造函数中设置它。或者,您也可以通过将它传递给第二个参数来设置它,用花括号括起来。

图 3-5 演示了在 Visual Studio 中设置分级控制属性时的智能感知支持。

A978-1-4842-0719-2_3_Fig5_HTML.jpg

图 3-5。

IntelliSense support in Visual Studio 2015

Intellisense 是 Microsoft Visual Studio 中的一项重要功能,它可以提高开发人员的工作效率,并根据用户在 IDE 中键入的内容向开发人员提供自动建议。

3.4 从 HTML 文档中获取 WinJS 控件

问题

您希望从 HTML 页面获取控件,并使用 JavaScript 代码设置属性。

解决办法

使用winControl属性从页面的DOM元素获取控件。

它是如何工作的

Create a new project using the Windows Universal (Blank App) template in Visual Studio 2015 Community. This creates a Windows universal app that can be run on Windows tablets and Windows Mobile running Windows 10.   Open the default.html page from the project in Visual Studio Solution Explorer.   Add the Rating control to the body section of the page. <div id="rating" data-win-control="WinJS.UI.Rating" >     </div>   Right-click on the js folder within the project in the Solution Explorer. Select Add ➤ New JavaScript File and provide a name for the file. In this example, let’s name the file controldemo.js. This adds the controldemo.js file under the js folder of the project.   Add the following code to the controldemo.js file. (function () {     "use strict";     function GetControl() {         WinJS.UI.processAll().done(function () {             var ratingControl = document.getElementById("rating").winControl;             ratingControl.userRating = 2;         });     }     document.addEventListener("DOMContentLoaded", GetControl); })();   When you invoke the document.getElementById method, you get the DOM element. You need to use the winControl property to get the associated control.   This needs to be surrounded by the WinJS.UI.processAll method, which returns the promise. The reason for surrounding your logic with the processAll method is that you have to wait until all the controls are created and parsed in the document before trying to retrieve it.   Once the Rating control is retrieved, you can start setting the values to the properties of the Rating control instance. In this example, you are setting the user rating to 2.   Finally, you need to add the reference of the controldemo.js file in the default.html page. Open the default.html page from Visual Studio Solution Explorer and add the following code to the head tag. <script src="/js/controldemo.js"></script>  

当您在 Windows Mobile 模拟器上运行应用时,您应该会看到如图 3-6 所示的屏幕。

A978-1-4842-0719-2_3_Fig6_HTML.jpg

图 3-6。

Windows Mobile emulator displaying the Rating control with value 2

3.5 拨动开关控制

问题

您需要为用户提供一个在屏幕上执行二进制操作的选项。例如,您需要为用户提供打开或关闭服务的选项。

解决办法

使用 WinJS 中的 ToggleSwitch 控件。它类似于标准的复选框控件,但具有更好的触摸支持。您只需用手指滑过 ToggleSwitch 控件即可选中或取消选中该选项。您可以使用 WinJS 在页面上声明 ToggleSwitch 控件。将 UI.ToggleSwitch 值赋给div元素的data-win-control属性。

它是如何工作的

下面演示如何在页面上声明 ToggleSwitch 控件。

<div id="locationServices" data-win-control="WinJS.UI.ToggleSwitch"

data-win-options="{

title :'Location Services',

labelOff: 'Disabled',

labelOn:'Enabled',

checked: true

}">

</div>

当在 Windows 平板电脑或 Windows Mobile 模拟器上执行时,前面的代码片段将如图 3-7 所示。

A978-1-4842-0719-2_3_Fig7_HTML.jpg

图 3-7。

ToggleSwitch on the Windows Mobile and Windows emulator

data-win-options属性用于设置 ToggleSwitch 控件的附加属性。在前面的例子中,像标题、labelOfflabelOnChecked这样的属性是使用这个属性设置的。

title 为 ToggleSwitch 设置标题内容。labelOfflabelOn属性根据控件的选中(开)和未选中(关)状态标识需要显示在 ToggleSwitch 旁边的文本。

使用控件的 checked 属性可以找到 ToggleSwitch 的当前状态(选中或未选中)。

让我们向项目的js文件夹添加一个新的 JavaScript 文件,并将其命名为 controldemo.js。打开default.html页面,添加 ToggleSwitch 控件和一个空的div标签,以显示切换开关状态变化的消息。

default.html看起来如下。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe3.5</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe3.5 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/controldemo.js"></script>

</head>

<body class="win-type-body">

<div id="locationServices" data-win-control="WinJS.UI.ToggleSwitch"

data-win-options="{

title :'Location Services',

labelOff: 'Disabled',

labelOn:'Enabled',

checked: true

}">

</div>

<div id="info"></div>

</body>

</html>

为了从 JavaScript 代码中识别状态,您需要连接 ToggleSwitch 控件的 change 事件处理程序。当您更改控件的状态时,会触发此事件。

打开controldemo.js文件,用下面的代码替换它。

(function () {

"use strict";

function GetControl() {

WinJS.UI.processAll().done(function () {

var toggleButton = document.getElementById("locationServices").winControl;

var InfoElement = document.getElementById("info");

toggleButton.addEventListener('change', function (args) {

if (toggleButton.checked) {

InfoElement.innerHTML = "Location Services enabled";

}

else {

InfoElement.innerHTML = "Location Services disabled";

}

})

});

}

document.addEventListener("DOMContentLoaded", GetControl);

})();

当您在 Windows 10 模拟器和 Windows Mobile 模拟器上运行应用时,您将看到如图 3-8 所示的屏幕。

A978-1-4842-0719-2_3_Fig8_HTML.jpg

图 3-8。

ToggleSwitch with the change event.

当您切换控件时,适当的消息会显示在Info div元素中。

3.6 日期选择器控件

问题

您希望允许用户从应用页面选择日期。

解决办法

使用允许用户选择日期的 WinJS DatePicker 控件。该控件显示三个列表:月、日和年各一个。

它是如何工作的

您可以在页面上声明 DatePicker 控件,如下所示。

<div id="Birthday" data-win-control="WinJS.UI.DatePicker" >

</div>

在这个菜谱中,让我们尝试在页面上添加 DatePicker 控件,并在 JavaScript 代码中绑定事件,以在一个div元素中显示所选日期。

Create a new project using the Windows Universal App template in Visual Studio 2015.   Open the default.html page and replace it with the following. <!DOCTYPE html> <html> <head>     <meta charset="utf-8" />     <title>Recipe3.6</title>     <!-- WinJS references -->     <link href="WinJS/css/ui-light.css" rel="stylesheet" />     <script src="WinJS/js/base.js"></script>     <script src="WinJS/js/ui.js"></script>     <!-- Recipe3.6 references -->     <link href="/css/default.css" rel="stylesheet" />     <script src="/js/default.js"></script>     <script src="/js/controldemo.js"></script> </head> <body class="win-type-body">     <div id="Birthday" data-win-control="WinJS.UI.DatePicker">     </div>     <div id="info"></div> </body> </html> The default.html page contains the DatePicker control as well as the div tag with the name information to display the selected date. The controldemo.js file is referenced, which you create next.   Add a new JavaScript file to the project’s js folder from Visual Studio Solution Explorer and name it controldemo.js. Add the following JavaScript code to the controldemo.js file. (function () {     "use strict";     function GetControl() {         WinJS.UI.processAll().done(function () {             var datepick = document.getElementById("Birthday").winControl;             var InfoEelement = document.getElementById("info");             datepick.addEventListener('change', function (args) {                 InfoEelement.innerHTML = "The selected date is " +                     datepick.current.toDateString();             })         });     }     document.addEventListener("DOMContentLoaded", GetControl); })();  

只要您更改日期、月份或年份,DatePicker 就会引发 change 事件。您可以通过处理该事件来获取当前选定的日期。

在 JavaScript 代码中,document.getElementByIdwinControl属性用于从 HTML 页面获取 DatePicker。从 DatePicker 控件调用addEventListener方法来订阅变更事件。

使用 DatePicker 的 current 属性检索选定的日期。

在 Windows Mobile 或 Windows 10 上运行应用会显示日期选择器,并显示所选日期,如图 3-9 所示。

A978-1-4842-0719-2_3_Fig9_HTML.jpg

图 3-9。

DatePicker control demo

通过分配格式字符串,可以控制 DatePicker 控件的年、月和日期字段的外观。

例如,可以对 DatePicker 进行格式化,以两位数格式显示缩写的月份和年份以及日期,如下所示。

<div id="Birthday" data-win-control="WinJS.UI.DatePicker"

data-win-options="{

monthPattern : '{month.abbreviated}',

datePattern: '{day.integer(2)}',

yearPattern: '{year.abbreviated}'

}">

</div>

使用monthPatterndatePatternyearPattern属性设置格式。

monthPattern属性定义了月份的显示模式。您可以使用表 3-1 中显示的值之一设置月模式属性。

表 3-1。

Month Pattern for the date picker

| 模式 | 描述 | | --- | --- | | 完整月份 | 这将显示月份的全名。 | | 月份。缩写(n) | 您可以使用带或不带参数的 month .缩写。参数指定一个月的字母数。 | | month.solo .完整 | 这表示适合独立显示的月份。并且,month . solo . abstracted 可以带参数使用,也可以不带参数使用。 | | 月.整数(n) | month.integer 用于指定月字段中显示的整数个数。 |

datePattern属性用于获取或设置 DatePicker 控件中日期的显示模式。您可以用表 3-2 中显示的值之一设置datePattern

表 3-2。

Date Pattern for the date picker

| 模式 | 描述 | | --- | --- | | day .整数(n) | 您可以使用带参数或不带参数的 day.integer。参数指定要包含的前导零;例如,如果值为 day.integer (2 ),则显示 02。 | | dayofweek .缩写 | 此属性显示一周中的某一天。参数指定要显示的字母数。 |

属性获取或设置年份的显示模式。默认的年模式是 year.full。您可以将其修改为表 3-3 中显示的任一值。

表 3-3。

Year pattern for the date picker

| 模式 | 描述 | | --- | --- | | 全年 | 以数字显示完整的年份 | | 年份。缩写(n) | 用指定的一组数字显示年份。 |

3.7 时间选择器控件

问题

您希望允许用户从应用页面选择时间。

解决办法

使用允许用户选择时间的 WinJS TimePicker 控件。该控件显示三个列表:小时、分钟和时间段(AM/PM)各一个。

它是如何工作的

您可以在页面上声明 DatePicker 控件,如下所示。

<div id="timeSelector" data-win-control="WinJS.UI.TimePicker" >

</div>

在这个菜谱中,让我们尝试在页面上添加 TimePicker 控件,并在 JavaScript 代码中绑定事件,以在一个div元素中显示所选时间。

Create a new project using the Windows Universal App template in Visual Studio 2015.   Open the default.html page and replace it with the following. <!DOCTYPE html> <html> <head>     <meta charset="utf-8" />     <title>BasicControls</title>     <!-- WinJS references -->     <link href="WinJS/css/ui-light.css" rel="stylesheet" />     <script src="WinJS/js/base.js"></script>     <script src="WinJS/js/ui.js"></script>     <!-- Recipe3.7 references -->     <link href="/css/default.css" rel="stylesheet" />     <script src="/js/default.js"></script>     <script src="/js/controldemo.js"></script> </head> <body class="win-type-body">     <div id="timeSelector" data-win-control="WinJS.UI.TimePicker">     </div>     <div id="info"></div> </body> </html> The default.html page contains the TimePicker control as well as the div tag with the name information to display the selected time. The controldemo.js file is referenced, which you will create in the next step.   Add a new JavaScript file to the project’s js folder from the Visual Studio Solution Explorer and name it controldemo.js. Replace the file with the following JavaScript code. (function () {     "use strict";     function GetControl() {         WinJS.UI.processAll().done(function () {             var datepick = document.getElementById("timeSelector").winControl;             var InfoEelement = document.getElementById("info");             datepick.addEventListener('change', function (args) {                 InfoEelement.innerHTML = "The selected time is " +                     datepick.current.toTimeString();             })         });     }     document.addEventListener("DOMContentLoaded", GetControl); })();  

只要您更改了小时、分钟或时间段,TimePicker 就会引发 change 事件。您可以通过处理该事件来获取当前选定的时间。

在 JavaScript 代码中,document.getElementByIdwinControl属性用于从 HTML 页面获取时间选择器。从 TimePicker 控件调用addEventListener方法来订阅变更事件。

使用 TimePicker 控件的 current 属性检索选定的时间。

在 Windows Mobile 或 Windows 10 上运行应用会显示时间选择器并显示所选时间,如图 3-10 所示。

A978-1-4842-0719-2_3_Fig10_HTML.jpg

图 3-10。

TimePicker control demo

通过使用data-win-options属性设置 clock 属性,可以将 TimePicker 设置为支持 24 小时制,如下所示。

<div id="timeSelector" data-win-control="WinJS.UI.TimePicker"

data-win-options="{

clock : '24HourClock',

minuteIncrement : 15

}">

</div>

可以用minuteIncrement属性控制分钟列表的增量值,如下所示。

当您在 Windows 10 或 Windows Mobile 10 上运行该页面时,您会看到如图 3-11 所示的屏幕。

A978-1-4842-0719-2_3_Fig11_HTML.jpg

图 3-11。

TimePicker with the 24-hour clock format and timeInterval adjustment

通过分配格式字符串,可以控制 TimePicker 控件的小时、分钟和周期字段的外观。

使用hourPatternminutePatternperiodPattern属性设置格式。

hourPattern属性设置小时的显示模式。hourPattern属性的默认值是 hour.integer(2 ),您可以通过更改参数值来修改hourPattern属性。属性获取或设置分钟的显示模式。此属性的默认值是 minute.integer (2 ),您可以通过更改参数中的整数数目来修改此模式。periodPattern属性获取或设置周期的显示模式;该属性的默认值是 period.abbreviated (2)。您可以通过更改参数值来修改此属性的模式。

表 3-4。

Pattern for hours, minutes and period in timepicker

| 模式 | 描述 | | --- | --- | | hour.integer(n) | 这将显示小时的指定位数。 | | {minute.integer(n)} | 这将显示分钟的指定位数。 | | {句点.缩写(n)} | 基于作为参数传递的值的期间显示模式。 |

3.8 工具提示控件

问题

当用户将鼠标悬停在页面上的任何元素上时,您需要显示工具提示。

解决办法

使用 WinJS Tooltip 控件在页面上的 HTML 元素上显示工具提示。当您将光标悬停在某个元素上时,工具提示会显示指定的秒数。当用户将光标从元素上移开时,工具提示应该会消失。

它是如何工作的

为按钮添加工具提示控件,如下所示:

<button id="btnSave"

data-win-control="WinJS.UI.Tooltip"

data-win-options="{

innerHTML: 'Saves the <b>Employee</b> record'}">

Save

</button>

通过data-win-options属性设置innerHTML属性,该属性设置工具提示控件的文本。这个文本也可以包含 HTML 标签。

图 3-12 展示了工具提示在 Windows Mobile 10 和 Windows 10 平板电脑上的显示方式。

A978-1-4842-0719-2_3_Fig12_HTML.jpg

图 3-12。

Tooltip displayed within the app

您可以通过修改win-tooltip CSS 类来自定义工具提示控件的样式。

从 CSS 文件夹中打开default.css文件,并将以下代码添加到文件的末尾。

.win-tooltip

{

background-color: bisque;

border-radius:30px;

border-color:red;

}

图 3-13 展示了定义了前面提到的样式后工具提示控件的外观。

A978-1-4842-0719-2_3_Fig13_HTML.jpg

图 3-13。

Tooltip with styling

注意,当使用 div 元素作为工具提示的容器时,需要将其 display 属性设置为 inline block,因为 div 元素的显示设置默认为 block。

3.9 显示文本

问题

您需要在 Windows 应用的页面上显示文本或标签。

解决办法

使用传统的 HTML 元素或标签在 Windows 应用的页面上显示文本。这些包括 div、标签、段落、标题等等。

它是如何工作的

HTML 元素(如标签、div、段落、标题等)是使用 JavaScript 在 Windows 通用应用上显示只读文本的一些常用控件。

您可以定义一个简单的 label 控件并设置其文本,如下所示。

<label>Welcome to the Windows 10 App Development World</label>

<div>by Microsoft MVPs</div>

可以使用两种方法之一将样式应用于显示文本:inline 或 CSS。

下面的代码片段演示了如何使用 inline style 属性来格式化文本。

<div style="font-family:Verdana">Welcome to the Windows 10 App Development World</div>

<p style="margin:0px; color:blue; font-family:Arial; font-size:18px">Welcome to the Windows 10 App Development World</p>

图 3-14 展示了使用内嵌样式属性的上述代码的输出。

A978-1-4842-0719-2_3_Fig14_HTML.jpg

图 3-14。

Styling the read-only text

CSS 允许开发人员在一个地方定义一个样式,然后在多个控件中重复使用。

3.10 在应用中编辑文本

问题

您需要允许用户在您的 Windows 应用页面上输入文本。

解决办法

使用 HTML 元素允许用户在页面上输入文本。这包括文本框、文本区域、密码输入框、富文本框等等。

它是如何工作的

使用 JavaScript 的 Windows 通用应用有四种不同类型的文本输入元素。

  • 文本框:该控件允许用户在单行中输入或编辑纯文本。
  • 文本区域:该控件支持多行,允许用户输入或编辑纯文本。
  • 密码输入框:该控件允许用户输入密码。
  • 格式文本框:该控件允许用户编辑需要格式化的文本。

这是一个简单的文本框、文本区域和密码输入框的 HTML。

<div><textarea id="textarea1" rows="2"></textarea></div>

<div><input type="text" /></div>

<div><input id="password" type="password" placeholder="Enter password" /></div>

图 3-15 展示了控件在 Windows Mobile 10 模拟器上的显示方式。

A978-1-4842-0719-2_3_Fig15_HTML.jpg

图 3-15。

Editable controls

一旦用户执行了一些动作,比如点击按钮,你就可以从 JavaScript 代码中获取控件的内容,如方法 3-4 所示。

四、列表控件、应用栏和工具栏

本章重点介绍与数据采集相关的控件,包括 Repeater、FlipView 和 ListView。本章还介绍了菜单相关控件的制作方法,如应用栏、工具栏、弹出菜单、上下文菜单和菜单输出。

4.1 使用中继器控制

问题

您需要使用 WinJS Repeater 控件在用户界面(UI)上显示数据集合。

解决办法

Repeater 控件是 WinJS 库中可用于在 UI 上显示集合数据的控件之一。您可以通过将data-win-control属性设置为 WinJS 来添加 Repeater 控件。容器的值,然后通过使用data-win-bind属性将属性绑定到 UI 中的控件。

它是如何工作的

为了演示 Repeater 控件的使用,让我们构建一个通用的 Windows 应用,显示一个雇员列表的 HTML 表,如图 4-1 所示。

A978-1-4842-0719-2_4_Fig1_HTML.jpg

图 4-1。

HTML table with a Repeater control

启动 Visual Studio 2015,并使用 JavaScript 模板创建一个新的 Windows 通用项目。

打开default.html页面,用下面的代码片段替换它。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.1</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body style="margin:20px">

<h1>Recipe 4.1</h1>

<table>

<thead>

<tr>

<th> Employee ID</th>

<th> Employee Name</th>

<th> Employee Designation</th>

</tr>

</thead>

<tbody id="repeaterData" data-win-control="WinJS.UI.Repeater">

<tr>

<td data-win-bind="textContent:id"></td>

<td data-win-bind="textContent:name"></td>

<td data-win-bind="textContent:designation"></td>

</tr>

</tbody>

</table>

</body>

</html>

在前面的代码片段中,Repeater 控件被添加到 body 部分;而 Repeater 控件的内部内容被用作模板。来自 repeater 数据的每一行都显示在 HTML 表的 body 部分。

前面的 HTML 页面引用了一个data.js页面。让我们将这个文件添加到项目中。向项目的js文件夹中添加一个新的 JavaScript 文件,并将其命名为 data.js。

(function () {

"use strict";

function Initialize() {

WinJS.UI.processAll().done(function () {

var repeaterControl1 = document.getElementById('repeaterData').winControl;

var Employees = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", designation: "Mobile Developer" },

{ id: 2, name: "Lohith GN", designation: "Web Developer" },

{ id: 3, name: "Vidyasagar", designation: "Game Developer" }

]);

repeaterControl1.data = Employees;

})

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

WinJS.Binding.List用于绑定中继器控件。在前面的代码片段中,Repeater 控件被绑定到 employees 列表,该列表表示雇员数据的集合。employee 对象包含以下属性:id、姓名和职务。使用 Repeater 控件的 data 属性绑定数据。

在 Windows Mobile 模拟器上运行应用。您应该会看到如图 4-2 所示的屏幕。

A978-1-4842-0719-2_4_Fig2_HTML.jpg

图 4-2。

Repeater control in Windows Mobile 10

如果希望 Repeater 控件中的项可调用或可选择,其中一个选择是在 Repeater 控件模板中使用 ItemContainer 控件。

下面的示例演示 ItemContainer 在 Repeater 控件中的用法,该控件绑定到雇员列表。

<div id="repeaterData" data-win-control="WinJS.UI.Repeater">

<div data-win-control="WinJS.UI.ItemContainer" data-win-bind="dataset.name:name">

<div data-win-bind="textContent:name"></div>

</div>

</div>

ItemContainer 有一个名为data-win-bind="dataset.name: name"属性的属性,它将雇员列表中每一项的名称与 ItemContainer 相关联。

Repeater 控件被绑定到 JavaScript 文件中的雇员列表,如下所示。

(function () {

"use strict";

function Initialize() {

WinJS.UI.processAll().done(function () {

var repeaterControl1 = document.getElementById('repeaterData').winControl;

var Employees = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", designation: "Mobile Developer" },

{ id: 2, name: "Lohith GN", designation: "Web Developer" },

{ id: 3, name: "Vidyasagar", designation: "Game Developer" }

]);

repeaterControl1.data = Employees;

repeaterControl1.addEventListener("invoked",function(e)

{

var name = e.target.dataset.name;

var message = new Windows.UI.Popups.MessageDialog(name);

message.showAsync();

})

})

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

当您在 Windows 中运行应用时,您会看到三个项目正在呈现。如果点击一个项目,会显示一个带有项目名称的消息框,如图 4-3 所示。

A978-1-4842-0719-2_4_Fig3_HTML.jpg

图 4-3。

Item in the Repeater control that is invokable

4.2 使用 FlipView 控件

问题

您只需要显示集合中的单个项目。

解决办法

使用 WinJS 中的 FlipView 控件,该控件一次仅显示集合中的单个项目。FlipView 控件的一个用例是一个照片库应用,用户可以在其中选择一个图像,然后在图像列表中滑动。

虽然一次只显示一项,但 FlipView 控件显示箭头,使您可以移动到数据源中的下一项或上一项。

通过用 WinJS 设置div元素的data-win-control属性,可以将 ListView 控件添加到页面中。列表视图值。

它是如何工作的

让我们在 Visual Studio 2015 中创建新的 Windows 通用项目。在js文件夹下将新的 JavaScript 文件命名为 data.js。这个 JavaScript 文件将包含可以在 ListView 中列出的数据。将下面的代码片段添加到data.js文件中。

(function () {

"use strict";

var Employees = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", designation: "Mobile Developer" },

{ id: 2, name: "Lohith GN", designation: "Web Developer" },

{ id: 3, name: "Vidyasagar", designation: "Game Developer" }

]);

WinJS.Namespace.define("recipeData",

{

Employees :Employees

});

})();

前面的 JavaScript 包含一个雇员集合;每个雇员都有一个 id、一个姓名和一个指定属性。

现在,您希望在 Windows 应用中一次显示一名员工。下面的 HTML 代码片段说明了如何使用 FlipView 控件显示雇员列表中的单个雇员。

请注意,该页面包含对data.js文件的引用,该文件包含 FlipView 控件的数据。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.2</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.2 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body class="win-type-body" style="margin:20px">

<h1>Recipe 4.2</h1>

<div id="template" data-win-control="WinJS.Binding.Template">

<div>

<h4 data-win-bind="innerText: name"></h4>

<h6 data-win-bind="innerText: designation"></h6>

</div>

</div>

<div id="flipView1"

data-win-control="WinJS.UI.FlipView"

data-win-options="{itemTemplate: select('#template') ,

itemDataSource : recipeData.Employees.dataSource}">

</div>

</body>

</html>

当您在 Windows 上运行该应用时,您应该会看到如图 4-4 所示的页面。

A978-1-4842-0719-2_4_Fig4_HTML.jpg

图 4-4。

FlipView in the WinJS app

FlipView 是用下面的 HTML 标记声明的。

<div id="flipView1"

data-win-control="WinJS.UI.FlipView"

data-win-options="{itemTemplate: select('#template') ,

itemDataSource : recipeData.Employees.dataSource}">

</div>

使用itemDataSource属性将 FlipView 绑定到雇员列表。在前面的代码片段中,FlipView 绑定到雇员列表,其类型为 WinJS.Binding.List。

请注意,FlipView 显示来自实现 IListDataSource 接口的数据源的数据。这方面的一个例子包括 WinJS。Binding.List 和 WinJS.UI.StorageDataSource。

此外,FlipView 的itemTemplate属性被设置为 id 为template的 TemplateControl。它包含用于格式化 ListView 中显示的员工详细信息的模板。在本例中,模板被配置为显示名称和称号。

4.3 使用 ListView 控件

问题

您需要在页面上显示一个交互式项目列表。

解决办法

使用 ListView 控件,它为开发人员提供了许多列出项目的选项,以及其他选项,如选择、排序、筛选、分组等。通过用 WinJS 设置data-win-bind属性,可以将 ListView 添加到页面中。列表视图值。

它是如何工作的

ListView 控件是 Windows 应用中最常用的控件之一。可以将 ListView 控件绑定到实现 IListDataSource 接口的数据源。目前,WinJS 有两个实现 IListDataSource 接口的对象。

  • WinJS。绑定.列表
  • WinJS。UI.StorageDataSource

在这个食谱中,我们将重点介绍如何使用 WinJS。绑定。列表数据源。

让我们看看如何在 WinJS 中使用 ListView 控件。绑定。列表数据源。

在 Visual Studio 2015 中新建一个 Windows 通用应用,打开default.html页面。用下面的代码替换它。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.3</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.3 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body class="win-type-body">

<h1>Recipe 4.3</h1>

<div id="template" data-win-control="WinJS.Binding.Template">

<div>

<h4 data-win-bind="innerText: name"></h4>

<h6 data-win-bind="innerText: designation"></h6>

</div>

</div>

<div id="listView1"

data-win-control="WinJS.UI.ListView"

data-win-options="{itemTemplate: select('#template')}">

</div>

</body>

</html>

下面的代码用于将 ListView 控件添加到页面中。

<div id="listView1"

data-win-control="WinJS.UI.ListView"

data-win-options="{itemTemplate: select('#template')}">

</div>

前面的代码片段中显示的 ListView 控件使用模板来显示每个雇员。

注意,您已经在 HTML 页面中引用了data.js文件。该文件包含雇员数组。向项目的js文件夹中添加一个新的 JavaScript 文件,并将其命名为 data.js。

(function () {

"use strict";

function Initialize() {

WinJS.UI.processAll().done(function () {

var listControl1 = document.getElementById('listView1').winControl;

var Employees = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", designation: "Mobile Developer" },

{ id: 2, name: "Lohith GN", designation: "Web Developer" },

{ id: 3, name: "Vidyasagar", designation: "Game Developer" },

{ id: 4, name: "Michael", designation: "Architect" }

]);

listControl1.itemDataSource = Employees.dataSource;

listControl1.addEventListener("iteminvoked", function (e) {

var index = e.detail.itemIndex;

e.detail.itemPromise.then(function (item) {

var message = new Windows.UI.Popups.MessageDialog(item.data.name);

message.showAsync();

})

})

})

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

从 employees 数组中创建一个列表,该数组使用itemDataSource属性绑定到 ListView 控件。

当您运行应用时,您会看到以列表视图显示的员工数据。

JavaScript 代码还包括处理 ListView 的调用事件的代码,该事件显示从列表中选择的雇员。

ListView 控件在内部对每个 ListView 项使用 ItemContainer 控件。您可以处理 ListView 控件的 item-invoked 事件,以检测何时单击了特定的 ListView 项。

图 4-5 显示了在 Windows 中呈现的屏幕,其中包含该食谱中的代码片段。

A978-1-4842-0719-2_4_Fig5_HTML.jpg

图 4-5。

ListView control in Windows app with the invoked event handling

ListView 控件支持不同的布局,这些布局可以决定控件的整体外观。这些布局包括

  • 网格布局
  • 列表布局
  • 跨单元布局

网格布局以网格格式显示 ListView 项,包含行和列。列表布局在单个列表中显示列表项。跨单元格布局将列表项显示为网格布局,但支持多列单元格。

要将 ListView 设置为网格布局,请将layout属性设置为 WinJS。在the data-win-options属性下的 UI.GridLayout,如下所示。

<div id="listView1"

data-win-control="WinJS.UI.ListView"

data-win-options="{itemTemplate: select('#template'),

layout : {type:WinJS.UI.GridLayout,maximumRowsOrColumns : 1}}">

</div>

图 4-6 显示了使用网格布局时呈现的用户界面。

A978-1-4842-0719-2_4_Fig6_HTML.jpg

图 4-6。

Grid layout in ListView

您也可以将布局设置为以下值:

  • WinJS.UI .储存格扩充配置
  • WinJS.UI.ListLayout

4.4 过滤 ListView 控件中的项目

问题

您需要通过从与 ListView 关联的数据源中过滤列表视图中显示的项目来过滤它。

解决办法

你可以使用 WinJS。然后使用createFiltered方法创建一个新的过滤列表。createFiltered函数在列表的输入项上创建一个过滤的投影。

它是如何工作的

让我们演示一下 ListView 控件中的过滤功能。

Create a new Universal Windows app in Visual Studio 2015 using the JavaScript template.   Open the default.html page from the Solution Explorer and replace it with the following code.  

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.4</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.4 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body class="win-type-body">

<h1>Recipe4.4</h1>

<div>

<input id="txtSearch" />

</div>

<div id="template" data-win-control="WinJS.Binding.Template">

<h3 data-win-bind="innerText:name"></h3>

</div>

<div id="lstEmployees" data-win-control="WinJS.UI.ListView"

data-win-options="{itemTemplate:select('#template')}">

</div>

</body>

</html>

注意包含了设置数据源和执行过滤操作的data.js文件。这个 HTML 页面包含一个 id 为txtSearch的简单文本框和一个 ListView 控件。ListView 有一个关联的自定义模板,用于以格式化的方式显示数据。

让我们将 JavaScript 文件添加到项目的js文件夹中,并将其命名为 data.js。

(function () {

"use strict";

// List of Employees to be used a datasource.

var lstEmployees = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar" },

{ id: 2, name: "Lohith GN" },

{ id: 3, name: "Senthil Kumar B" },

{ id: 4, name: "Vidyasagar" },

]);

function Initialize() {

WinJS.UI.processAll().done(function () {

// Get the Listview from the DOM

var lstControl = document.getElementById('lstEmployees').winControl;

// Get the Search Tex from the HTML Page

var filterText = document.getElementById('txtSearch');

lstControl.itemDataSource = lstEmployees.dataSource;

filterText.addEventListener("keyup", function () {

filterEmployee(lstControl, filterText.value);

});

});

}

// Function to filter the list

function filterEmployee(listEmployee,searchtext)

{

var filtereddata = lstEmployees.createFiltered(function (item) {

var result = item.name.toLowerCase().indexOf(searchtext);

return item.name.toLowerCase().indexOf(searchtext) == 0;

});

listEmployee.itemDataSource = filtereddata.dataSource;

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

这段 JavaScript 代码包含一个名为filterEmployee的方法,它接受一个 ListView 控件和一个用于过滤的搜索字符串。该函数过滤 ListView 并显示与搜索字符串匹配的雇员。

下面是createFiltered方法中过滤 ListView 控件中数据源的函数。

var fileteredData = lstEmployees.createFiltered(function (item) {

var result = item.name.toLowerCase().indexOf(searchtext);

return item.name.toLowerCase().indexOf(searchtext) == 0;

});

该函数的作用类似于一个动态过滤器,当项目以搜索文本字符串开始时返回项目。

在 Windows 上运行应用。您应该会看到如图 4-7 所示的屏幕。

A978-1-4842-0719-2_4_Fig7_HTML.jpg

图 4-7。

Filtering the ListView

当您开始在文本框中输入文本时,您会看到筛选出的项目显示在屏幕上。

4.5 ListView 控件中的分组项目

问题

您需要在 ListView 中按类别对项目进行分组,而不是按平面列表进行分组。

解决办法

若要对 ListView 中的项目进行分组,需要使用分组的数据源。这可以通过使用 WinJS 中的WinJS.Binding.List.createGrouped()函数来实现。

它是如何工作的

要在 WinJS 中对 ListView 控件中的项目进行分组,有必要包含两个模板:一个用于组标题,一个用于单个项目。

让我们在 Visual Studio 2015 中创建新的 Windows Universal 项目,打开default.html页面。用下面的代码片段替换它。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.5</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.5 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body class="win-type-body">

<h1>Recipe 4.5</h1>

<div id="GroupHeader" data-win-control="WinJS.Binding.Template">

<h3 data-win-bind="innerText: technology"></h3>

</div>

<div id="employee" data-win-control="WinJS.Binding.Template">

<h4 data-win-bind="innerText:name"></h4>

</div>

<div id="lvEmployees" data-win-control="WinJS.UI.ListView"

data-win-options="{

itemTemplate: select('#employee'),

groupHeaderTemplate: select('#GroupHeader')

}">

</div>

</body>

</html>

这个代码片段包含一个名为 lvEmployees 的 ListView 控件,它有一个组头模板和与之相关联的itemTemplate

注意对data.js JavaScript 文件的引用。

让我们在 Visual Studio 2015 解决方案资源管理器中的js文件夹下创建一个新的 JavaScript 文件,并将其命名为 data.js。

(function () {

"use strict";

function Initialize() {

WinJS.UI.processAll().done(function () {

var listView1 = document.getElementById("lvEmployees").winControl;

var employeeList = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", technology: "Mobile" },

{ id: 2, name: "Michael", technology: "Web" },

{ id: 3, name: "Lohith", technology: "Web" },

{ id: 4, name: "Stephen", technology: "Mobile" },

{ id: 5, name: "Vidyasagar", technology: "Game" },

{ id: 6, name: "Joseph", technology: "Mobile" },

]);

var groupedEmployees = employeeList.createGrouped(

function (item) {

return item.technology;

},

function (item) {

return { technology: item.technology }

},

function (group1, group2) {

return group1 > group2 ? 1 : -1;

});

listView1.groupDataSource = groupedEmployees.groups.dataSource;

listView1.itemDataSource = groupedEmployees.dataSource;

});

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

这段 JavaScript 代码创建了项目数据源和分组数据源。该列表包含雇员记录,每一项都包含属性 id、姓名和技术。

分组的数据源是使用 WinJS 的createGrouped方法创建的,该方法需要传递三个函数作为参数。

  • GroupKey:该功能用于将列表中的每一项与一个组相关联。前面的示例返回了与每个雇员相关联的技术属性。
  • GroupData:该函数返回组头显示的数据项。在前面的示例中,GroupData返回标题中显示的组的技术。
  • GroupSorter:该函数处理组的顺序;例如,以升序在标题中列出组。

请注意,分组的数据源是活动的,它也可以使用筛选的数据源。

准备好项目数据源和分组数据源后,它们分别被设置为 ListView 的groupDataSource属性和itemDataSource属性,如下所示。

listView1.groupDataSource = groupedEmployees.groups.dataSource;

listView1.itemDataSource = groupedEmployees.dataSource;

当您在 Windows 上运行应用时,您应该会看到如图 4-8 所示的屏幕。

A978-1-4842-0719-2_4_Fig8_HTML.jpg

图 4-8。

ListView with grouped data

请注意,这些项目是按技术分组的,并显示在页面上。

4.6 ListView 中的语义缩放

问题

当使用 ListView 时,您希望为用户提供一个选项,以两种不同的缩放级别查看数据。

解决办法

您可以使用 WinJS 中的 SemanticZoom 控件在您的应用中引入语义缩放功能。SemanticZoom 控件使您能够在使用 ListView 时提供同一数据的两种不同视图。

您可以通过将div元素的data-win-control属性设置为 WinJS 来添加 SemanticZoom。UI.SemanticZoom 值

它是如何工作的

语义缩放可以使用 WinJS 中的 Semantic zoom 控件实现。设想这样一个场景,您有一个员工列表,可以根据他们所使用的技术对其进行分组。为了让用户能够轻松地在技术之间导航,您可以使用语义缩放,默认情况下,您可以看到按类别分组的员工,缩小后,您只能看到技术列表。

在 Visual Studio 2015 中创建新的通用 Windows 应用,打开default.html页面。用下面提供的代码替换现有的代码。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.6</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.6 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/data.js"></script>

</head>

<body class="win-type-body">

<h1>Recipe 4.6</h1>

<!-- Zoom In-->

<div id="GroupHeader" data-win-control="WinJS.Binding.Template">

<h1 data-win-bind="innerText: technology"></h1>

</div>

<div id="EmployeeTemplate" data-win-control="WinJS.Binding.Template">

<h2 data-win-bind="innerText:name"></h2>

</div>

<!-- Zoom out-->

<div id="TechnologyTemplate" data-win-control="WinJS.Binding.Template">

<h6 data-win-bind="innerText: technology"></h6>

</div>

<div id="szEmployee" data-win-control="WinJS.UI.SemanticZoom">

<!-- Zoom In-->

<div id="lvEmployees" data-win-control="WinJS.UI.ListView"

data-win-options="{

itemTemplate: select('#EmployeeTemplate'),

groupHeaderTemplate: select('#GroupHeader')

}">

</div>

<!-- Zoom Out-->

<div id="lvTechnologies" data-win-control="WinJS.UI.ListView"

data-win-options="{

itemTemplate: select('#TechnologyTemplate')

}">

</div>

</div>

</body>

</html>

上一页包含一个 SemanticZoom 控件,该控件有两个 ListView 控件。下面是使用 SemanticZoom 控件和 ListView 的代码。

<div id="szEmployee" data-win-control="WinJS.UI.SemanticZoom">

<!-- Zoom In-->

<div id="lvEmployees" data-win-control="WinJS.UI.ListView"

data-win-options="{

itemTemplate: select('#EmployeeTemplate'),

groupHeaderTemplate: select('#GroupHeader')

}">

</div>

<!-- Zoom Out-->

<div id="lvTechnologies" data-win-control="WinJS.UI.ListView"

data-win-options="{

itemTemplate: select('#TechnologyTemplate')

}">

</div>

</div>

SemanticZoom 控件包括两个具有不同缩放级别的 ListView 控件。当用户试图放大或缩小时,ListView 控件会相应地切换。

让我们在项目中的js文件夹下添加一个新的 JavaScript 文件,并将其命名为 data.js。将以下代码添加到data.js文件中。

(function () {

"use strict";

function Initialize() {

WinJS.UI.processAll().done(function () {

var listView1 = document.getElementById("lvEmployees").winControl;

var listView2 = document.getElementById("lvTechnologies").winControl;

var employeeList = new WinJS.Binding.List([

{ id: 1, name: "Senthil Kumar", technology: "Mobile" },

{ id: 2, name: "Michael", technology: "Web" },

{ id: 3, name: "Lohith", technology: "Web" },

{ id: 4, name: "Stephen", technology: "Mobile" },

{ id: 5, name: "Vidyasagar", technology: "Game" },

{ id: 6, name: "Joseph", technology: "Mobile" },

]);

// Grouped Datasource

var groupedEmployees = employeeList.createGrouped(

function (item) {

return item.technology;

},

function (item) {

return { technology: item.technology }

},

function (group1, group2) {

return group1 > group2 ? 1 : -1;

});

listView1.groupDataSource = groupedEmployees.groups.dataSource;

listView1.itemDataSource = groupedEmployees.dataSource;

listView2.itemDataSource = groupedEmployees.groups.dataSource;

});

}

document.addEventListener("DOMContentLoaded", Initialize);

})();

当您运行应用时,您应该会看到如图 4-9 所示的屏幕。

A978-1-4842-0719-2_4_Fig9_HTML.jpg

图 4-9。

SemanticZoom in the default view

单击屏幕右上角显示的–按钮,或使用拉伸手势缩小。

替代视图如图 4-10 所示。

A978-1-4842-0719-2_4_Fig10_HTML.jpg

图 4-10。

Alternate ListView shown using SemanticZoom

4.7 使用 AppBar 控件

问题

您需要提供对与当前页面或当前选择相关的常见任务的快速访问。

解决办法

通过向页面添加应用栏,您可以快速访问与当前页面或当前选择相关的常见任务。通过为div元素设置data-win-control="WinJS.UI.AppBar"属性,可以将 AppBar 控件添加到页面中。

它是如何工作的

应用栏是一行,包含图标按钮和应用屏幕底部的省略号。当用户点击省略号时,它显示可用的带标签的图标按钮和菜单项。

下面是将 AppBar 控件添加到 HTML 页面的语法。

<div data-win-control="WinJS.UI.AppBar"></div>

可以使用 JavaScript 代码以及以下语法添加 AppBar 控件。

var object = new WinJS.UI.AppBar(element, options);

AppBar 命令被添加到 app bar 中。这只是显示在应用栏中的命令或按钮。

<button data-win-control="WinJS.UI.AppBarCommand"></button>

通过将控件的data-win-options属性的 section 属性设置为 secondary,可以指定 AppBarCommand 是否应显示为菜单。

让我们创建一个演示 AppBar 功能的应用,它包括以下功能。

  • 演示添加和删除选项的命令(按钮)。
  • appbar 命令(菜单项)演示当用户点击省略号时显示的菜单项。

当用户点击按钮或菜单项时,相应的事件被处理,并显示适当的消息。

在 Visual Studio 2015 中创建新的通用 Windows 项目,打开default.html页面。用下面的代码替换它的内容。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.7</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.7 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

<script src="/js/appbarevents.js"></script>

</head>

<body class="win-type-body">

<div id="appBar" data-win-control="WinJS.UI.AppBar">

<button data-win-control="WinJS.UI.AppBarCommand"

data-win-options="{id:'cmdAdd', label:'Add', icon:'add', section:'primary', tooltip:'Add'}"></button>

<button data-win-control="WinJS.UI.AppBarCommand"

data-win-options="{id:'cmdRemove', label:'Remove', icon:'remove', section:'primary', tooltip:'Remove'}"></button>

<button data-win-control="WinJS.UI.AppBarCommand"

data-win-options="{id:'cmdCamera', label:'Click Photo', icon:'camera', section:'secondary', tooltip:'click'}"></button>

</div>

<div id="Message"></div>

</body>

</html>

HTML 标记在主要部分添加了两个 appbar command(Add,Remove ),在次级菜单中添加了一个 AppBarCommand (Camera)。属性为控件提供了额外的选项。其中一些属性包括以下内容:

  • Id:唯一标识 AppBarCommand。
  • label:appbar command 中显示的内容。
  • icon:appbar command 的内置图标。
  • section:app bar 中应该显示命令的部分。该值可以是主要的或次要的。
  • tooltip:鼠标悬停在命令按钮上时显示的文本。

注意,该页面包含对appbarevents.js JavaScript 文件的引用。这包含处理 appbar 命令上的事件的逻辑。让我们在项目中的js文件夹下创建一个新的 JavaScript 文件,并将其命名为 appbarevents.js。

(function () {

"use strict";

WinJS.UI.Pages.define("default.html", {

ready: function (element, options) {

element.querySelector("#cmdAdd").addEventListener("click", AddMethod, false);

element.querySelector("#cmdRemove").addEventListener("click", RemoveMethod, false);

element.querySelector("#cmdCamera").addEventListener("click", CameraMethod, false);

}

});

// Command button functions

function AddMethod() {

var message = new Windows.UI.Popups.MessageDialog("Add Button Pressed");

message.showAsync();

}

function RemoveMethod() {

var message = new Windows.UI.Popups.MessageDialog("Remove button pressed");

message.showAsync();

}

function CameraMethod() {

var message = new Windows.UI.Popups.MessageDialog("Camera button pressed");

message.showAsync();

}

})();

前面的 JavaScript 代码处理 AppBarCommand 按钮的 click 事件。单击该按钮时,会显示一条消息。

在 Windows 上运行应用。您应该会看到如图 4-11 所示的屏幕。

A978-1-4842-0719-2_4_Fig11_HTML.jpg

图 4-11。

Windows app with the AppBar

点击应用栏中的省略号按钮,显示第二部分,如图 4-12 所示。

A978-1-4842-0719-2_4_Fig12_HTML.jpg

图 4-12。

Windows app with the AppBar and secondary section

当您单击菜单按钮时,它会显示相应的消息。

4.8 使用工具栏控件

问题

您需要显示一组可以出现在任何位置的命令;例如,屏幕顶部的弹出按钮或应用栏。

解决办法

您可以使用工具栏控件在操作区域中显示尽可能多的命令。这种控制不局限于应用中的单一位置。它可以在拆分视图、弹出按钮等中找到。

它是如何工作的

使用 JavaScript 模板在 Visual Studio 2015 中创建新的通用 Windows 应用。打开default.html页面。

用下面的代码替换default.html页面的内容。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>Recipe4.8</title>

<!-- WinJS references -->

<link href="WinJS/css/ui-light.css" rel="stylesheet" />

<script src="WinJS/js/base.js"></script>

<script src="WinJS/js/ui.js"></script>

<!-- Recipe4.8 references -->

<link href="/css/default.css" rel="stylesheet" />

<script src="/js/default.js"></script>

</head>

<body class="win-type-body">

<div class="basicToolbar" data-win-control="WinJS.UI.ToolBar">

<!-- Primary commands -->

<button data-win-control="WinJS.UI.Command" data-win-options="{

id:'cmdAdd',

label:'add',

section:'primary',

type:'button',

icon: 'add',

onclick: recipes.clickcommand}"></button>

<button data-win-control="WinJS.UI.Command" data-win-options="{

id:'cmdEdit',

label:'Edit',

section:'primary',

type:'button',

icon: 'edit',

onclick: recipes.clickcommand}"></button>

<button data-win-control="WinJS.UI.Command" data-win-options="{

id:'cmdDelete',

label:'delete',

section:'primary',

type:'button',

icon: 'delete',

onclick: recipes.clickcommand}"></button>

<!-- Secondary command -->

<button data-win-control="WinJS.UI.Command" data-win-options="{

id:'cmdShare',

label:'share',

section:'secondary',

type:'button',

onclick: recipes.clickcommand}"></button>

</div>

</body>

</html>

前面的代码片段在主命令中添加了三个按钮,在辅助命令中添加了一个按钮(Share)。默认情况下,辅助命令是隐藏的,当您点击省略号按钮时会显示出来。

通过将div元素的data-win-control属性设置为 WinJS 来添加工具栏控件。工具栏值。

您可以通过设置 WinJS 的data-win-control属性在工具栏中添加按钮。UI .命令值。data-win-options属性用于设置命令属性。以下是为该命令设置的一些属性。

  • id:定义命令的标识符。
  • label:定义命令显示的文本。
  • section:定义工具栏中命令应该出现的区域。这可以采用主值或次值。
  • type:设置为“button”显示按钮控件。
  • onClick:触发并调用相应 JavaScript 方法的事件。
  • icon:显示命令的内置图标。

注意,我们已经为该命令设置了OnClick事件。让我们为它添加事件。

打开项目的js文件夹下的default.js文件。在args.setPromise方法之前添加以下代码。

WinJS.Namespace.define("recipes", {

clickcommand: WinJS.UI.eventHandler(function (ev) {

var command = ev.currentTarget;

if (command.winControl) {

var message = Windows.UI.Popups.MessageDialog(command.winControl.label);

message.showAsync();

}

})

});

前面的代码片段定义了名为recipe的名称空间,并添加了一个名为clickcommand的事件处理程序。这将在调用事件时显示一个 MessageDialog。

现在,让我们在 Windows 上运行应用。您应该会看到如图 4-13 所示的屏幕。

A978-1-4842-0719-2_4_Fig13_HTML.jpg

图 4-13。

Toolbar in Windows app

当您单击命令按钮时,您会看到一个消息对话框,描述所单击的按钮。