二十、使用设置和应用数据

在这一章中,我将向您展示如何向用户展示应用设置,以及如何使它们持久化。几乎每个应用都有一些用户可以自定义的功能,以与其他应用一致的方式向用户提供选项是一种重要的方式,可以确保用户在使用应用时能够建立在他们以前的 Windows 体验上。

对应用有特殊的规定,使设置工作变得简单和相对容易。我将向您展示呈现设置的不同技术以及持久存储设置(和其他数据)的 Windows 特性。表 20-1 提供了本章的总结。

images

准备示例 App

我将建立在我在第 19 章中用来解释生命周期事件的EventCalc例子之上。在那一章中,我向你展示的一个特性是当应用即将被挂起时如何存储会话状态。我当时提到,您不应该将用户设置存储为会话数据,所以我构建同一个示例应用来告诉您故事的其余部分是合适的。提醒一下,你可以看到EventCalc是如何出现在图 20-1 中的。

images

图 20-1。event calc 应用

准备示例应用

为了准备演示设置的应用,我在项目中添加了一个名为/js/settings.js的新文件,你可以在清单 20-1 中看到。这个文件定义了一个名为ViewModel.Settings的名称空间,我将在这里存储用户首选项。

清单 20-1 。settings.js 文件的内容

`(function () {     WinJS.Namespace.define("ViewModel", {         Settings: WinJS.Binding.as({             backgroundColor: "#1D1D1D",             textColor: "#FFFFFF",             showHistory: true         })     });

WinJS.Namespace.define("ViewModel.Converters", {         display: WinJS.Binding.converter(function (val) {             return val ? "block" : "none";         }),     });

})();`

ViewModel.Settings名称空间中的属性将控制应用布局的背景和前景色,以及显示计算历史的面板的可见性。我修改了default.html文件,将settings.js文件纳入范围,并添加了一些新的数据绑定,以便将ViewModel.Settings属性应用于适当的元素,如清单 20-2 所示。

清单 20-2 。将设置绑定添加到 default.html 文件

`<!DOCTYPE html>

         EventCalc

              

                        

    
        
    
    
        Events         
        
    
    
        Calculator         
                         +                          =             ` `            Calculate         
    
    
        History         
        
    

`

我要做的最后一个更改是添加一个对WinJS.Binding.processAll方法的额外调用,以便激活标记中的数据绑定。您可以在清单 20-3 中看到我添加到/js/default.js文件中的附加语句。

清单 20-3 。激活设置数据绑定

`... app.onactivated = function (args) {     var promises = [];

if (args.detail.kind === activation.ActivationKind.launch) {         switch (args.detail.previousExecutionState) {             case activation.ApplicationExecutionState.suspended:                 startBackgroundWork();                 writeEventMessage("Resumed from Suspended");                 break;             case activation.ApplicationExecutionState.terminated:                 ViewModel.State.setData(app.sessionState);                 writeEventMessage("Launch from Terminated");                 promises.push(performInitialization());                 break;             case activation.ApplicationExecutionState.notRunning:             case activation.ApplicationExecutionState.closedByUser:             case activation.ApplicationExecutionState.running:                 writeEventMessage("Fresh Launch");                 promises.push(performInitialization());                 break;         }

if (args.detail.splashScreen) {             args.detail.splashScreen.addEventListener("dismissed", function (e) {                 writeEventMessage("Splash Screen Dismissed");             });         }        promises.push(WinJS.UI.processAll().then(function() {             return WinJS.Binding.processAll(document.body, ViewModel.Settings);         }).then(function () {             return WinJS.Binding.processAll(calcElems, ViewModel.State);         }));

args.setPromise(WinJS.Promise.join(promises));     } }; ...`

这些更改和添加的结果是一组可观察的属性,在ViewModel.Settings名称空间中定义。当这些属性改变时,default.html文件中标记的数据绑定会更新关键元素的 CSS 值。您可以通过使用调试器启动应用(从 Visual Studio Debug菜单中选择Start Debugging)并在JavaScript Console窗口中输入以下语句来测试这些属性:


ViewModel.Settings.showHistory = false **ViewModel.Settings.backgroundColor = "#317f42"**


改变设置值会触发数据绑定的更新,改变背景颜色并隐藏计算历史,如图图 20-2 所示。

images

图 20-2。改变设置属性的值

在接下来的小节中,我将向您展示向用户呈现这些设置属性并持久存储用户选择的值的机制。

向用户呈现设置

Windows 提供了一个处理设置的标准机制,它是通过设置魅力(你可以通过魅力栏或使用Win+I快捷方式打开它)来触发的。

设置通过设置窗格呈现,如图图 20-3 所示,默认设置窗格显示了应用的一些基本细节,并包含一个Permissions链接,向用户显示应用在其清单中声明了哪些功能。“设置”面板的底部有一组标准按钮,用于配置系统范围的设置。

images

图 20-3。默认设置窗格

