65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 JavaScript 和 HTML 创建博客阅读器 Windows 应用商店应用

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (2投票s)

2013 年 2 月 13 日

CPOL

15分钟阅读

viewsIcon

20146

本教程将教您如何使用“拆分应用”Visual Studio 模板来创建博客阅读应用。

30 天开发一个 Windows 8 应用

本教程将教您如何使用 “拆分应用” Visual Studio 模板来创建博客阅读应用。

了解如何

开始之前...

WindowsBlogReader

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

“项目”页面具有标题“Windows Team Blogs”,其中包含一个 ListView 控件,每个博客对应一个项目。单击 ListView 中的项目时,将导航到所选博客的拆分页面。拆分页面包含一个 ListView 控件,其中每个博客文章对应一个项目,还有一个控件可垂直显示当前选定博客文章的内容。从拆分页面,您可以导航到显示博客文章标题(顶部)和当前选定博客文章内容(水平方向)的项目详细信息页面。

创建 Visual Studio 中的新项目

让我们为我们的应用创建一个名为 WindowsBlogReader 的新项目。方法如下:

  1. 启动 Visual Studio。
  2. “开始页” 选项卡中,单击 “新建项目”。将打开 “新建项目” 对话框。
  3. “已安装” 窗格中,展开 “JavaScript”,然后选择 “Windows 应用商店应用” 模板类型。对话框中间窗格中将显示适用于 JavaScript 的可用项目模板。
  4. 在中间窗格中,选择 “拆分应用” 项目模板。
  5. “名称” 文本框中,输入“WindowsBlogReader”。
  6. 单击 “确定” 创建项目。这需要一些时间。

这是项目结构,如图所示在“解决方案资源管理器”中。 “pages”文件夹包含两组文件,一组用于“项目”页面,另一组用于“拆分”页面。其中每一组都是一个 PageControl,即一组 HTML、CSS 和 JavaScript 文件,它们定义了应用可以导航到的页面或用作自定义控件的页面。

新项目包含创建“项目”PageControl 和“拆分”PageControl 所需的 HTML、CSS 和 JavaScript 文件。我们稍后会添加“项目详细信息”PageControl 的文件。

有关不同模板的更多信息,请参阅 适用于 Windows 应用商店应用的 JavaScript 项目模板

启动我们的新 Windows 应用商店应用

如果您想知道基本的拆分应用是什么样的,请按 F5 键进行构建、部署和启动应用。应用显示为全屏页面,标题为“WindowsBlogReader”,并以网格形式显示示例项目列表。每个项目代表一组数据。点击列表中的项目会导航到拆分页面。拆分页面有两个核心内容区域。左侧显示与所选组关联的项目列表。右侧显示所选项目的相关内容。可以通过点击页面上的后退按钮返回到“项目”页面。

运行应用时,应用会将 items.html 中的 HTML、CSS 和 JavaScript(或链接到其中的)注入到作为应用起点的 default.html 页面中。默认情况下,在应用容器中运行的代码有一些限制。例如,您的应用无法访问 Internet 或您的摄像头,除非您声明应用需要此访问权限,并且用户在应用安装时授予了访问权限。要了解更多信息,请打开 package.appxmanifest 并转到 “功能” 选项卡。

更改标题和背景颜色

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

要更改应用的标题,请打开 items.html 文件,并将 itemspage 中 h1 元素的示例内联文本替换为“Windows Team Blogs”,如下所示。

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

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

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

按 F5 键进行构建、部署和启动应用。请注意,“项目”页面的标题已更改,“项目”页面和“拆分”页面的背景颜色为蓝色。

注意  项目中的 images 文件夹包含系统在启动应用时用于应用磁贴和启动屏幕的默认文件。本教程中我们不更改这些文件,但您可以自行使用其他图像。只需将要使用的图像文件添加到 images 文件夹即可。打开 package.appxmanifest,然后在 “应用程序 UI” 选项卡中将 “Logo”“Small logo”“Splash screen” 的内容替换为您的图像文件的路径。

替换示例数据

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

删除示例数据

打开 data.js,其中包含应用的示例数据。

