使用 JavaScript 创建你的第一个 Metro 风格应用

红薯 发布于 2012/03/01 22:47
阅读 1K+
收藏 5

本教程介绍了使用 JavaScript 创建 Metro 风格应用所需的基本代码和工具。你使用 HTML5、层叠样式表 Level 3 (CSS3) 和适用于 JavaScript 的 Windows 库来定义 UI,使用 JavaScript 来编写应用逻辑。

如果你希望使用其他编程语言,请参阅:

要求

若要完成本教程,你必须拥有一台运行 Windows 8 Consumer Preview 和 Microsoft Visual Studio 11 Express Beta for Windows 8 的计算机。请参阅 Metro 风格应用入门

WindowsBlogReader

在本教程中,我们为某些 Windows 团队博客创建了一个基本的阅读器。完成后的应用外观如下所示:

主页、拆分页面以及详细信息页面。

主页的标题为“"Windows Team Blogs"”,并且包含一个 ListView 控件,将每个博客显示为一个项目。单击 ListView 中的项目时,则导航到所选博客的拆分页面。拆分页面包含一个 ListView 控件,将每个博客文章显示为一个项目,还有一个控件将当前所选的博客文章的内容以垂直方式显示。从拆分页面可以导航到详细信息页面,在详细信息页面中,博 客文章的标题显示在顶部,当前所选博客文章的内容以水平方式显示。

JavaScript 中的 Metro 风格应用

开始编写代码之前,下面先介绍一些有用的背景信息。使用 HTML、CSS 和 JavaScript 时,创建网站和创建 Metro 风格应用有许多相同之处,但也有一些重要的不同之处。

这些功能可用于 Metro 风格应用:

  • 增强了触摸功能的支持
  • 可访问 Windows 运行时
  • 适用于 JavaScript 的 Windows 库中的控件
  • 控制 HTML 外观和感觉的更多控件以及适用于 JavaScript 的 Windows 库中的控件

Metro 风格应用中的这些限制可能影响你开发应用的方式以及标记和代码的表现:

  • 活动应用占用了一个填满了大部分屏幕的窗口。你不能创建新窗口,也不能调整现有窗口大小或移动现有窗口。
  • 你的应用可以分区为两个逻辑上下文。本地上下文是默认上下文,应用中打包的代码在此处运行。此上下文中的代码可以访问文件系统和设备,也可以进行跨域的 HTTP 请求。Web 上下文是外部下载的代码运行的位置。你必须使用 iframe 元素在网页上下文中运行 Web 代码。
  • 注入到本地上下文中页面的 HTML 进行了筛选,就如已经过 toStaticHTML 方法处理一般。你可以忽略此限制,但是仅针对不包含你控制范围之外的远程 Web 内容的受信任内容。
  • 你不能使用 ActiveX 控件。
  • 必须将所有访问的页面编码为 UTF-8 或 UTF-8 的子集,如 ANSI。

在 Visual Studio 11 Express 中创建新项目

为我们的应用创建一个名为 WindowsBlogReader 的新项目。以下是操作方法:

  1. 启动 Visual Studio。

  2. 在“起始页”选项卡中,单击“新建项目”。将打开“新建项目”对话框。

  3. 在“已安装”窗格中,展开 JavaScript 并选择“Windows Metro 风格”模板类型。JavaScript 可用的项目模板显示在对话框的中心窗格中。

  4. 在中心窗格中,选择“分隔应用程序”项目模板。

  5. 在“名称”文本框中,输入 "WindowsBlogReader"。

  6. 单击“确定”以创建项目。这需要花费一点时间。

下面是在解决方案资源管理器中显示的项目的结构。新项目包含创建主页和拆分页面所需的 HTML、CSS 和 JavaScript 文件。稍后我们将为详细信息页面添加文件。

解决方案资源管理器中 WindowsBlogReader 项目的屏幕截图。

有关详细信息,请参阅 Metro 风格应用的 JavaScript 项目模板

启动我们的新 Metro 风格应用

如果你非常想看到基本的分隔应用的外观,请按 F5 以生成、部署并启动应用。应用显示为全屏页面,标题为 "WindowsBlogReader",包含一列示例项目,显示为网格。每个项目表示一组数据。右键单击以显示基本的应用栏,或者从底端或顶端轻扫(如 果你的系统支持触摸)来显示。单击列表中的项目以导航至拆分页面。拆分页面包含两个核心内容区域。在左侧,你可以看到与所选组关联的项目列表。在右侧,可 以看到所选项目的内容。可以通过点击或单击页面上的“后退”按钮或应用栏上的“主页”按钮来返回主页。

