Background
Microsoft’s guidance for Windows 8 applications is based on content over chrome. Development styles for prior versions of Windows often included navigation controls, buttons, tabs, and other non-content related items intermixed with the data, often obscuring the information that the application was trying to convey. This isn’t to say that we were all doing it wrong all of these years, as there wasn’t a mechanism (or even guidance) in place to provide an alternative.
Microsoft’s solution for this in Windows 8 is to provide the AppBar as well as the Charms bar. The AppBar stays out of the way until invoked by the user (by either swiping from the top or bottom of the screen or right clicking with the mouse), and then appears at the bottom (and top if that portion is also implemented) of the screen. This provides an easy to access option for actions and navigation commands that stay out of the way of the data until the user actively requests them to come into view.
The Charms (Search, Share, Devices, and Settings) provide a unified mechanism for building common features into your application. Like the AppBar, the Charms bar stays neatly tucked away until the user requests it (by swiping from the right or pressing Windows-C on the keyboard).
The Sample Application
The sample application that I have been building in my blog posts on MVVM (MVVM Part 1 and MVVM Part 2) has command buttons placed in the middle of the User Interface. This was done for simplicity, but as explained above, this is bad form.
The application is very simple (as shown in Figure 1). We have an Observable List (WinJS.Binding.List) that holds multiple Observable Contact cards. There are two commands on the user interface, one for updating the contact, and the other for adding a new contact record. If you haven’t been following this series, you can download the starter project here.
Figure 1 – The Sample Application
Design Goals
In this post, we will be moving the action buttons from the User Interface to the AppBar as well as some User Interface housekeeping to make sure the UI is consistent with expectations.
Rearranging the User Interface
With Mater Detail forms, the detail record is seldom (if ever) on top of the list of records. Unfortunately, that is exactly how this application has grown over the series of posts. Fortunately, fixing this is very simple – just move the div for the detail record and the markup for the two buttons to a location after the div for the ListView. The Binding Template can go just about anywhere on the page, since it isn’t shown to the user directly (I prefer to keep it before the ListView). The resulting <body> text is shown in Listing 1, and the resulting application is shown in Figure 2.
<div id="listViewTemplate" data-win-control="WinJS.Binding.Template">
<div style="width:400px;" class="win-type-x-large twoColumnLayout">
<div class="leftColumn" >
First Name: <br />
Last Name: <br />
Age: <br />
</div>
<div class="rightColumn">
<span data-win-bind="textContent:firstName"></span> <br />
<span data-win-bind="textContent:lastName"></span> <br />
<span data-win-bind="textContent:age"></span> <br />
</div>
</div>
</div>
<div data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource:ViewModel.ContactList.dataSource,
itemTemplate:select('#listViewTemplate')}"></div>
<div id="contactDetail" class="win-type-xx-large twoColumnLayout">
<div class="leftColumn" >
First Name: <br />
Last Name: <br />
Age: <br />
</div>
<div class="rightColumn">
<span data-win-bind="textContent:firstName"></span> <br />
<span data-win-bind="textContent:lastName"></span> <br />
<span data-win-bind="textContent:age"></span> <br />
</div>
</div><br /><br />
<button id="updateContactCommand" class="win-type-x-large">
Update Contact
</button>
<button id="addContactCommand" class="win-type-x-large">
Add Contact
</button>
Listing 1 – default.html
Figure 2 – Update User Interface
Adding An AppBar
The first step in adding an AppBar control is made extremely simple with Blend, which now ships with all paid versions of Visual Studio. Open default.html in Blend, click on JavaScript controls (in the Assets tab), then drag the AppBar Control onto the form. This is shown in Figure 3.
Figure 3 – Using Blend to add an AppBar Control
In addition to adding the core AppBar markup, Blend also adds a single AppBar command to the AppBar. Blend makes it very easy to add any of the additional AppBar Command types (Flyout, Separator, and Toggle Commands) into your AppBar (as shown in Figure 4).
Figure 4 – AppBar Controls available in Blend
Updating the Command Options
For now, I just want to transfer the current functionality to the AppBar – I’ll add FlyOuts for interacting with the user when adding or updating records in a later post. Using the HTML Attributes in Blend (as shown in Figure 5), I set the following properties on the Command Buttons:
html |
data-win-options |
id |
label |
tooltip |
type |
editContact |
‘Edit Contact’ |
‘Edit Contact’ |
‘button’ |
addContact |
‘Add Contact’ |
‘Add Contact’ |
‘button’ |
NOTE: To clear a value in Blend, click on the box at the end of the property, and select “Clear”.
Figure 5 – Setting AppBar command options in Blend
Since I no longer need the old buttons, they can be deleted from default.html. The markup for the AppBar and the commands is shown in Listing 2.
<div data-win-control="WinJS.UI.AppBar">
<button id="editContact" data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{icon:'edit', label:'Edit Contact', tooltip:'Edit Contact', type:'button'}">
</button>
<button id="addContact" data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{icon:'add', label:'Add Contact', tooltip:'Add Contact', type:'button'}">
</button>
</div>
Listing 2 – The AppBar and Commands
Using The New Commands
To take advantage of the new commands, the only change necessary is the JavaScript selectors in default.js. All of the event handler code for the HTML buttons works just fine with AppBar commands. Yet another example of Microsoft making sure that existing Web Development knowledge cleanly transfers to Windows 8 development! The changes are shown in Listing 3 (with the original code for the command selectors commented out to show the change). I could have reused the same names as the original buttons and not have to change a single line of JavaScript, but the new names are more fitting for the direction I am taking the functionality of the commands.
//var updateContactButton = document.getElementById('updateContactCommand');
var updateContactButton = document.getElementById('editContact');
//var addContactButton = document.getElementById('addContactCommand');
var addContactButton = document.getElementById('addContact');
Listing 3 – Updated selectors for AppBar commands
Figure 6 – Updated application with AppBar commands
Summary
In this blog post, we removed the commands from the User Interface to be aligned with the Microsoft Design Recommendations for Windows 8. Now that the commands are tucked away in the AppBar, the application can focus on the data and the content, and not worry about commands or navigation getting in the way. We also saw that interacting with AppBar commands in JavaScript works exactly the same as working with regular commands. The display magic for the AppBar is all done through CSS (and the CSS is provided to us by Microsoft).
You can download the source code here.
About the author
Philip Japikse
|
Philip Japikse an international speaker, a Microsoft MVP, INETA Community Champion, MCSD, CSM/ CSP, and a passionate member of the developer community, Phil Japikse has been working with .Net since the first betas, developing software for over 20 years, and heavily involved in the agile community since 2005. Phil works as a Developer Evangelist for Telerik's RadControls for Windows 8 as well as the Just family of products (JustCode, JustMock, JustTrace, and JustDecompile) and hosts the Zero To Agile podcast (www.telerik.com/zerotoagile). Phil is also the Lead Director for the Cincinnati .Net User’s Group (http://www.cinnug.org). You can follow Phil on twitter via www.twitter.com/skimedic read his Telerik blog at http://blogs.telerik.com/skimedic and his personal blog at www.skimedic.com/blog. |