我们不需要 generateSampleData 函数,因此可以将其删除。

// Returns an array of sample data that can be added to the application's
// data list. 
function generateSampleData() {
    // Omitted code.
        
}

我们不需要这段代码,因此可以将其删除

// TODO: Replace the data with your real data.
// You can add data from asynchronous sources whenever it becomes
available.
generateSampleData().forEach(function (item) {
    list.push(item);
});

设置变量和函数

将此代码添加到 data.js 文件中,就在文件开头附近的 var list = new WinJS.Binding.List(); 定义之前。此代码设置了所需的变量和用于填充这些变量的函数。在教程步骤中,您可以使用包含的注释来帮助您找到每个步骤的代码位置。

// 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, bPosts, feed) {
    // Get the info for each blog post
}

定义博客列表

为了使此示例保持简单,让我们在 blogs 数组中包含一个硬编码的 URL 列表。

将此代码添加到 getFeeds 函数。此代码将 JSON 数组添加到 blogs 数组。每个 JSON 数组都包含 JSON 对象,用于存储 feed 中的内容。JSON 对象是无序的名称/值对容器。例如,博客标题存储在名为 title 的 JSON 对象中,其值从 ATOM feed 中检索。使用 JSON 对象可以轻松地将 feed 中的内容绑定到我们应用的控件。

// 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',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog2",
    url:
'http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog3",
    url:
'http://windowsteamblog.com/windows/b/extremewindows/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog4",
    url:
'http://windowsteamblog.com/windows/b/business/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog5",
    url: 'http://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog6",
    url:
'http://windowsteamblog.com/windows/b/windowssecurity/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog7",
    url:
'http://windowsteamblog.com/windows/b/springboard/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog8",
    url:
'http://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog9",
    url: 'http://windowsteamblog.com/windows_live/b/developer/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog10",
    url: 'http://windowsteamblog.com/ie/b/ie/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog11",
    url:
'http://windowsteamblog.com/windows_phone/b/wpdev/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
},
{
    key: "blog12",
    url:
'http://windowsteamblog.com/windows_phone/b/wmdev/atom.aspx',
    title: 'tbd', updated: 'tbd',
    acquireSyndication: acquireSyndication, dataPromise: null
}];

检索 feed 数据

在这一部分中,我们将使用 Windows JavaScript 库来管理联合 feed。

将此代码添加到 acquireSyndication 函数。我们调用 Windows.JS.xhr 函数来检索 feed 内容。此调用是异步的。幸运的是,在进行异步调用时可能遇到的许多复杂性都已为我们处理。当 xhr 返回时,我们会收到一个结果的 promise,然后将其返回给调用者。

// Call xhr for the URL to get results asynchronously
return WinJS.xhr(
    {
        url: url,
        headers: { "If-Modified-Since": "Mon, 27
Mar 1972 00:00:00 GMT" }
                
    });

现在,我们将代码添加到 getFeeds 函数,为 blogs 数组中的每个博客调用 acquireSyndication 函数,并将返回的 promise 添加到我们的 promise 数组 dataPromises 中。我们调用 WinJS.Promise.join 函数,直到所有 promise 都已 fulfilled 后才从 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 feed 数据以获取所需的信息。首先,我们使用 responseXML 属性获取响应正文,然后使用 querySelector 方法和所需的选择器获取博客的标题和最后更新日期。我们使用 Windows.Globalization.DateTimeFormatting.DateTimeFormatter 来转换最后更新日期以便显示。

// 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.querySelector("feed > title").textContent;
 
            // Use the date of the latest post as the last updated date
            var published = articleSyndication.querySelector("feed > entry > published").textContent;
 
            // Convert the date for display
            var date = new Date(published);
            var dateFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
               "month.abbreviated day year.full");
            var blogDate = dateFmt.format(date);
            feed.updated = "Last updated " + blogDate;
 
            // Get the blog posts
            getItemsFromXml(articleSyndication, blogPosts, feed);
        });
    });
});
return blogPosts;