没有关闭应用的按钮或命令。可以使用关闭手势或 Alt+F4 来关闭应用。转至“开始”屏幕。请注意,部署应用会将应用的磁贴添加到“开始”屏幕的最后一组。若要再次运行应用,请在“开始”屏幕上点击或单击应用的磁贴,或在 Visual Studio 中按 F5。

运行使用 JavaScript 编写的 Metro 风格的应用时,Internet Explorer 会呈现 HTML。但是运行 Metro 风格应用时,承载 Internet Explorer 的流程与浏览 Web 时的流程完全不同。Internet Explorer 在应用容器内的 WWAHost.exe 流程中运行。WWAHost 运行应用时,片段加载程序提取 itemsPage.html 中的(其中链接的)HTML、CSS 以及 JavaScript,并将其注入到作为应用开始的 default.html 页面中。对于在应用容器中运行的代码默认可以执行的操作有一些限制。例如,你的应用不能访问 Internet 或网络摄像机,除非你声明应用需要此访问功能,且用户在安装应用时授予了此访问权限。若要了解更多信息,请打开 package.appxmanifest,并转至“功能”选项卡。

更改标题和背景色

我们来执行两个简单的任务来自定义应用。

若要更改应用的标题,请打开 itemsPage.html,将 itemspageh1 元素的示例内部文本替换为 "Windows Team Blogs",如此处所示。

<h1 class="titlearea win-type-ellipsis">     <span class="pagetitle">Windows Team Blogs</span> </h1> 

若要设置应用的背景色,请打开 default.css,并将此 background-color 属性添加到 #contenthost 中。

CSS
#contenthost
{
    height: 100%;
    width: 100%;    
    background-color: #0A2562;
}

按 F5 来生成、部署并启动此应用。请注意,主页的标题已更改,主页和拆分页面的背景色为蓝色。

注意  项目中的 images 文件夹包含默认的文件,系统将这些文件用于应用启动时应用的磁贴和初始屏幕。在本教程中,我们不更改这些内容,但是你可以按照自己的喜好使用其他图像。只 需将要使用的图像文件添加到 images 文件夹中即可。打开 package.appxmanifest,将“应用程序 UI”选项卡上“徽标”、“小徽标”和“初始屏幕”的内容替换为你的图像文件的路径。

替换示例数据

项目模板包含运行应用时看到的示例数据。我们使用这些步骤为 Windows 团队博客将这些示例数据替换为来自 ATOM 源的数据:

删除示例数据

打开 data.js,其中包含应用的示例数据。我们不需要这些占位符变量,所以你可以删除它们:

  • groupDescription
  • itemDescription
  • itemContent
  • sampleGroups
  • sampleItems

我们不需要这些函数,所以也可以将它们删除:

  • groupKeySelector
  • groupDataSelector

设置变量和函数

将此代码添加到 data.js(在 getItemsFromGroup 函数定义之前),以设置我们所需的变量以及填充它们的函数。我们执行本教程中的步骤时,你可以使用包含的评论来找到每一步放置代码的位置。

// Set up array variables var dataPromises = [];var blogs;// Create a data binding for our ListView var blogPosts = new WinJS.Binding.List();// Process the blog feeds function getFeeds() { 
    // Create an object for each feed in the blogs array     // Get the content for each feed in the blogs array     // Return when all asynchronous operations are complete }function acquireSyndication(url) {
    // Call xhr for the URL to get results asynchronously }function getBlogPosts() {
    // Walk the results to retrieve the blog posts }function getItemsFromXml(articleSyndication, blogPosts, feed) {
    // Get the info for each blog post }// Organize the data for display  function getGroupedData() {
}

定义博客列表

为了使这个示例简单一点,我们在 blogs 数组中包含一列硬编码的 URL。

将此代码添加到 getFeeds 函数。此代码将 JSON 数组添加到 blogs 数组。每个 JSON 数组都包含多个 JSON 对象,以存储来自源的内容。JSON 对象是名称/值对的未经排序的容器。例如,博客标题存储在一个 JSON 对象中,该对象名为 title,还有一个从 ATOM 源检索的值。使用 JSON 对象使我们将来自源的内容绑定到应用的控件变得很简单。