如果你点击Permissions链接,你会看到一个设置弹出按钮的例子,如图 20-4 中的所示。这就是设置的处理方式——它们被分组到类别中,在设置窗格中显示为链接,单击链接会显示一个设置弹出按钮,其中包含更多详细信息,通常还包含允许用户更改应用设置的控件。

images

图 20-4。权限弹出按钮

images 提示您可以通过更改应用清单的Packaging部分中的值来更改Permissions弹出按钮中显示的详细信息。

如图所示,设置弹出按钮有一个标题区,其中包含一个后退按钮——单击此按钮将返回设置窗格。设置窗格和设置弹出按钮都是轻触式的,这意味着用户可以通过单击或触摸屏幕上的其他地方来关闭它们,就像我在本书的前一部分描述的弹出 UI 控件一样。

在这一部分,我将在设置窗格中添加额外的链接,以允许用户查看和更改我在/js/settings.js file中定义的设置。我将向窗格添加两个新链接:Colors链接将打开一个窗格,让用户设置backgroundColortextColor设置属性,History链接将打开一个窗格,让用户设置showHistory设置属性。在这个过程中,我将演示你的应用如何将自己集成到标准设置系统中,以及你如何创建设置弹出按钮,其外观和行为与图 20-4 中的默认Permissions弹出按钮相同。

images 通过设置魅惑辅助设置是契约的一个例子。契约是一组定义明确的交互、事件和数据对象,允许应用在标准的 Windows 功能中具体化。设置只是我在本书中解释的契约之一——当我向你展示如何将你的应用集成到 Windows 搜索功能中时,你会在第 21 章中看到一个更复杂的例子。

定义弹出型 HTML

我需要做的第一件事是为每个设置面板创建一个 HTML 文件。首先,我创建了一个名为colorsSettings.html的文件,其内容可以在清单 20-4 中看到。这是一个相对简单的文件,所以我将 CSS 和 JavaScript 放在 HTML 标记所在的文件中。

清单 20-4 。colorsSettings.html 文件的内容

<!DOCTYPE HTML> <html> <head>     <title></title>     <style>         #colorsDiv #backbutton { color: white; border-color: white;}         #colorsDiv div.win-header { color: white; background-color: #004d60;}     </style>     <script>         WinJS.UI.Pages.define("colorsSettings.html", {             ready: function () {                 WinJS.Utilities.query("#colorsDiv input").listen("change", function (e) {                     ViewModel.Settings.backgroundColor = backgroundColorInput.value;                     ViewModel.Settings.textColor = textColorInput.value;                 });                 backbutton.addEventListener("click", function () {                     WinJS.UI.SettingsFlyout.show();                 });                 WinJS.Binding.processAll(colorsDiv, ViewModel.Settings);             }         });     </script> </head> <body>     <div id="colorsDiv" **data-win-control="WinJS.UI.SettingsFlyout"** **            data-win-options="{width:'narrow'}**">         <div class="win-header">             <button id="backbutton" class="win-backbutton"></button>             <div class="win-label">Colors</div>         </div>         <div class="win-content">             <div>                 <h2>Background Color</h2>                 <input id="backgroundColorInput" data-win-bind="value:backgroundColor" />             </div>             <div>                 <h2>Text Color</h2>                 <input id="textColorInput" data-win-bind="value:textColor" />             </div>         </div>     </div> </body> </html>

这个 HTML 的核心是一个名为SettingsFlyout的 WinJS UI 控件。该控件应用于div元素,仅用于向用户呈现设置。width选项是由SettingsFlyout定义的唯一配置选项,它允许你请求一个标准的弹出按钮(使用narrow值)或一个有额外空间的按钮(使用wide值)。

设置弹出文件的内容通常需要一些 JavaScript 来处理用户输入,您可以看到我已经使用了WinJS.UI.Pages.define方法(我在第 7 章中描述过)来确保在我设置我的事件处理程序和应用数据绑定之前加载文档中的元素。

images 提示我建议你在创建设置弹出按钮时使用列表中的 HTML 作为模板。它包含了你需要的一切——包括标题和后退按钮的标题,以及一个用于设置内容的区域。

对于这个设置弹出按钮,我定义了两个input元素,它们是绑定到ViewModel.Settings属性的数据,并且在change事件被触发时更新这些属性。对于另一个设置弹出按钮,我已经创建了一个非常相似的文件,叫做historySettings.html,它的内容你可以在清单 20-5 中看到。

清单 20-5 。historySettings.html 文件的内容

<!DOCTYPE HTML> <html> <head>     <title></title>     <style>         #historyDiv #backbutton { color: white; border-color: white;}         #historyDiv div.win-header { color: white; background-color: #004d60;}     </style>     <script>         WinJS.UI.Pages.define("historySettings.html", {             ready: function () { `                showToggle.addEventListener("change", function () {                     ViewModel.Settings.showHistory = showToggle.winControl.checked;                 });                 backbutton.addEventListener("click", function () {                     WinJS.UI.SettingsFlyout.show();                 });                 WinJS.Binding.processAll(historyDiv, ViewModel.Settings);             }         });     

    
        
                         
History