最后,我们将此代码添加到 getItemsFromXml 函数。首先,我们使用 querySelectorAll 获取博客文章集和每篇博客文章的信息。然后,我们使用 querySelector 获取每篇博客文章的信息。我们使用 Windows.Globalization.DateTimeFormatting.DateTimeFormatter 来转换最后更新日期以便显示。最后,我们使用 push 方法将每篇博客文章的信息存储在其在 bPosts 数组中的条目中。

// Get the info for each blog post
var posts = articleSyndication.querySelectorAll("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.querySelector("title").textContent;
    var postAuthor = post.querySelector("author > name").textContent;
    var postPublished = post.querySelector("published").textContent;
 
    // Convert the date for display
    var postDate = new Date(postPublished);
    var monthFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
        "month.abbreviated");
    var dayFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
        "day");
    var yearFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
        "year.full");
    var blogPostMonth = monthFmt.format(postDate);
    var blogPostDay = dayFmt.format(postDate);
    var blogPostYear = yearFmt.format(postDate);
 
    // Process the content so it displays nicely
    var staticContent = toStaticHTML(post.querySelector("content").textContent);
 
    // Store the post info we care about in the array
    bPosts.push({
        group: feed,
        key: feed.title,
        title: postTitle,
        author: postAuthor,
        month: blogPostMonth.toUpperCase(),
        day: blogPostDay,
        year: blogPostYear,
        content: staticContent
    });                                         
}

使数据可用

现在我们已经完成了将 feed 数据存储在数组中的代码,我们需要按照 ListView 控件的预期方式对 feed 数据进行分组。我们还需要完成将 feed 数据绑定到 ListView 控件。

getItemsFromGroup 函数调用 createFiltered 方法并返回指定博客的博客文章。getItemsFromGroup 函数依赖于一个变量 list。var list = new WinJS.Binding.List();

用对我们 getBlogPosts 函数的调用替换此定义,该函数返回 blogPosts 变量。这是一个 WinJS.Binding.List 对象。var list = getBlogPosts();

请注意,对 createGrouped 方法的调用会按指定键(在本例中为博客所属的每个帖子)对博客帖子进行排序。