// Create an object for each feed in the blogs array blogs = [
{
    key: "blog1",
    url: 'http://windowsteamblog.com/windows/b/developers/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog2",
    url: 'http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog3",
    url: 'http://windowsteamblog.com/windows/b/extremewindows/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog4",
    url: 'http://windowsteamblog.com/windows/b/business/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog5",
    url: 'http://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog6",
    url: 'http://windowsteamblog.com/windows/b/windowssecurity/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog7",
    url: 'http://windowsteamblog.com/windows/b/springboard/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog8",
    url: 'http://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog9",
    url: 'http://windowsteamblog.com/windows_live/b/developer/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog10",
    url: 'http://windowsteamblog.com/ie/b/ie/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog11",
    url: 'http://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null },
{
    key: "blog12",
    url: 'http://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx',
    title: 'tbd', updated: 'tbd',
    backgroundImage: darkGray,
    acquireSyndication: acquireSyndication, dataPromise: null }];

检索源数据

对于此部分中的步骤,我们使用适用于 JavaScript 的 Windows 库来管理联合源。

将此代码添加到 acquireSyndication 函数。我们调用 Windows.JS.xhr 函数以检索源内容。此调用为异步调用。幸运的是,程序已经为我们处理好了在进行异步调用时可能会遇到的许多复杂问题。xhr 返回时,我们将收到结果的承诺,此承诺将返回到调用方。

// Call xhr for the URL to get results asynchronously return WinJS.xhr({ url: url });

现在,我们将代码添加到 getFeeds 函数以调用 blogs 数组中每个博客的 acquireSyndication 函数,并添加返回到我们承诺数组的承诺 dataPromises。 我们先调用 WinJS.Promise.join 函数,等待所有承诺均已满足后,再从 getFeeds 返回。这可以确保在显示 ListView 控件之前,我们拥有全部所需的信息。

// Get the content for each feed in the blogs array blogs.forEach(function (feed) {
    feed.dataPromise = feed.acquireSyndication(feed.url);
    dataPromises.push(feed.dataPromise);
});// Return when all asynchronous operations are complete return WinJS.Promise.join(dataPromises).then(function () {
    return blogs;
});

接下来,将此代码添加到 getBlogPosts 函数。对于 blogs 数组中的每个博客,我们针对所需的信息分析 XML 源数据。首先,我们使用 responseXML 属性以获得响应正文,然后使用 selectSingleNode 方法以及所需的 XPath 语句来获得博客的标题和最后更新日期。

// Walk the results to retrieve the blog posts getFeeds().then(function () {
    // Process each blog     blogs.forEach(function (feed) {
        feed.dataPromise.then(function (articlesResponse) {
            var articleSyndication = articlesResponse.responseXML;

            // Get the blog title              feed.title = articleSyndication.selectSingleNode("/feed/title").text;

            // Use the date of the latest post as the last updated date             var ds = articleSyndication.selectSingleNode("/feed/entry/published").text;
            var date = ds.substring(5, 7) + "-" + ds.substring(8, 10) + "-" + ds.substring(0, 4);
            feed.updated = "Last updated " + date;

            // Get the blog posts             getItemsFromXml(articleSyndication, blogPosts, feed);
        });
    });
});return blogPosts;

最后,将此代码添加到 getItemsFromXml 函数。首先,我们使用 selectNodes 来获得博客文章集以及每篇博客文章的信息。然后,我们使用 selectSingleNode 来获得每篇博客文章的信息。最后,我们使用 push 方法将每篇博客文章的信息存储在 blogPosts 数组中的相应条目中。

// Get the info for each blog post var posts = articleSyndication.selectNodes("//entry");// Process each blog post for (var postIndex = 0; postIndex < posts.length; postIndex++) {
    var post = posts[postIndex];

    // Get the title, author, and date published     var postTitle = post.selectSingleNode("title").text;
    var postAuthor = post.selectSingleNode("author/name").text;
    var pds = post.selectSingleNode("published").text;
    var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10) + "-" + pds.substring(0, 4);

    // Process the content so it displays nicely     var staticContent = toStaticHTML(post.selectSingleNode("content").text);

    // Store the post info we care about in the array     blogPosts.push({
        group: feed,
        key: feed.title,
        title: postTitle,
        author: postAuthor,
        pubDate: postDate,
        content: staticContent,
        backgroundImage: mediumGray
    });                                         
}