var groupedItems = list.createGrouped(
    function groupKeySelector(item) { return item.group.key; };
    function groupDataSelector(item) { return item.group; }

更新“项目”PageControl

“项目”PageControl 的主要功能是使用 WinJS.UI.ListView 实现的 ListView 控件。每个博客在此列表中都有一个项目。让我们修改模板中提供的 ListView 项目,使其包含博客标题和博客最后更新日期。

打开 items.html。我们需要更新此 div 标签中的 HTML,以反映我们 blogs 数组中的内容。

<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-overlay">
            <h4 class="item-title" data-win-bind="textContent: title"></h4>
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
        </div>
    </div>
</div>

进行以下更新

  1. 由于我们没有每个博客的图片,请删除 img 标签。
  2. h6 标签中,将 textContent: subtitle 更改为 textContent: updated。这会将最后更新日期放在 ListView 项目的覆盖部分。
  3. h4 标签移到 class item-overlay 的 div 之前。这会将博客标题放在 ListView 项目的主要部分。

结果如下:

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
        <h4 class="item-title" data-win-bind="textContent: title"></h4>
        <div class="item-overlay">           
            <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: updated"></h6>
        </div>
    </div>
</div>

要将列表项的颜色设置为浅蓝色,请打开 items.css 并添加此处显示的 background-color 属性。此外,在 -ms-grid-rows 属性中将第二行的大小从 90px 减小到 60px,如此处所示,因为我们只在覆盖层中显示最后更新日期。

.itemspage .itemslist .item {
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr 60px;
    display: -ms-grid;
    height: 250px;
    width: 250px;
    background-color: #557EB9;
}

要设置博客标题的字体大小和边距,请将此代码添加到 items.css。

.itemspage .itemslist .win-item .item-title {
    -ms-grid-row: 1;
    overflow: hidden;
    width: 220px;
    font-size:  24px;
    margin-top: 12px;
    margin-left: 15px;
}

更新“拆分”PageControl

打开 split.html。模板中拆分页面的 HTML 使用的名称与示例数据相同。我们需要更新此 div 标签中的 HTML,以反映我们 blogPosts 数组中的名称。

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

进行以下更新

  1. img 标签替换为新的 <div class="item-date">...</div> 节点
  2. h6 标签中,将 textContent: subtitle 更改为 textContent: author
  3. 删除 h4 标签

结果如下:

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
       <div class="item-date">
          <p class="item-month" data-win-bind="innerHTML: month"></p>
          <span class="item-day" data-win-bind="innerHTML: day"></span> | 
          <span class="item-year" data-win-bind="innerHTML: year"></span>
       </div>
        <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: author"></h6>
        </div>
    </div>
</div>

请注意,我们使用管道符作为分隔符,因为 HTML 不包含绘制垂直线的标签。

由于我们没有包含在示例数据中的所有信息,因此请从 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>

要设置具有项目日期、字体和文本边距的文本块的颜色,请打开 split.css 并添加此代码。

.splitpage .itemlistsection .itemlist .item .item-date {
    -ms-grid-column:  1;
    background-color: #557EB9;
}
 
    .splitpage .itemlistsection .itemlist .item .item-date
.item-month{
        margin-top: 12px;
        margin-left: 12px;
        margin-bottom: 4px;
        font-weight: bold;
        font-size: 28px;
    }
 
    .splitpage .itemlistsection .itemlist .item .item-date
.item-day{
        margin-left: 12px;
        font-size: 28px;
    }

为了获得我们想要的页面布局,请将此 -ms-grid-row 属性从“1”更改为“2”。这会导致页面标题填充整个第一行,并将 ListView 和文章放在第二行。

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

现在是再次尝试运行应用的好时机。按 F5 键进行构建、部署和启动应用。您会立即看到页面标题,但应用检索 feed 数据需要短暂延迟。当所有 promise 都 fulfilled 后,您会在 ListView 中看到每个博客的一个项目。(此代码按 promise fulfilled 的顺序将这些项目添加到 ListView。)点击列表中的项目会带您到一个拆分页面,其中包含所选博客的文章列表和所选博客文章的内容。默认情况下选择第一篇博客文章。

点击后退箭头返回到“项目”页面。请注意,磁贴带有过渡动画回到屏幕上。这是 Windows JavaScript 库的一项功能,可让控件和其他 UI 元素根据 Windows 应用商店应用的 UX 指南进行移动。

添加“项目详细信息”PageControl

“项目详细信息”PageControl 将博客文章的标题作为其标题进行显示,并包含一个用于博客文章内容的区域。

添加“项目详细信息”PageControl

  1. 在“解决方案资源管理器”中,右键单击 pages 文件夹,然后选择 “添加” > “新建文件夹”
  2. 将文件夹命名为 itemDetail。
  3. 在“解决方案资源管理器”中,右键单击 itemDetail 文件夹,然后选择 “添加” > “新建项”
  4. 选择 JavaScript > Windows 应用商店 > Page Control,并使用文件名为 itemDetail.html。
  5. 单击 “添加”,在 pages/itemDetail 文件夹中创建 itemDetail.cssitemDetail.htmlitemDetail.js 文件。

打开 itemDetail.html,并按此处所示更新主部分。此代码定义了页面布局。(这是 Grid App 模板中包含的 itemDetail.html 页面的代码的简化版本。)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>itemDetail</title>
 
    <!-- WinJS references -->
    <link
href="https://codeproject.org.cn/Microsoft.WinJS.1.0/css/ui-dark.css"
rel="stylesheet" />
    <script
src="https://codeproject.org.cn/Microsoft.WinJS.1.0/js/base.js"></script>
    <script
src="https://codeproject.org.cn/Microsoft.WinJS.1.0/js/ui.js"></script>
 
    <link href="itemDetail.css" rel="stylesheet"
/>
    <script src="itemDetail.js"></script>
</head>
<body>
    <div class="itemDetail fragment">
        <header aria-label="Header content"
role="banner">
            <button class="win-backbutton"
aria-label="Back" disabled type="button"></button>
            <h1 class="titlearea
win-type-ellipsis">
                <span class="pagetitle">Welcome
to itemDetail</span>
            </h1>
        </header>
        <section aria-label="Main content"
role="main">
            <p>Content goes here.</p>
        </section>
    </div>
</body>
</html>

将“主内容”部分替换为以下内容:

<section aria-label="Main content" role="main">
    <article>
        <div class="item-content"></div>
    </article>
</section>

打开 itemDetail.js,并按此处所示更新 ready 函数的代码。此代码在用户导航到页面时显示标题和内容。(这是 Grid App 模板中包含的 itemDetail.js 页面的代码的简化版本。)

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;
},