使数据可用

现在,我们已完成了将源数据存储到数组中的代码,我们需要按预期根据 ListView 控件来分组源数据。我们还需要完成将源数据绑定到 ListView 控件。

将此代码添加到 getGroupedData 函数。blogPosts 变量是一个 WinJS.Binding.List 对象。调用 createGrouped 方法将按指定的键(此情况中是指每篇文章所属的博客)对博客文章排序。

return blogPosts.createGrouped(function (item) { return item.group.key; },
    function (item) { return item.group; },
    function (l, r) { return l < r; });

getItemsFromGroup 函数非常不错。它调用 createFiltered 方法,并为指定的博客返回博客文章。

getItemsFromGroup 函数依赖于变量 list。从 data.js 中删除此模板代码:

var list = new WinJS.Binding.List();var groupedItems = list.createGrouped(groupedKeySelector, groupDataSelector);// TODO: Replace the data with your real data. // You can add data from asynchronous sources whenever it becomes available. sampleItems.forEach(function (item) {
    list.push(item);
});

使用此代码替换删除的代码,此代码将我们的 getBlogPosts 函数结果存储在 list 变量中,将 getGroupedData 函数结果存储在 groupedItems 变量中。

var list = getBlogPosts();var groupedItems = getGroupedData();

更新主页

主页的主要功能是使用 WinJS.UI.ListView 实现的 ListView 控件。我们现在修改 ListView 控件中的默认项目。每个博客在此列表中都有一个项目。列表项包含博客标题和最后更新日期。

打开 itemsPage.html。找到此 h6 标记并将 textContent: subtitle 更新为 textContent: updated

<h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6> 

更新拆分页面

拆分页面的 HTML 使用与示例数据相同的名称。我们需要更新 HTML,从而在我们的 blogPosts 数组中反映出名称。打开 splitPage.html。找到此 div 标记,将 textContent: subtitle 更改为 textContent: author,并将 textContent: description 更改为 textContent: pubDate

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">     <div class="item">         <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />         <div class="item-info">             <h3 class="item-title win-type-ellipsis" data-win-bind="textContent: title"></h3>             <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>             <h4 class="item-description" data-win-bind="textContent: description"></h4>         </div>     </div> </div> 

因为我们没有包含在示例数据中的所有信息,所以从 articleSection 删除此代码可以简化页面。

<header class="header">     <div class="text">         <h2 class="article-title win-type-ellipsis" data-win-bind="textContent: title"></h2>         <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4>     </div>     <img class="article-image" src="#" data-win-bind="src: backgroundImage; alt: title" /> </header> 

若要获取所需的页面布局,请打开 splitPage.css。将此 -ms-grid-row 属性从 "1" 更改为 "2"。这导致页面标题填满整个第一行,并且将 ListView 和文章放在第二行。

CSS
.splitpage .articlesection
{
    -ms-grid-column: 2;
    -ms-grid-row-span: 2;
    -ms-grid-row: 1;
    ...
}

现在,来试试再次运行应用吧。按 F5 来生成、部署并启动此应用。可以立即看到页面标题,但是应用检索源数据时有短暂的延迟。满足所有承诺后,可以看到在 ListView 中每个博客一个项目。(此代码以满足承诺的顺序将这些项目添加到 ListView 中。)点击或单击 ListView 中的项目会将你带到拆分页面,此拆分页面包含所选博客的博客文章列表以及所选博客文章的内容。默认选中第一篇博客文章。

单击“后退”箭头,返回到主页。请注意,返回到屏幕的磁贴带有过渡动画。这是适用于 JavaScript 的 Windows 库中的一个功能,它支持控件以及其他用户界面元素按照 Metro 风格应用的 UX 指南移动。

添加详细信息页面

详细信息页面将博客文章的标题显示为自己的标题,并有一块区域包含博客文章的内容。

若要添加详细信息页面:

  1. 在解决方案资源管理器中,右键单击“js”文件夹,选择“添加”>“新建项目”。
  2. 选择“JavaScript 文件”,并使用文件名“detailPage.js”。
  3. 单击“添加”以创建文件。
  4. 在解决方案资源管理器中,右键单击“html”文件夹,选择“添加”>“新建项目”。
  5. 选择“HTML 页面”,并使用文件名“detailPage.html”。
  6. 单击“添加”以创建文件。
  7. 在解决方案资源管理器中,右键单击“css”文件夹,选择“添加”>“新建项目”。
  8. 选择“样式表”,并使用文件名“detailPage.css”。
  9. 单击“添加”以创建文件。