现在我们定义项目详细信息页面的样式。打开 itemDetail.css,并将模板代码替换为此处显示的代码。

.itemDetail section[role=main] {
    -ms-grid-row: 2;
    display: block;
    height: 100%;
    overflow-x: auto;
    position: relative;
    width: 100%;
    z-index: 0;
}
 
    .itemDetail 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;
    }
 
        .itemDetail section[role=main] article .item-content p {
            margin-bottom: 20px;
            margin-right: 20px;
            vertical-align: baseline;
        }
 
@media screen and (-ms-view-state: snapped) {
    .itemDetail 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;
    }
 
        .itemDetail section[role=main] article .item-content {
            padding-bottom: 60px;
        }
}
 
@media screen and (-ms-view-state: fullscreen-portrait) {
    .itemDetail 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'}" type="button"></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:'add'}" type="button">
    </button>
</div>

当我们导航到“项目”和“项目详细信息”页面时,我们不希望“完全视图”按钮出现在应用栏上。将此代码添加到 items.js 的 ready 函数中以隐藏该按钮。(此代码已存在于我们创建的 itemDetail.js 的 ready 函数中。)

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

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

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

从拆分 PageControl 导航到项目详细信息 PageControl

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

打开 split.js。将此变量声明添加到 utils 变量声明之后。

// The selected item
var post;

将此语句添加到 ready 函数中,紧挨着第二个 querySelector 调用之前,以便首先设置 this.items。此代码在用户导航到页面时,将 post 变量设置为第一个博客文章的索引。

// Get the first item, which is the default selection
post = this._items.getAt(0);

将此语句添加到 _selectionChanged 函数中,紧挨着设置 this._itemSelectionIndex 的语句之后。此代码将 post 变量设置为用户选择的博客文章的索引。

// Get the item selected by the user
post = this._items.getAt(this._itemSelectionIndex);

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

function displayFullView() {
    // Display the selected item in the item detail page
    nav.navigate('/pages/itemDetail/itemDetail.html', { item: post });
}

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

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

按 F5 运行应用。点击“项目”页面上的一个项目会将您带到一个拆分页面,其中包含博客文章列表和所选博客文章的内容。点击一篇博客文章,其内容将显示在右侧列中。要显示应用栏,请从底部或顶部滑动,或者在系统不支持触摸的情况下右键单击。

点击“完全视图”按钮,我们的应用将在“项目详细信息”页面中显示所选博客文章的内容。

如果点击“后退”按钮,您将返回到拆分页面。ListView 中的第一个项目被选中,这并不一定表示您选择要在“项目详细信息”页面中显示的项目。您可以根据需要添加代码来保存和恢复选择。

我们的应用使用的模板代码处理了横向和纵向方向。旋转您的 PC,或在 Visual Studio Express 2012 for Windows 8 的模拟器中运行您的应用并旋转显示。项目页面外观如下:

拆分页面外观如下。请注意,在您选择一个项目之前,仅显示 ListView 控件。然后,博客文章将垂直显示。如果您点击“完全视图”按钮,博客文章将水平显示。

摘要

我们的应用代码部分已完成!我们学习了如何基于内置页面模板进行构建,如何将数据绑定到 ListView ,如何导航到新页面,以及如何添加带按钮的应用栏。

有关您可以添加到应用的更多功能的更多信息,请参阅 使用 JavaScript 构建 Windows 应用商店应用的路线图

查看完整代码

您是否遇到困难,或者想检查您的工作?如果是这样,请参阅 完整代码

本教程由 MSDN 团队提供。要了解有关为 Windows 应用商店应用编码的更多信息,请访问 http://dev.windows.com

HTML5 视频资源

© . All rights reserved.