打开 detailPage.html,使用此处显示的代码替换模板代码。此代码定义页面布局。(此 HTML 是包含在网格应用程序模板中的 itemDetailPage.html 页面稍微简化了的版本。)

<!DOCTYPE html> <html> <head>     <meta charset="utf-8">     <title>detailPage</title>     
    <!-- WinJS references -->     <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">     <script src="//Microsoft.WinJS.0.6/js/base.js"></script>     <script src="//Microsoft.WinJS.0.6/js/ui.js"></script>     <link href="/css/default.css" rel="stylesheet">     <link href="/css/detailPage.css" rel="stylesheet">     <script src="/js/data.js"></script>     <script src="/js/detailPage.js"></script> </head> <body>     <!-- The content that will be loaded and displayed. -->     <div class="detailpage fragment">         <header aria-label="Header content" role="banner">             <button class="win-backbutton" aria-label="Back" disabled></button>             <h1 class="titlearea win-type-ellipsis">                 <span class="pagetitle"></span>             </h1>         </header>         <section aria-label="Main content" role="main">             <article>                 <div>                     <div class="item-content"></div>                 </div>             </article>         </section>     </div> </body> </html> 

打开 detailPage.js,并添加此处显示的代码。此代码显示用户导航至此页面时的标题和内容。(此 JavaScript 是包含在网格应用程序模板中的 itemDetailPage.js 页面稍微简化了的版本。)

(function () {
    "use strict";

    var ui = WinJS.UI;
    var utils = WinJS.Utilities;

    ui.Pages.define("/html/detailPage.html", {
        // This function is called whenever a user navigates to this page. It         // populates the page elements with the app's data.         ready: function (element, options) {
            // Display the appbar but hide the Full View button             var appbar = document.getElementById('appbar');
            var appbarCtrl = appbar.winControl;
            appbarCtrl.hideCommands(["view"], false);

            var item = options && options.item ? options.item : data.items.getAt(0);                                           
            element.querySelector(".titlearea .pagetitle").textContent = item.title;
            element.querySelector("article .item-content").innerHTML = item.content;
        }
    });
})();

现在,我们为详细信息页面定义样式。打开 detailPage.css,使用此处显示的代码替换模板代码。(此 CSS 取自包含在网格应用程序模板中的 itemDetailPage.css 页面。)

CSS
.detailpage section[role=main]
{
    -ms-grid-row: 2;
    display: block;
    height: 100%;
    overflow-x: auto;
    position: relative;
    width: 100%;
    z-index: 0;
}

    .detailpage section[role=main] article
    {
        /* Define a multi-column, horizontally scrolling article by default. */
        column-fill: auto;
        column-gap: 80px;
        column-width: 480px;
        height: calc(100% - 50px);
        margin-left: 120px;
        width: 480px;
    }

        .detailpage section[role=main] article .item-content p
        {
            margin-bottom: 20px;
            margin-right: 20px;
            vertical-align: baseline;
        }

@media screen and (-ms-view-state: snapped)
{
    .detailpage section[role=main] article
    {
        /* Define a single column, vertically scrolling article in snapped mode. */
        -ms-grid-columns: 300px 1fr;
        -ms-grid-row: 2;
        -ms-grid-rows: auto 60px;
        display: -ms-grid;
        height: 100%;
        margin-left: 20px;
        overflow-x: hidden;
        overflow-y: auto;
        width: 300px;
    }

        .detailpage section[role=main] article .item-content
        {
            padding-bottom: 60px;
        }
}

@media screen and (-ms-view-state: fullscreen-portrait)
{
    .detailpage section[role=main] article
    {
        margin-left: 100px;
    }
}

添加带有显示详细信息页面命令的应用栏

我们添加一个应用栏,它包含可用于导航到详细信息页面的按钮,并使此按钮仅在我们位于拆分页面时才显示。

打开 default.html 并取消注释此代码。

<!-- <div id="appbar" data-win-control="WinJS.UI.AppBar">
    <button data-win-control="WinJS.UI.AppBarCommand" 
            data-win-options="{id:'cmd', label:'Command', icon:'placeholder'}">
    </button>
</div> --> 

修改占位符按钮的定义,以在应用栏靠右侧远端创建一个标签为“完全视图”的按钮,如此处所示。

<div id="appbar" data-win-control="WinJS.UI.AppBar">     <button data-win-control="WinJS.UI.AppBarCommand" 
            data-win-options="{id:'view', label:'Full View', icon:'&#xE109;'}">     </button> </div> 

我们不希望在导航至主页和详细信息页面时,“完全视图”按钮显示在应用栏上。将此代码添加到 itemsPage.js 中的 ready 函数内以隐藏按钮。(此代码已经出现在我们创建的 detailPage.js 中的 ready 函数内。)

// Display the appbar but hide the Full View button var appbar = document.getElementById('appbar');var appbarCtrl = appbar.winControl;
appbarCtrl.hideCommands(["view"], false);

我们导航至拆分页面时,“完全视图”按钮将显示在应用栏上。将此代码添加到 splitPage.js 中的 ready 函数内以显示按钮。

// Display the appbar and show the Full View button var appbar = document.getElementById('appbar');var appbarCtrl = appbar.winControl;
appbarCtrl.showCommands(["view"], false);

从拆分页面导航到详细信息页面

用户单击应用栏上的“完全视图”按钮时,应用导航到详细信息页面并显示所选博客文章的标题和内容。

打开 splitPage.js。将此变量声明添加到 utils 变量声明的后面。

var post;

在第一次调用 querySelector 之后将此语句添加到 ready 函数,以便可以先设置 this.items。此代码将 post 变量设置为用户导航至页面时第一篇博客文章的索引。

post = this.items.getAt(0);

将此语句添加到 selectionChanged 函数,在设置 that.itemSelectionIndex 的语句后面。此代码将 post 变量设置为用户所选博客文章的索引。

post = that.items.getAt(that.itemSelectionIndex);

将此事件处理程序函数添加到 post 变量声明的后面。用户单击“完全视图”按钮时即调用此处理程序。WinJS.Navigation.navigate 函数加载详细信息页面,并将所选的博客文章作为项目传递。

function displayFullView() {
    nav.navigate('/html/detailPage.html', { item: post });
}

将此代码添加到 ready 函数中(在我们添加的代码的之后),以显示“完全视图”按钮。此代码将我们的 displayFullView 函数注册为“完全视图”按钮的 click 事件的事件处理程序。

// Register the event handler for the Full View button document.getElementById('view').addEventListener("click", displayFullView, false);

按 F5 以运行应用。单击主页上的项目会将你带到拆分页面,此拆分页面包含博客文章列表以及所选博客文章的内容。点击或单击博客文章,文章内容即显示在右侧栏中。若要显示应用栏,请右键单击,或者从底端或顶端轻扫(如果你的系统支持触摸)。点击或单击“完全视图”按钮,我们的应用将在详细信息页面中显示所选博客文章的内容。

如果点击或单击“后退”按钮,则返回到拆分页面。ListView 中的第一项被选中,它不一定是你在详细信息页面中选择显示的项。 你可以根据需要添加代码来保存并还原所选项。

我们的应用所使用的模板代码可以显示横向和纵向方向。旋转你的电脑,或在 Visual Studio 11 Express Beta for Windows 8 的模拟器中运行你的应用然后旋转显示器。主页外观如下所示。

纵向方向主页的屏幕截图。

拆分页面外观如下所示。请注意,在选择项目前,仅显示 ListView 控件。然后,博客文章以垂直方向显示。如果你单击“Full View”按钮,则博客文章以水平方向显示。

纵向方向拆分页面的屏幕截图。

总结

我们已经完成了应用的代码!我们了解了如何构建内置页面模板,如何将数据与 ListView 绑定,如何导航至新页面以及如何添加带按钮的应用栏。

有关在应用中可以添加的其他功能的详细信息,请参阅使用 JavaScript 的 Metro 风格应用的路线图

相关主题

使用 JavaScript 的 Metro 风格应用的路线图
使用 Visual Studio 11 开发 Metro 风格应用
加载中
0
NILYANG
NILYANG
niubility
0
lgscofield
lgscofield
红薯大哥,我想问问,我们这个社区应该是java开发的吧...这个Metro风格的东西是怎么样引入到java中的呢,最近看这个挺感兴趣的想学学...请指教一下吧
lgscofield
lgscofield
@红薯 哦,明白了,谢谢...
红薯
红薯
metro风格只是一种页面的样式,跟用什么语言开发都没有关系啊:)
返回顶部
顶部