Silverlight 4 User Interface Cookbook
Build and implement rich, standard-friendly user interfaces with Silverlight and Expression Blend
Vibor Cipan
BIRMINGHAM - MUMBAI
Silverlight 4 User Interface Cookbook Copyright © 2010 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, Packt Publishing, nor its dealers or distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: August 2010
Production Reference: 1190810
Published by Packt Publishing Ltd. 32 Lincoln Road Olton Birmingham, B27 6PA, UK. ISBN 978-1-847198-86-0 www.packtpub.com
Cover Image by Leisha Bryant (
[email protected])
Credits Author Vibor Cipan Reviewers Thomas Martinsen Chanh Ong Yingwei Yang Acquisition Editor David Barnes Development Editor Tarun Singh Technical Editors Pallavi Kachare Namita Sahni Indexer Rekha Nair
Editorial Team Leader Akshara Aware Project Team Leader Ashwin Shetty Project Coordinator Ashwin Shetty Proofreader Aaron Nash Production Coordinators Adline Swetha Jesuthas Kruthika Bangera Cover Work Adline Swetha Jesuthas
Foreword At a recent workshop, a developer raised his hand and asked me if I could teach me him how to design. I responded with "Not in 10 minutes, I can't." Although a poor attempt at humor on both of our sides, his request had a real motivation. As technologies like Silverlight push forward, the lines between where the design work stops and the development work begins have begun to blur. This new type of technology, which provides such a large amount of UI customization with ease, can produce amazing results. This type of UI freedom can also be very intimidating and possibly produce awful results. Trust me, I've seen it before. Guidance is needed for both developers and designers to know how best to take advantage of Silverlight's flexible UI capabilities. Luckily, there are a few people who specialize in this space between design and development and act as a catalyst to bring out the best results from the two sides. There are three tasks that this Design Developer person can aid with during the development cycle: •
Converting the graphical design assets into interactive UI elements that maintain the same appearance, interaction, and motion
•
Providing the integration of the UI elements with the logic, functionality, and data of the application
•
Sharing their knowledge with both designers and developers to bring them closer to the dividing line of tasks and improving their workflow and abilities
Vibor Cipan, the author of this book, is one of those Design Developers who helps with all three of the aforementioned tasks. He is also an active community member, with a popular blog, a passion for UX, and a lot of history in the Silverlight space. In this book, he shares his knowledge of UI patterns covering: when to use them, why they work, and how to implement them in Silverlight. For the designer who is already familiar with the UI patterns, this book can help you begin to implement them in Silverlight and Expression Blend. For the developer who already knows the code, this book can help you decide when and why to use which pattern.
Grab a copy of the book and share it with your team, refer to it as a reference (which is easily done due its tidy format), and learn how to take advantage of the amazingly flexible UI capabilities of Silverlight! Adam Kinney Principal, Designer and Developer—Pixel Lab
About the Author Vibor Cipan is currently serving as a CEO and Partner of the FatDUX Zagreb office, a
full service interactive agency with offices around the world. Before joining FatDUX, Vibor worked at Microsoft Development Center in Copenhagen and before that at Microsoft Croatia. One thing, however, has stayed constant, which is his focus on user experience, service design, usability, and information architecture. He has been awarded the prestigious title Microsoft Most Valuable Professional for three years in a row (and is still currently holding that title). He was the youngest awardee and first one in the CEE Europe to receive the award while a full-time student. He is technologically agnostic, but, his main interests however are focused around Silverlight, WPF, Expression, and Windows Phone user experiences. If asked if he is a designer or developer he will most likely say something like "I'm a devigner—a very special and unique breed. Instead of sitting on a chair, I've decided to be a bridge. I'm pixel pusher at heart, yet I'm confident navigating and understanding the code. Oh and throw in some business consulting and management and that would be my (dream) job." Today, Cipan is a well known professional and speaker, often seen talking at local and international conferences about user experience and service design topics, evangelizing and teaching the importance of the UX and service design for clients and building world class UX and service design solutions spanning the desktop, web, mobile ,and offline worlds. He is an active blogger blogging at his UX Passion blog (http://www.uxpassion.com/) and he is on Twitter under @viborc name. When he is not UX'ing he's an avid bicyclist and traveler. Some of his firm's clients are Microsoft,Real Networks and IISEIE, Zappos, Amazon, UN, and many others.
Acknowledgement They say that every journey begins with the first step and rare things reflect the journey metaphor better as writing your first book. Now, taking a look back I'm happy and proud to see this journey has brought this book in front of you. However, and we all know how cliché it sounds, this book would not be possible without help from many people involved in it. I wish to thank, for their extreme patience, encouragement, and ability to tolerate my busy schedule, my publisher Packt Publishing and many fine people there: Ashwin, Douglas, Namita, Pallavi, and Tarun—thank you so much for everything, you guys are terrific. I've started thinking about this book while I was working at Microsoft in Denmark. I've spent many hours talking and discussing different ideas with my colleagues from the UX team there. Many of them were my source of inspiration and encouragement, and they didn't even know that. Some of them are still in Copenhagen or Redmond, some are working somewhere else but thank you all for your ideas, suggestions, and tremendous opportunity to learn and grow: Anne, Ashu, David, Erlingur, Eva, Hans, Ingrid, JJ, Kim, Morten. Special thanks are in order for my manager who was a mentor, tutor, and a guide during my time in Denmark—Hans Roed Mark and to Jakob Nielsen our UX Director at Microsoft. They both have asked for more and more every time helping me grow my skills. Mange tak! Vjekoslav Babić deserves my appreciation as well. He was the one who introduced me to Packt and suggested that writing a book might be a great idea and a worthwhile project. Vjeko, hvala ti! After Microsoft, my new journey has started, one with the FatDUX. I was happy to get the ability to live my dream job and build my dream team. But now, FatDUX is so much more to me than just an employer. After all, the content for this book was written while I was working at FatDUX. Therefore, my friends and colleagues have supported me in so many different ways that I can't even remember all of them. Eric Reiss, Søren Muus, Jeff Parks, Linda Packer... I'm so proud to be the part of the FatDUX family. Looking forward to many, many great quacks with you!
However, my closest friend, Darko Čengija and my "number one" at FatDUX Zagreb, Antun Debak have been the greatest support one man can ever ask for. They have helped me manage my time, talked to customers, shared their experiences, and been there every time I needed them. Thank you both for being such great friends, colleagues, and professionals. Hvala vam od srca! Huge thanks goes to Katarina Itrić. We all need someone in our life that we can rely on, share our stories with, have long night walks and sometimes just sit together and enjoy life, just like that. Hvala ti za to! And to my family… you were here at any moment, providing me with moral support. But two members of my family deserve it most. My mother, Hedviga Koči for her continuous mantra: "Do whatever you want in your life, but do it best you can. Put yourself in—that is the only way to go." And to my grandfather, who was one of the last true gentlemen around, Pavle Poly Cipan, who passed away several weeks before I had finalized the book. Unfortunately, he was not here to see this book and hold it in his hands, but his wisdom, kindness are something that has enabled me to go even further and live my dreams. Though my Hungarian is not best he deserves one warm and heart full Köszönöm szépen, nagypapi!. Winners never quit. Quitters never win. (Napoleon Hill)
About the Reviewers Thomas Martinsen is an experienced and reputable .NET developer with focus on Silverlight, WPF, and Windows Phone development. In recent years, Thomas has worked with several companies and helped them to implement Silverlight in their solutions. Besides acting as advisor and partner on several Silverlight and WPF projects, Thomas teaches Silverlight, WPF, and Expression Blend.
Chanh Ong is a Computer Specialist and has many years of experience in various
computer platforms and operating system, programming languages such as PHP, Javascript (AJAX), C, VB, Perl, Microsoft Access, dBase, FoxPro, and so on, system administration on Unix, Linux, Vax and Microsoft Windows, DBA of various databases like Oracle, Mysql, Postgres, Informix, MSSQL, and so on. He utilizes web server Apache and IIS to help build web application. He also does custom template for client. He has an open source project called COAddOns that develops several add-ons for Mambo, Joomla, MiaCMS, and MoseCMS, which is an easy and extensible CMS. He is also a former Mambo CMS core developer. He researches CMS and tools! He has a lot of experience installing various CMS including Wiki and he also set up sites using Microsoft SharePoint services. He has a website that helps him on his effort of researching various CMS tools and blog about his findings. His website also provides support for his open source project called COAddOns.
His main web site is: http://support.ongetc.com and his open source project document site is: http://docs.ongetc.com and his blog is: http://blog.ongetc.com. He wrote an article for Packt Pub called How to Choose an Open Source Content Management System and you can find it online here at http://www.packtpub.com/ article/how_to_choose_an_open_source_content_management_system . He has also reviewed for Packt Open Source CMS Beginner's Guide and has participated as a judge for Packt annual Open Source CMS Award.
I want to thank Reshma Sundaresan for letting me to be the book reviewer for this book and Ashwin Shetty for working closely with me on scheduling the reviewing of each chapter. I like to thank the author of this book which he has done a very nice job with this book especially since Silverlight release several versions during the development of this book. Silverlight has gone from version 2 to version 4. This book is truly a "cookbook" it give the exposure of many features of Silverlight in a easy follow instruction. I also want to thank my family to let me have the time to do this book review
Yingwei Yang joined Microsoft in 2008. Before that, he worked for ITG and Redcats USA. Yingwei enjoy working with .NET technology and is a big fan of Service Oriented Architecture, Silverlight, and Cloud. He always thinks that Web Services/Software as a Service that brings endless opportunities and possibilities. Yingwei Yang also helped review the book SOA with WCF, LINQ, and Visual Studio 2008 (6620) and WCF-Muti-tier Services Development with LINQ (1148).
This book I dedicate to my mother Hedviga and my late grandpa Pavle. For all your support, for all those years and for many more to come…Hvala!
Table of Contents Preface Chapter 1: Layouts and General Content Organization Introduction Fluid layout Creating a navigation pane from scratch Window management and positioning Wizards Progressive disclosure—showing additional controls on demand Control docking with DockPanel Journal navigation Tabs Adding a status bar area
Chapter 2: Actions and Commands
Introduction Command buttons Classical menus Context (right-click) menus Progress indicators with known process duration Progress indicators with unknown process duration Creating menu drop-down Command links Split button and creating one from scratch Multiple item selections with simple ListBox Multiple item selections with ListBox and CheckBox combinations
1 7
7 8 15 25 35 47 47 52 57 64 73
83
83 84 89 98 100 104 106 111 119 123 126
Table of Contents
Chapter 3: Searching, Finding, and Navigating
129
Chapter 4: Date and Time Input, Tables, and Ratings
173
Chapter 5: Maps, Pop-up Windows, and Escaping the Browser
197
Chapter 6: New Controls and Avant-Garde Features
227
Introduction Designing prominent action points How to create faceted navigation and classification Creating tree views Creating and using expanders and collapsible panels Creating and using a paging pattern Using titled sections Creating and using task panes (aka Action Panels) Creating and utilizing promoted actions Introduction Designing date picker interface Using and implementing the calendar interface Designing time input interface Implementing star-based rating Designing list views with alternating row colors
Introduction Implementing pop-up window (modal dialogs) in Silverlight Designing responsive enabling user interface Adding maps to Silverlight applications Building full-screen Silverlight experiences Implementing out-of-browser experiences Introduction Webcam support and printing Exploring and using pixel shaders and effects Animating ListBox items PathListBox—abandoning the rectangular ListBox
ii
129 130 133 138 143 149 155 160 167
173 174 178 184 188 191 197 198 204 209 217 221 227 228 234 240 246
Preface This book offers a number of tutorial-based recipes with each recipe depicting one of the commonly used user interface patterns built with Silverlight (and in some cases with WPF just to showcase the possibilities). Each recipe takes a step-by-step approach, first giving you the idea what is the recipe about, followed by the steps needed to be executed. The chapter then explains about the recipe, context for its usage and, last but not the least, the professional user interface and user experience guidelines. From discussion and recipes dealing with fixed and fluid layouts, sample data generation, and building the custom command link controls, to the more advanced and somewhat avant-garde topics covering the usage and implementation of webcam and printing support and pixel shader effects—this book is covering all you need to know to properly design and implement your user interface together with professional user experience and interface guidelines to make your solutions and apps pleasurable for your users.
What this book covers Chapter 1, Layouts and General Content Organization gives you an introduction to the different ways of content and interface organization. Not only covering the topics of when to use fixed and fluid layouts, but also content organization with tabs and other available controls, this chapter is fundamental in many aspects. Chapter 2, Actions and Commands gives you recipes and patterns involving regular buttons, progress bars, and list boxes. It covers ground touching many different patterns for bringing your UI to life and keeping your users happy and informed. You can also learn how to build your own custom control and expose its properties. Chapter 3, Searching, Finding, and Navigating teaches you how to architect your application's UI. By introducing you to the concepts of faceted navigation, prominent action points, titled sections, it gives you a precise guide on how and when to use specific Silverlight controls to build your desired UI.
Preface Chapter 4, Date and Time Input, Tables, and Ratings will show you how to use form elements to build usable and flexible date, time and calendar interfaces. Special attention is given to the globalization and related guidelines. Also, this recipe covers dealing with long lists–it will show you how real-life metaphors are used in modern UIs. Chapter 5, Maps, Pop-up Windows and Escaping the Browser showcases some of the more modern UI patterns possible with Silverlight. It also covers fundamental but often overlooked pattern called progressive disclosure. Looking at adding mapping capabilities to your application or to run and use your Silverlight application out of the browser? Those patterns are covered in this chapter. Chapter 6, New Controls and Avant-garde Features will show you how to use some of the coolest new Silverlight features. For example, PathListBox enables you to abandon classical, rectangular appearance of the ListBox container, while pixel shaders and effects can add some extra fun to your applications. Now add support for webcam and printing and you'll be able to build really rich and immersive experiences with Silverlight.
What you need for this book This book uses Expression Blend 4 for virtually all recipes in it. You might find it useful to use Visual Studio 2010 (or one of its free "express" editions) for better code editing and development experience, but Expression Blend 4 should be your first choice for this book. Though the book covers mostly Silverlight 4 and the user interface patterns and user experience guidelines are referring to Silverlight, first few chapters utilize WPF 4 (Windows Presentation Foundation) technology. Almost all ideas, approaches, methods, and guidelines applicable to WPF are also applicable to Silverlight itself. In order to use and follow all recipes, be sure that, apart from Expression Blend 4 you have installed Silverlight Toolkit. Silverlight toolkit adds support for numerous additional controls of your Silverlight 4 controls. You can get it from http://silverlight.codeplex.com. The last part of the book showcases usage of the PathListBox control. This control supported under Silverlight 4 is not (at the moment of writing this book) part of the Silverlight or Silverlight Toolkit. Also, effects, pixel shaders, and numerous other features are available to you when you install Expression Blend 4 SDK for Silverlight 4 available for free from:
http://www.microsoft.com/downloads/details.aspx?FamilyID=d197f51ade07-4edf-9cba-1f1b4a22110d&displaylang=en (short link: http://bit.ly/9KaiIG).
Who this book is for This book is targeted at both designers and developers. As an author, I've found myself in both roles at different points within my professional career and my intrinsic motivation was to create a book that will serve as a useful resource for designers and developers finding their way with Silverlight and Expression Blend. 2
Preface
Developers will find described UI techniques to be useful for them—especially the specific and professional design and user experience guidelines for described patterns and controls. Also, they will understand how to use Expression Blend as a design environment while still being able to safely resort to their more natural Visual Studio environment to write and test code logic. Designers will benefit from this cookbook as Silverlight is still gaining traction amongst them. While most designers are skilled with Flash or Photoshop, Silverlight and Expression Blend are still not their primarily designing environments and tools. With this book they will not only learn enough about technical side of the story but also many design related techniques, approaches, and guidelines while also getting the chance to understand interaction, code-based side of the story. In my opinion, I believe that the biggest value of this book lies in the numerous guidelines, ideas, methods, and approaches described. They are all here to help you build and implement great user experiences and to make your users happy, satisfied, and passionate about your products and services.
Conventions In this book, you will find a number of styles of text that distinguish between different kinds of information. Here are some examples of these styles, and an explanation of their meaning. Code words in text are shown as follows: "Now save all your files and go to the Window1.xaml file (basically, your main file)." A block of code is set as follows:
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold: private void expOptions_Collapsed(object sender,RoutedEventArgs e) { this.expOptions.Header = "Show advanced options"; }
3
Preface New terms and important words are shown in bold. Words that you see on the screen, in menus or dialog boxes for example, appear in the text like this: "LayoutRoot is a grid control hosted in UserControl". Warnings or important notes appear in a box like this.
Tips and tricks appear like this.
Reader feedback Feedback from our readers is always welcome. Let us know what you think about this book— what you liked or may have disliked. Reader feedback is important for us to develop titles that you really get the most out of. To send us general feedback, simply send an e-mail to
[email protected], and mention the book title via the subject of your message. If there is a book that you need and would like to see us publish, please send us a note in the SUGGEST A TITLE form on www.packtpub.com or e-mail
[email protected]. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide on www.packtpub.com/authors.
Customer support Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
Downloading the example code for the book You can download the example code files for all Packt books you have purchased from your account at http://www. PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.
4
Preface
Errata Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you would report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/support, selecting your book, clicking on the errata submission form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded on our website, or added to any list of existing errata, under the Errata section of that title. Any existing errata can be viewed by selecting your title from http://www.packtpub.com/support.
Piracy Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works, in any form, on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at
[email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors, and our ability to bring you valuable content.
Questions You can contact us at
[email protected] if you are having a problem with any aspect of the book, and we will do our best to address it.
5
1
Layouts and General Content Organization In this chapter, we will cover: ff
Liquid versus fixed layouts
ff
Navigation pane and how to create one from scratch
ff
Window management and positioning
ff
Wizards
ff
Progressive disclosure—showing additional controls on demand
ff
Control docking with Dock Panel
ff
Journal navigation
ff
Tabs
ff
Status bar area
Introduction Before we start building any application, regardless of being a web application built with Silverlight or a typical desktop application built with Windows Presentation Foundation, we will be faced with making some very basic and extremely important decisions. Will our application be able to scale to all of the different screens and resolutions or are we going for a fixed size? Other than that, how are we going to navigate through data presented in our application? How do we deal with windows and their positions, sizes, and states? We might go further and ask ourselves—can we conceive our application as the number of steps that users have to go through to complete one or more tasks? In that case, we might consider using the wizard UI pattern—how to create wizards and use Aero Wizard guidelines instead of older and obsolete Wizard97 guidelines.
Layouts and General Content Organization What will happen if we present too much data and information to the users, especially the data is irrelevant at the moment? It might lead to user confusion and dissatisfaction. Then, we can consider using the progressive disclosure and interesting UI patterns, which will help us cope with the "control and data overload" challenges. When we change the screen resolution or resize our windows or pages (please note that throughout this book these terms are being used to designate both, windows as parts of desktop applications and pages as parts of web applications, and in many cases UI patterns are same for both of those), controls might need to change their position, or even size. How do we implement and efficiently use control docking and scaling in those scenarios? Tabs are really useful: they enable us to put different content and controls on them. but despite them being so well-known, they are often misused and their usage can lead to a user's frustration. How do we use tabs properly and avoid having our users being frustrated and unhappy with our UI? Often, applications need to communicate information to their users. Some use pop-up windows, message boxes, or status bars. When should you consider using a status bar in your applications and when might it be a better idea to use some other UI pattern? This introduction has asked a lot of relevant questions. Now, it's time to proceed to some concrete answers and patterns.
Fluid layout There are two basic types of layouts that I want to consider here. First is the "fixed" layout, which basically means that all of the elements on your page or window will remain of the same size, irrespective of the screen resolution or other form factor. Then, there is "fluid" layout, which is good for enabling your content to adjust in a size that is appropriate for the current screen resolution, page dimensions, or generally the form factor that your users will be using. I am going to show you how to create a simple example of fixed and fluid layout in Silverlight. After that, I will give you some guidance on when to use fixed and when to use fluid layouts.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK. Some recipes in this and the following chapter are dealing with WPF, not with Silverlight. However, ideas, methods, approaches and user experience guidelines are applicable to both technologies. 8
Chapter 1
Now we will see how to create a fluid layout design.
How to do it... We will create two examples: the first one will demonstrate fluid layouts and the second one, fixed layouts. 1. After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a grid control hosted in UserControl. 2. Click on UserControl and change its height and width to Auto. To do that, go to Properties | Layout and change these properties. You will notice that they are set to 640 and 480 by default. Click on the little cross-arrows to set them to Auto. 3. Now, let's change the background color of LayoutRoot. Click on it in the Objects and Timeline pane, then go to Properties pane, navigate to the Brushes section, click on Background, select Solid color brush (second icon in the row), and select any color.
4. Press F5 or go to Project | Test Solution. 5. Your default web browser will start and you will see that the entire surface is covered in the color that you have previously set for your UserControl. Try resizing the browser and you will see that the surface is still completely covered with the selected color. 6. Close your browser and return to Blend. 7. Now we will add some objects on top of LayoutGrid and explore their behavior.
9
Layouts and General Content Organization 8. Change the design-time size of your UserControl by clicking and dragging handlers. Be sure to select UserControl before you start resizing. Note that this is changing only the design-time dimensions; run-time dimensions are still set to Auto.
9. On the toolbox (usually a left–aligned, vertical stripe with a number of different controls and tools), locate and select the Rectangle tool. You can also select it by pressing the M key. Draw several rectangles on top of LayoutRoot.
10. Again, press F5 to start your project. 10
Chapter 1
11. Play with your web browser now. Try changing the height and width and notice the behavior of the rectangles; they will also change their dimensions. You don't need to think about the mechanics behind this behavior right now. 12. Close your browser and return to Blend again.
How it works... How does it really work? The first step was changing the width and height properties of our UserControl to Auto. By doing so, we have allowed it to stretch automatically and fill in all available space. Simple as that! As our LayoutRoot is Grid control and its height and width properties have been set to Auto as well, LayoutRoot has also filled in all available space. We have just changed its color to make it more distinguishable. That is why our browser has been filled with LayoutRoot. After that, we added several rectangles to our LayoutRoot. And here is where some interesting behaviors start. Depending on the position of rectangles, some of them have been aligned horizontally or vertically to different sides of LayoutGrid. You can easily check that by clicking on them and then looking at HorizontalAlignment and VerticalAlignment under the Layout section within the Properties pane. Depending on that alignment, rectangles have been resizing when you have resized your browser. This was a very basic illustration of a liquid type of layout. We implement such a layout by using the grid control. Next, we will see how to make a fixed layout design.
How to do it... The steps are the same as those of the previous example—the creation of liquid fluid layout. I will assume that you have followed those directions and will take it from there. So, the main difference will be that instead of using Grid for LayoutRoot, we will use Canvas. 1. Right-click on LayoutRoot in the Objects and Timeline pane and from the menu, select Change Layout Type | Canvas. 2. Hit F5 to test your project. 3. Try resizing your browser again. Notice that the rectangles are keeping their positions as well as their dimensions intact. No matter what you do with your web browser size, they will be the same.
11
Layouts and General Content Organization
How it works... What happened after we changed our Grid control to Canvas type of control in the second example? All our rectangles have retained their size and positions, no matter what we have done with browser. The reason lies in the fact that Canvas control used the so-called "absolute positioning" and no layout policy is being applied to its child elements (rectangles in our case). You can literally consider it as a blank canvas.
There's more... To summarize, if you require maximum layout flexibility, you will use Grid control. It employs a number of different rules that can be applied to its child elements. For fixed layouts, which are not dependent on the screen size or resolutions, you will use Canvas control with absolute positioning.
More info about grid sizing, rows, and columns The grid is a truly versatile control and it enables you to build very flexible and sometimes complex layouts. A really important concept includes the possibility of dividing the grid into rows and columns, so that you get even more flexibility for your layouts. With grid control selected, position your mouse pointer over its border. You will notice that the mouse pointer will change its appearance and look like the following screenshot. You can click to add gridlines and define columns and rows in that way.
Now it is important to understand that the grid supports three ways of defining sizes for columns and rows—fixed, star, and auto. 12
Chapter 1
Fixed sizing uses exact pixel values to define row or column dimensions and means that they will not resize. Star sizing is using relative dimensions. In fact, it just indicates that width should be relative to the other star-sized columns (or rows, for that matter). Consider the following examples:
These three definitions will have the same column width. They will be identical with each column occupying the same amount of space. Now, consider this sample:
Here, the second column will be exactly two times bigger than the first one—a ratio of 2:1. Auto sizing means that the elements contained in a grid will also resize when the parent element resizes. It also means that the size of that column or row will depend on the size of the object that is located in that specific column or row. In XAML code, those definitions can look like this:
If you omit the width definition, Blend will automatically use star sizing. More detailed information about Grid and Canvas panel controls can be found in the Microsoft Expression Blend User Guide. Just hit F1 to access it within your application.
13
Layouts and General Content Organization
When to use fixed and when to use fluid layouts As you might have guessed already, there is no definite suggestion as to whether you should use only one of those layout types. Most likely, you will be using both of them. For example, message boxes or some dialogs will not benefit from resizing, but general application workspaces and web pages might want to look into using the most or all the space available to them in a meaningful manner. Also, if you need to preserve some fixed positions, you will use a fixed layout system. However, there are some proven practices outlining the usage of fixed and fluid layouts. Fixed layout works well for message boxes displaying information or errors to end users. They will not benefit significantly by adding the ability to resize them. Same goes for dialog boxes presenting users with progress on operations such as file copying or deleting. Keep their sizes fixed. Of course, you will ensure that they look good at different screen resolutions by testing them. You can even try to optimize content positioning, depending on the current screen resolution, but you should not allow users to resize those types of windows. If you consider web environments (you can apply the same principles here), all those modal windows, pop-up dialogs, and message boxes should be of a fixed size. When it comes to fluid layouts, the situation is more complex and it is more challenging to give design guidelines. But generally, you should use liquid layout type in cases where your application and dialog boxes can benefit from more space available to them. If you are building a file browser, you should implement the "liquid layout" system and use all available space to show as many files and folders as possible, so that your users can select them without scrolling too much. The same goes for web pages—in general, you would want to use as much space as possible for your content. But you should be aware that there are limits. You can put your textual content on the web page in liquid layout and enable it to resize together with your web browser and use the extra space available to them. But from the usability point of view, lines of text that are too long will decrease readability dramatically. Today, screen sizes are often over 20 inches and the trend of increasing sizes will continue into the future for some time—does that mean that you should enable your text or controls to scale accordingly? Absolutely not! The general rule is that your line of text should not be longer than about 66 characters. The reason for that is the fact that the human eye struggles with reading lines longer than that. I recall seeing that suggestion in The Elements of Typographic Style written by Canadian typographer, Robert Bringhurst. If you apply some good fonts and think about the overall appearance, you can go up to 75 characters, but don't go over that.
14
Chapter 1
What I like to do is define three sizes for my UI elements: preferred (which is basically default or optimal) size, minimum size, and maximum size. Preferred size is the size that the specific UI element will have on a given screen resolution. Minimum size is the size that will be the smallest size each element can scale to. For example, you can choose to set the minimum size of your window to 800 by 600 pixels and optimize all controls within it to fit into that. Also, by setting maximum size you can ensure that your form and controls will not stretch too much (as I suggested a moment ago when talking about text length). The great thing is that WPF and Silverlight also support these sizes and you can set them for each control you add to your UI. Other suggestions for dealing with controls in liquid layouts include keeping navigation elements (in web pages) anchored to top and left margins. Controls such as text boxes, tables, grids, and list views should increase their lengths and possibly even widths but again, recall what I have said in the previous paragraph about too long text lines—same applies to all controls. If you are using background colors, patterns, or similar elements, they should fill the new space completely and that is the only case where you should use all space available. It is also important to think about what will happen if your window or web page gets too small for its content. As I said earlier, set the minimum size for each and every control including container controls such as windows or pages. Optimize the layout for that case. If you don't do that, your controls might become inaccessible during run-time, aesthetic dimension will be also destroyed, and your application will become practically useless or extremely hard to use. Most WPF and Silverlight controls will adjust nicely by adding scrollbars to help adapt to these changes, so that will spare you from implementing all that logic by yourself. Don't be afraid to put some constraints on liquid layouts, sometimes too much flexibility will harm your user's experience though your intentions were quite the opposite. I am a firm believer that by limiting certain aspects of UI flexibility we are actually helping our users and building better experiences.
See also ff
Control docking with DockPanel
Creating a navigation pane from scratch If you have ever used Microsoft Outlook 2007 or even earlier versions (and the chances for that are pretty high), then you are already familiar with the concept of the navigation pane.
15
Layouts and General Content Organization Navigation pane consists of two major parts—content and buttons. Depending on the selected button, the content part will be changed. The content part can host a number of different controls, such as tree view.
In this recipe, I will show you how easy it is to use tab control from WPF and create a basic navigation pane control that resembles the look and feel of the Outlook's navigation pane. However, be sure to understand that this is not a replacement for third-party navigation pane controls, which offer much better and richer functionalities; but of course, all those goodies come at some price. 16
Chapter 1
So, if you need a really simple navigation pane, let's say for your prototyping efforts, then you can use this recipe and create one. If you are creating a commercial, line-of-business application, then you should consider getting one of those fully blown controls available on the market. That being said, this recipe is useful even if you go and buy third-party controls because general usage ideas and guidelines are equally applicable. And, it does seem surprising at the moment, but basic guidelines used for tabs may be applicable to a navigation pane pattern too.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears, select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After your new WPF project has been created, you should notice that under the Objects and Timeline pane, Window and LayoutRoot grid controls are visible. 2. Go to Asset Library and draw a TabControl on top of LayoutRoot. With TabControl selected, go to the Properties pane and set all margin values to 0 and Width to 250. This will align the tab control to the left-hand side and stretch it from the top to the bottom of your window, giving it a specified width. 3. Right-click on TabControl under the Objects and Timeline pane and from the drop-down menu, click on Add TabItem. Repeat this once again so that you end up with four tab item controls added under the TabControl parent. Your visual tree should look somewhat similar to the following screenshot:
4. Now select each TabItem and under the Properties pane, locate the Common Properties section and Header property. For each tab item, type the header value. You can go with the values found in Outlook 2007, for example, Mail, Calendar, Contacts, and Tasks.
17
Layouts and General Content Organization 5. Select TabControl and under the Common Properties section, change TabStripPlacement to Bottom. If you now go and press F5 to test your application, you will notice that tabs are located at the bottom. We are still fairly far away from the complete navigation pane found in Outlook but you can start to see where we are heading.
6. The next step is modifying the control template of the tab control. Right-click on TabControl and from the drop-down menu, click on Edit Control Parts (Template) | Edit a Copy...—a new dialog Create Style Resource will appear. Keep the default Name (Key). Notice the possibility to define this template on an application- or document-wide scope. Also, you can create a separate resource dictionary and use that file for all specific styles and templates. I will choose that approach this time and will use the same file for all other styles that I am going to create in this recipe. So, click on New... and accept the defaults from the new dialog. Now hit OK on the first dialog, and just make sure that under the Define in section, the resource dictionary is selected with the name of the RD file that you have just created. 7. Now you are in template editing mode. If you now take a look at the Objects and Timeline pane, you will notice that the scope has been set to TabControlStyle1— our TabControl template. This enables us to modify the look of our controls without making an impact and destroying their functionality. 8. Click on HeaderPanel and notice that HeaderPanel is of the TabPanel type. You can see that at the very top under the Properties pane. We need to change TabPanel to StackPanel. To do that, press F11 to switch to "XAML" or "Split" view, which will enable you to edit the XAML code. Locate the following line:
18
Chapter 1
And change it to: <StackPanel Margin="2,2,2,0" x:Name="HeaderPanel" Grid.Column="0" Grid.Row="0" IsItemsHost="true" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
9. Now save all your files and go to the Window1.xaml file (basically, your main file). 10. Press F5 to test your application now and notice that the tabs are now stacked pretty much in the same way as they are in Outlook 2007: one above the other.
11. Let's go and make more changes. Select all tab item controls (CTRL + click) and then change their height to 32. Also, change the left and right margin values to -2. Now, your navigation pane is starting to look like a real one from Outlook.
19
Layouts and General Content Organization 12. Take a look at the There's more... section (of this part) for further possibilities of customization and changes.
How it works... The key for understanding how this pattern and recipe works is pretty simple. The navigation pane control seen in Outlook is nothing more than TabControl with tabs stacked vertically, and that's the whole truth. We have added simple TabControl to our artboard and decided to change its control template. Once we were there, everything became pretty simple and straightforward. First step was to change TabPanel to StackPanel. Literally, we just changed one thing in the whole of XAML code and our tabs have stacked vertically one above other, which is the basic characteristic of StackPanel as a control. After that everything else was pretty much just cosmetics treatment. We've changed the tab item's height to 32 and we have made some changes to the Margin property in order to align and stack each and every tab item nicely. Again, I find it necessary to repeat that this is not a replacement for third-party navigation pane controls that are offering better and richer functionalities.
There's more... In this section, I will show you how to add more functionalities and even further customize your navigation pane.
Hosting content into specific tabs Remember that we have changed the control template of our TabControl but that the functionality has been preserved completely. As a consequence, the process of hosting and adding different content to tabs is the same as it is for regular tabs. 1. Let's continue from the last step in our recipe. If you expand any TabItem under the Objects and Timeline pane, you will notice that it is comprised of two major parts—Header and Grid. Click on Grid to make it active. 2. Now you can add any control from Asset Library or any other object like you would on any other grid-like control. Try experimenting by adding different controls. In the code sample that you can download from this book's website, I've added a simple TreeView control under the Mail tab.
20
Chapter 1
How to align header text to left Again, I will take it from the last step. So, our next challenge is to left-align labels such as Mail, Calendar, and others. To do this, we will need to edit a control template for the TabItem control. 1. Right-click on any tab item, let's say the first one with the Mail label. From the drop-down menu, click on Edit Control Parts (Template) | Edit a Copy..., and the Create Style Resource dialog will appear. Accept the suggested Name ( Key) and under the Define in section, select Resource dictionary. You'll remember that we defined our resource dictionary earlier as a single location where we will keep all our templates and styles. When ready, click on OK. 2. Now we are able to edit the template for our tab item. If you take a look at the Objects and Timeline pane, you will see the visual tree for our TabItemStyle1. Expand all nodes until you can see an object called Content (which is of ContentPresenter type). Click on it and go to the Properties pane. Locate the Layout section and you will see the HorizontalAlignment and VerticalAlignment properties. They are surrounded with a yellow border, and from them, you can see a little, yellow square, which indicates that these values have been bounded to the control template. 3. We want to set our own bindings. Click on the little square and from the drop-down menu click on Reset. Do this for both the HorizontalAlignment and VerticalAlignment properties.
21
Layouts and General Content Organization 4. Now, set Left as the value for HorizontalAlignment and Center for the VerticalAlignment property.
5. If you now go and hit F5, you will notice that the Mail label has been left-aligned, but that is not the case for the rest of the labels. The reason for this is the fact that in previous steps we have edited a copy of the control template and applied it to only the first tab item. 6. In order to get all labels left-aligned, go to your Window1.xaml file and under the Objects and Timeline pane, right-click on the next tab item. From the drop-down menu, select Edit Control Parts (Template) | Apply Resource | TabItemStyle1.
22
Chapter 1
7. Repeat the same procedure for the rest of the tab item controls and then hit F5 to test your application. Now all the labels are left-aligned.
8. Note that you can also add other controls in our TabItem style, for example, images. To do that, refer to the Tabs recipe in this book and follow the instructions given there for adding icons to tabs.
When to use navigation pane? As its name implies, the navigation pane is a control or pattern (if you like) that is focused on navigation. But what type of navigation? Is it the same as journal navigation? First and foremost, a pattern or control (if you prefer calling it that) is never used alone. It is (or should I say, it must be) used as part of a wider navigation concept. While a regular tab control with specific tabs is useful for property pages, dialogs, and different types of content organization, the navigation pane is great for application-specific navigation. In the real world, it means the following—you will position the navigation pane on the left-hand side of your application. When you click on specific buttons (tabs that is), they will expose content in their upper "container" part. In our recipe, that was the TreeView control added on the Mail tab. The most relevant and interesting things happen when users click on different items within the container part of a navigation pane. Then, application-wise navigation occurs. If you have challenges picturing this, go to Outlook and simply try clicking on Mail, and after that on the Inbox, Outbox, or Sent Items folders. You will notice that the right-hand part of your application changes. Virtually the same pattern is available in Microsoft Dynamics products such as NAV or AX, and many others as well. 23
Layouts and General Content Organization I've mentioned earlier that most guidelines and suggestions that I've outlined for tabs hold true for the navigation pane as well. However, I will reiterate some of them and also point out some differences right here: ff
Tabs (or buttons) such as Mail, Calendar, and so on must be linear in their structure, which means that there is no hierarchy in their organization—Mail is not a parent of Calendar and so on. Simply put, each and every tab or button must be mutually independent. But you are free to host hierarchy-based controls such as a "tree view" within your navigation pane.
ff
The navigation pane is for navigation. It's not a regular tab control used for organizing your content, controls, and properties. It's not a wizard too: don't ever use it as a control that should guide users through wizard-like processes.
ff
The first tab or button should be the one that is most likely to be most used and it should be selected by default. Again, using Outlook as a sample, the first tab is Mail—the one that is being used the most.
ff
Feel free to use icons. That was not something that I've been encouraging in the case of tabs, but here, you have enough space and you don't have to be afraid that you will make too much of a visual clutter. Sure, that holds true only if you use nice, clear, recognizable, and understandable icons.
ff
Don't use any kind of terminating or similar type of button within the container part of a navigation pane; no OK, Cancel, or Apply buttons here. It's called the "navigation pane" and it should do just that—help your users to navigate to or expose different parts of your application and help them get their jobs done quickly.
ff
Have I mentioned that in your real–life applications, you should use full-blown, third-party navigation pane controls and not this? We've created a really basic one here? This was a nice learning example and all of the suggestions stated here are applicable to real-world commercial navigation pane controls. And yes, I'm not really able to give you any suggestions on which control you should use, but there are numerous vendors offering them and I'm sure you will find them easily on the Internet.
See also ff
24
Tabs
Chapter 1
Window management and positioning Often overlooked or even completely ignored, window management presents the basic of any window–based desktop application. Though this recipe will be focused on WPF and desktop applications, today, window management plays an important role in web environments as well where different types of modal, dialog, and message box windows are appearing. As a consequence, most ideas and general guidelines presented here might be quite useful for web solutions as well. This recipe will cover several basic ideas and approaches regarding window placement, their positions, and size. As there are several concepts being described here, I have, when it seemed appropriate to do so, created smaller sub-recipes that are building on previous ones. WPF provides a fairly rich window management model but it is upon developers and designers to come up with the right usage and interactions involving windows. This recipe aims to help you with that challenge.
Getting ready Before we proceed any further, it is a good idea to define several concepts that we will be using and relying on during this recipe. You can think of this as a small dictionary and it is compatible with Microsoft UX guidelines for Windows Vista and Windows 7 operating systems. ff
Top-level or Primary window: It has no owner window, meaning that this is the one that is displayed on the taskbar and in most cases, can be considered to be the main application window.
ff
Owned or Secondary window: It has an owner window and as a general rule, it is not displayed on the taskbar.
ff
User–initiated window: It is always being displayed as a direct result of a user's actions. Action can be clicking on some buttons, commands, menu items, and so on. Also, there are program-initiated windows—ones that are initiated by an application itself without user's action—and system-initiated windows—ones that are initiated by the underlying operating system itself.
ff
Contextual window: It is type of a user-initiated window but with a very strong relationship to the UI object, from which it was invoked and launched. Context is extremely important here and positioning often plays a very important role (it will be covered in this recipe).
So, let's start. We are going to explore window management and that's why I will be using WPF. Start your Expression Blend 4 and then select New project... From the dialog that appears selectWPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK. 25
Layouts and General Content Organization
Title bar controls and window borders - How to do it... After your new WPF project has been created, you should notice under the Objects and Timeline pane that the Window and LayoutRoot grid controls are visible. 1. Before doing anything, hit F5 and your application will start. Your window will look like this:
You will see the icon, title, minimize, maximize, and close buttons. If you click on the icon, the system menu will appear. Positioning the mouse cursor on the window borders will allow you to resize the window. 2. Click on Window | Properties and locate the Common Properties section. Changing the icon: By changing the Icon property, you can change the look of the window icon. You can use a number of picture formats—ICO, PNG, BMP, JPG, TIFF, and GIF. Feel free to choose any picture that is available to you for testing purposes. The selected picture will be automatically added to your project. Setting the ResizeMode: WPF supports several resize modes and you can select them from the ResizeMode drop-down list. You can pick anything between NoResize, CanMinimize, CanResize (which is the default choice), and CanResizeWithGrip. Select CanMinimize. 3. The ShowInTaskbar property enables you to choose whether your window will appear on the Windows taskbar. As in this case our window is the primary window, we will want it to appear on the taskbar so leave the ShowInTaskbar property checked. 4. By setting the Title property, you can set your window title. Set the Title property to Our Main Window.
26
Chapter 1
5. Now locate the Appearance section and WindowStyle property. From the dropdown list, you can select one of the following options: None, SingleBorderWindow, ThreeDBorderWindow, and ToolWindow. Select SingleBorderWindow, which is the default choice. 6. Hit F5 now and your window will appear. It should resemble the following screenshot:
You can see that the icon, title, and control buttons have been affected. We decided to set the ResizeMode property to CanMinimize and users now can minimize the window, but there is no ability to change its size (positioning the mouse cursor over the borders does not enable us to resize it) or maximize it (the Maximize button is disabled). And as you have enabled the ability to display window in the taskbar, you can easily locate it there (like it is the case with most other Windows applications).
Window sizes and states - How to do it... In this recipe we will deal with window sizes and different states. 1. With your window selected (under Objects and Timeline pane), go to Properties and locate the Layout section and Height and Width properties. 2. Set the Width to 250 and Height to 480. Values are in pixels and they will define the size of your window during the runtime. 3. Now, click on the little arrow pointing downwards (Show advanced properties) and some more properties under the Layout section will be exposed. Locate MinWidth, MinHeight, MaxWidth, and MaxHeight. You can enter your values here and limit the window's maximum and minimum values for both height and width. By default, all minimum values are set to 0, and all maximum values are set to infinity. For the test, set MinWidth and MinHeight both to 200.
27
Layouts and General Content Organization 4. Now go to the Common Properties section and set the ResizeMode to CanResizeWithGrip. We want to test the MinWidth and MinHeight effects but in order to do that we have to set ResizeMode to either CanResize or CanResizeWithGrip. 5. Hit F5 now to test your application. You will notice the resize grip in the lower-right corner. Try sizing your window; you will notice that you cannot resize it to be smaller than 200 by 200 pixels.
6. Close the window and return to Blend. 7. Under Common Properties, locate the WindowState property. Click on the dropdown list and you will see following choices: Normal, Minimized, and Maximized. Select Maximized and hit F5 to start your application. 8. Your application will now start Maximized. If you click on Restore Down, it will be restored to the dimensions you have previously set for its Height and Width properties.
Window positioning - How to do it... Let's investigate the window positioning options now. As I am going to continue this recipe from the previous one, I will just go to the WindowState property and set it back to Normal before I do anything else. 1. Okay, now we are ready to continue. With your window selected, go to the Layout section and locate the Left and Top properties. Set Left to 100 and Top to 150. Now when you press F5, your application will start and your window will be positioned 100 pixels from the left and 150 pixels from the top.
28
Chapter 1
2. Close your application and return to Blend. Now under Common Properties, locate WindowStartupLocation. The drop-down list offers you several choices—Manual, CenterScreen, and CenterOwner. Select CenterScreen and hit F5.
29
Layouts and General Content Organization 3. In this case, your application will be automatically centered on your screen and the Left and Top properties that you have set before will be just ignored giving an advantage to the CenterScreen choice set for the WindowStartupLocation property.
Title bar controls and window borders- How it works... Typical title bar controls are icon, title, and minimize, maximize, and close buttons. Expression Blend allows you to set and manipulate all of them by changing the number of properties described in this recipe. While Icon and Title and really simple and understandable, let me invest some time and explain the different ResizeMode and WindowStyle properties.
ResizeMode ResizeMode is a property that is used to describe window behaviors and abilities when resizing is in question. You can control how and if, at all, a user can resize your window. Your choice is reflected in different combinations of Minimize, Maximize, and Close buttons as well as on the ability to resize window by clicking and dragging its borders. ResizeMode can be set to one of the following values: NoResize, CanMinimize, CanResize, and CanResizeWithGrip. Let me describe them briefly. ff
NoResize will render your window as non-resizable and only a Close button will be presented in the title bar, allowing users to only close the current window. Positioning the mouse cursor over borders will not allow for any resizing.
ff
CanMinimize is the choice that we have taken in our recipe. With this choice, a window can be closed, minimized, and then restored after previous operations. Though both the Minimize and Maximize buttons are shown, the Maximize button is disabled so the user can click only on the Minimize or Close buttons to terminate the window. There is no option to resize the window.
ff
CanResize is the default choice. All buttons (Minimize, Maximize, and Close) are present and enabled. Users are able to resize a window by positioning the mouse cursor over its borders—it is the most flexible option available.
ff
CanResizeWithGrip allows for the same interaction as CanResize with the addition of the resize grip that appears in the bottom-right corner of the window.
WindowStyle WindowStyle is a property in charge of the window's border appearance. There are four different possible styles at your disposal: None, SingleBorderWindow, ThreeDBorderWindow, and ToolWindow. 30
Chapter 1
Let's describe them in more detail: ff
None, as its name suggests, shows no title bar and border. All you can see is a simple client area.
ff
SingleBorderWindow is the default choice: it shows a window with its standard controls and has a simple, single border.
ff
ThreeDBorderWindow is same as SingleBorderWindow but with a pseudo 3D border and it is much heavier in its appearance, as you can see.
31
Layouts and General Content Organization ff
ToolWindow is a specific window type—a thinner border and a title bar with only a Close button available. However, it is resizable. It is often used as a secondary window for applications with a number of tools and options exposed in them (such as palettes and tools in Paint.NET).
Window sizes and states - How it works... Blend allows for a really great number of options related to window sizes and their management. The easiest and simplest way to set up your window's size is to set its Height and Width properties. However, you can use even more advanced properties such as MinWidth, MinHeight, MaxWidth, and MaxHeight. You can change those properties and limit the window's maximum and minimum values for both height and width. By default, all minimum values are set to 0, and all max values are set to infinity.
WindowState By setting the WindowState property, you can control the appearance of the window in one of the three possible states: normal, minimized, and maximized. ff
Normal state is the default state. In this state a window can be moved and resized, if it is resizable.
ff
Minimized state means that the window is collapsed to its taskbar button (in the default case, when ShowInTaskbar is set to True). If it is set to False, the window will collapse to its minimum possible size and place itself in the bottom-left corner of the desktop. It cannot be resized by using a resize grip or by dragging the border although it can be dragged around your desktop.
ff
Maximized state means that the window will be expanded to the maximum size it can take. It cannot be resized by using a resize grip or by dragging the border.
32
Chapter 1
Window positioning - How it works... There are two main ways to go about window positioning. The first one includes setting the Left and Top property, which enables you to precisely position your window on the screen, while the other approach requires setting the WindowStartupLocation property.
WindowStartupLocation The WindowStartupLocation property handles the initial location of your window. Every window's position can be described with the Left and Top property relative to desktop. You can also use one of the available options for this property: Manual (default), CenterScreen, and CenterOwner. ff
Manual startup location means that the window will be displayed based on Left and Top property values. In case they have been omitted, the underlying operating system will position the window on a specific location.
ff
CenterScreen will position the window exactly at the center of the screen on which it was opened. It will ignore Left and Top properties in case they have been set previously.
ff
CenterOwner works in a manner similar to CenterScreen but instead of positioning the window on the center of the screen, it will consider the center of the window that opened it as its startup location.
There's more... This section will show you some more ideas and approaches that you should consider and take into account while designing and using windows as objects in your solutions.
What is the minimum screen resolution you should be targeting? This is one of the most challenging questions presented in this book, though it seems to be very simple. Today, on the market, you can find a huge variety of different monitors and supported resolutions—from small netbooks to huge, widescreen monitors. Obviously, there is not a single "works for all" resolution. However, when you are designing your application, you must answer this question. At the time of writing, the minimum supported resolution for Windows OS is 800×600 pixels, though I can't really remember when was the last time I saw some desktop or notebook computer running on this resolution (netbooks might be an exception, for sure). Taking all this into account, I would strongly suggest that all your fixed size windows do not exceed the 800×600 dimension and the rest of the windows, ones that can be resized, should be optimized for 1024×768 resolution. It is your responsibility to invest time and explore how resizable windows and their content (UI controls) will behave in 800×600 resolution. 33
Layouts and General Content Organization Good designers will try to accommodate their application's design and layout for different resolutions so that in case of a higher resolution, your users can benefit from a bigger workspace. As always, it is a question of the right balance and compromise between possibilities, wishes, and limitations. If you are one of the rare guys around who knows that your application will be used on exclusively higher resolutions, then you have a nice challenge of creating an application that can take the full advantage of additional screen space.
General window usage guidelines As I've mentioned in previous paragraphs, all your fixed size windows should not exceed the 800×600 dimension and the rest of the windows, ones than can be resized, should be optimized for 1024×768 resolution. If your application has some critical parts and it is supposed to be used in a safe mode environment, you might need to lower the bar and design for 640×480 resolution, but honestly, such cases are really rare, and practically non-existent in typical consumer applications. When you are testing your windows, use the following table: DPI / Percentage
Resolution
96dpi – 100%
800 × 600
120dpi – 125%
1024 × 768
144dpi – 150%
1200 × 900
Performs well?
Under the Performs well? column, insert Yes or No based on the following criteria: ff
Are there any layout problems?
ff
Do you notice control clipping, text readability problems, or anything related?
ff
How do icons and bitmaps perform? Are they stretched? What about alignments?
ff
Can users access each and every command in all tested cases?
It is better to use larger initial window sizes and use the space effectively (your users will appreciate that). It's a much better solution than trying to fit everything into a small space. Don't go over 66 characters for text elements. (I've talked about that under Fixed versus Liquid layouts recipe of this chapter.) Windows User Experience Interaction Guidelines suggest that "centering" the window means biasing vertical placement slightly towards the top of the monitor, and not placing the window exactly in the middle of the screen. The reason for this is that our eyes are naturally more biased towards the top of the screen. However, that difference is quite small—you can go for 45% from the top of the monitor or owner window and 55% from the bottom.
34
Chapter 1
If the window that you are launching is contextual (remember, I've explained this term at the very beginning of this recipe), then you can go and display it near the object (button, let's say) that it was launched from. Take into account that you should place it out of the way so that the source object is not obscured; if possible, position it offset down and to the right. If your window is being launched from the notification area or system tray, you should display it close to that area too. If your window can be described as a process dialog (one that contains a progress bar—for example, file copy dialog), then you should place it in the lower-right corner of the active monitor, but not as close to the notification area as was the case with the windows launched from that area. If your window is an owned (secondary) window, then you should initially display it centered on the top of the owner window (you can use the WindowStartupLocation property and set it to CenterOwner, or you can use the 55% : 45% rule for centering the window (as described in an earlier guideline).
See also ff
Journal navigation
ff
Fluid versus fixed layouts
Wizards If implemented correctly, wizards can really do some magic for your users and make them happier and satisfied. This recipe goes after desktop-based wizards. I will show you how to implement them using the WPF and provide you with some Microsoft Aero Wizard guidelines. As was the case with the navigation pane pattern, a large number of different vendors are able to provide you with pre-built, fully capable desktop-based wizard frameworks implementing a number of rich functionalities. I will show you how to build a simple wizard but you are encouraged to explore third-party options. However, the guidelines and suggestions I will be giving here are applicable to those third-party products, so do yourself and your users a favor and try to take the most out of these suggestions.
Getting ready As I've already mentioned, we are going to build a desktop-based wizard in this recipe, and that's why I will be using WPF. Start your Expression Blend 4 and then select New project. From the dialog that appears select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. 35
Layouts and General Content Organization
How to do it... There are several page types that can be used in wizards. They are: ff
Getting started page (optional)
ff
Choice page
ff
Commit page
ff
Progress page (optional)
ff
Follow-up page (optional)
Before you start building and implementing your wizard system, you should have a clear understanding of the task flow and user's actions. In this recipe, I will just mimic some typical wizard behavior but be sure to read the How to use and implement wizards section of this chapter. OK, let's start with our building process—in this recipe, I will build a typical choice page. After your new WPF project has been created you should notice that under the Objects and Timeline pane, Window and LayoutRoot grid controls are visible. 1. Click on the window and then under the Properties pane, set its Height to 429 and Width to 549 pixels. Set its Title to Add Printer. Also under the Common Properties section, locate the ResizeMode property and set it to NoResize. 2. From the Asset Library, draw a Border control on top of LayoutRoot. Click on Border control and set the following under the Properties pane:
Set the Width to Auto, Height to 40
Set all margin values to 0
Set HorizontalAlignment to Stretch
Set VerticalAlignment to Bottom
3. Under the Appearance section, set the BorderThickness value for Top to be 1. 4. Under the Brushes section set the following colors:
For Background: Solid color brush—RGB (240,240,240) or HEX (#FFF0F0F0) For BorderBrush: Solid color brush—RGB (223,223,223) or HEX (#FFDFDFDF)
5. If you now hit F5 and start your application, you will notice that Border control is docked to bottom, looks gray with a bit darker top border. This is the area that we will refer to as to the command area.
36
Chapter 1
6. In the command area, we put at least one Commit button to commit to the task or proceed to the next step. We will add two buttons now—Next and Cancel. But as Border control can have only one child control, we need to add a Grid control and then draw our buttons on top of that Grid control. 7. With the Border control selected, from toolbox or Asset Library draw a grid control on top of Border controls itself. Under the Properties pane, set the grid's height and width to Auto, and all margin values to 0. That will stretch the grid and make it completely fill in the available space within Border control. 8. As grid is an extremely versatile and flexible control, we can now add our buttons on it. Select the grid and draw two buttons on it. 9. Call the first button btnNext and second one btnCancel. You can change their names by selecting them and then under the Properties pane (at the very top), you will find the Name property. 10. Select btnCancel, find the Content property, and set it to Cancel. Set Width to 65 and Height to 23. Choose Right as the HorizontalAlignment and Top for VerticalAlignment. For margin values, use 0 for Left and Bottom, 10 for Right, and 8 for Top; this should position our btnCancel nicely. 11. Now, let's change some properties for btnNext. Set the Content property to Next. Also, set the Width to 65 and Height to 23. Choose Right as HorizontalAlignment, and Top for VerticalAlignment. For margin values, use 0 for Left and Bottom, 85 for Right, and 8 for Top. And under the Common Properties section, locate the IsEnabled property and uncheck it. 12. Press F5 now and your wizard should look close to the one in the following screenshot:
37
Layouts and General Content Organization 13. So far so good. It's good to point out at this stage that you will have to use code to manipulate when the Next and other buttons are enabled, which will depend on the current progress and the context of your wizard. 14. Now we need to add the main instructions. It's basically a text label that summarizes what to do in the current wizard page. We can use Label as a control for this. So, draw a label (you can get it from Asset Library or toolbox) on top of the LayoutRoot and set the following properties:
Set Name to lblMainInstruction
Set Foreground color to RGB (0, 51,153) or HEX (#00003399)
Set both Width and Height to Auto
Set HorizontalAlignment to Left, and VerticalAlignment to Top
For margin values, set Left to 32 and Top to 14
Finally, set Choose a local or network printer for the Content property
15. These settings will always be the same for the main instructions for each and every wizard step. Only exception is the Content property, which must change appropriately. 16. As you remember, the page that we are currently working on is called "choice page". We have a main instruction, a command area, and now we will design the content area that hosts other controls and objects. 17. We will use regular buttons for this part although for the wizard pattern you should use command links. I will be explaining how to design and implement action or command links in Chapter 2, so be sure to go through that recipe and use controls and designs defined there instead of the buttons that I am going to use here for the sake of the brevity. 18. We will use two buttons that will provide users with choices. 19. Draw two buttons; name the first button btnLocalPrinter and the second one btnNetworkPrinter. 20. Let's set the following properties for btnLocalPrinter:
Under Brushes section set Background to No brush
Set Height to 58
Set HorizontalAlignment to Stretch and VerticalAlignment to Top
For margin values, set 50 for Left, 10 for Right, and 55 for Top
38
Set HorizontalContentAlignment to Left and VerticalContentAlignment to Top (You might need to click on Show advanced properties to display these properties.)
Under Padding, set Left to 20, Right and Bottom to 1, and Top to 6.
Set Content to Add a local printer.
Chapter 1
21. Now set the following properties for btnNetworkPrinter:
Under the Brushes section set Background to No brush
Set Height to 58
Set HorizontalAlignment to Stretch and VerticalAlignment to Top
For margin values, set 50 for Left, 10 for Right, and 145 for Top
Set HorizontalContentAlignment to Left and VerticalContentAlignment to Top (You might need to click on Show advanced properties to display these properties.)
Under Padding, set Left to 20, Right and Bottom to 1, and Top to 6.
Set Content to Add a network, wireless or Bluetooth printer
This basically sets the stage for your further improvements and customizations. The next steps are defining other page types and adding interaction logic between them. I will describe those page types and typical considerations that you need to take into account and address when designing and implementing your wizards.
How it works... It is of utmost importance for you to have a clear understanding of your wizards' purpose and flow. Don't go and start designing and implementing wizards before you have that. You need to come up with a logical flow, specific page designs, and then start designing. However, the page that you will be designing (in almost 100% of cases) will be a simple choice page. In the last recipe, I've outlined the basic idea of how to design a page and now we will dig a bit into some technical details. First of all, we have set ResizeMode to NoResize in order to keep our windows' dimension fixed (429 by 549 pixels, in our example). As a consequence, we get only a Close button on our window. Guidelines do allow implementation of resizable windows for wizards but I am generally opposed to that approach and I will explain the reason for this under the There's more... section. Okay, in the next step, we have used Border control for designing the command area of our choice page. As border, as a control, can have only a single child element, we have added grid as a child element of Border and then hosted Next and Cancel buttons within grid control (which can accept as many child elements as you need). You must pay special attention when it comes to handling Next, Cancel, Apply, and other buttons or commands that will appear in this area; this includes taking care if they are enabled, disabled, visible at all times, and so on. I am outlining those guidelines later on, so be sure to check them out.
39
Layouts and General Content Organization After we have designed the command area, we are ready for setting up the main instruction— the text label that is used for summarization of what to do in the current wizard window. It is really important to make it as understandable as possible so that users can understand what is being done in this specific window just by reading the main instruction. Next step was designing the content area—the main area of your wizard page where you usually place commands and where the most attention of your users will be focused on. We have added two "command links". (I am putting them under quotes for a reason: they are not real action or command links, what I have done basically is just changed some of the properties of regular buttons. But you can find how to design and implement real action or command links under Chapter 2, Actions and Commands.)
There's more... As you've learned so far, wizards can be fairly complex and incorporate numerous page types given wizard's purpose. In this section, you will gain much more insights about those types and when and how to use and implement them. Again, this is WPF recipe but the general ideas, user experience considerations and design itself can be easily applied to Silverlight itself.
Brief overview of different wizard page types In this recipe, I've guided you through the process of designing the very simple, even incomplete, choice page as a part of the wizard. According to the general UI guidelines, all wizard pages have a title bar, main instruction label(s), a content area, and a command area. In the previous recipe, we have designed all parts of our choice page except for the title bar. The fact is that the title bar for the so-called "Aero Wizards" looks pretty different from the one we have defined—it comes with an extended glass surface with the name of the wizard, the Back button in the upper-left corner, and a Close button with optional Minimize or Maximize buttons.
In the last chapter of this book, I am explaining how to extend the glass surface into your WPF windows, so you can refer to that recipe and use it for creating more realistic Aero Wizards even without third-party controls (if that is something you'd like to do). Anyway, let's go through the typical wizard page types.
40
Chapter 1
There are several typical wizard page types: ff
Getting started page (optional)
ff
Choice page
ff
Commit page
ff
Progress page and (optional)
ff
Follow-up page (optional)
Getting started page It is optional and its purpose is to outline the prerequisites or to explain the purpose of the wizard. But the general suggestion is not to use this page if all of the necessary information can be shown on the first choice page.
41
Layouts and General Content Organization Choice page(s) Wizards usually have more than one choice page; they are used with the purpose of gathering information from users in order to complete a specific task. A general suggestion is to use wizards if you know that users will be presented with more than two choice pages. If, however, you are dealing with one or two choice pages, you should consider using the regular dialogs and not the wizard because it is a pretty heavy UI pattern.
Commit page This type of page looks quite similar to the regular choice page but there is one significant difference: after a user commits an action, there is no going back; in other words, action cannot be undone. That also means that the commit page does not have a Next button; it has buttons that clearly state commands such as Connect or so. There is no common agreement as to whether there should be only one or more commit pages in a single wizard. However, personally I am a strong supporter of the single commit page idea.
42
Chapter 1
Progress page If during the wizard there is going to be an operation that will take four or more seconds, you should use the "progress page" type. It is optional, in the sense that if your operations will be shorter than four seconds, you are fine to drop the progress page. They are, in most cases, called after the Commit page and with a progress bar animation (or some other operation's progress indicator such as custom animation); they are good indicators of the operation's progress for the end users.
43
Layouts and General Content Organization When an operation is done, the wizard should advance automatically to the next wizard page.
Follow-up page This type of page is optional and is being used to provide users with final results or outcomes. I am not a big fan of "Thank you" pages. Stick to the task and get to it; your users will appreciate that much more than Thank you for installing this device, especially if it has taken them longer and you are just prolonging that with a useless "Thank you" page.
44
Chapter 1
To design resizable wizards or not Although Microsoft says that usage of resizable wizards is fine under Aero Wizard specifications and guidelines, I would advise you to be careful when you decide to go for resizable wizards. Let me make it clear that I am not completely against it but I would suggest and play safe and use ResizeMode = NoResize. I guess that my strongest argument for this would be having buttons in the command area always positioned in the same location. Imagine the scenario where you can go through your wizard just by clicking on Next several times. It is much faster if the Next button is in that case positioned at the same location. Of course, in this case, I am pointing out the problem where you are changing your wizard's dimension on a page-by-page basis. However, having wizards resizable so that they can leverage extra space available might be good idea. Again, I'd say play it safe; optimize them for minimum resolution supported under Windows Vista or Windows 7 (800 x 600), and don't go for some wild resizing behaviors.
When to use wizards I bet you all remember older wizards; you can find them if you are still using Windows XP or with some third-party applications that are just breaking all known UI or UX guidelines for wizard applications under Windows Vista or Windows 7. Older wizards were based on a standard called Wizard97 and that "97" is not there for no reason, so we should think about the year we are currently in. Anyways, new wizard standards are in place and some of the changes include more flexible page layout and text formatting, and removal of the really unnecessary Welcome or Congratulations or Finish pages. (I bet those are not being missed by anyone.) Some other pillars are the prominent main instructions with the great idea of unifying the earlier heading and subheading. Also, implementation of command links is a nice way of enabling users to have immediate and generally more expressive choices, thus eliminating the usage of several UI controls such as radio buttons followed with a Next button. Navigation within wizards is more aligned with the one that is usually found on the Web and within Windows Explorer. In our recipe, we have not implemented that kind of navigation but you can read about it in the Journal navigation recipe of this chapter. You might have noticed that the Back button is not present in the command area, rather it is now located in its new standard location— upper-left corner. I've had several opportunities listening to people saying that in the beginning, this was a bit distracting to them but now they actually see the point; more focus is being given to commit choices.
45
Layouts and General Content Organization Guidelines ff Don't go for wizards like there is no tomorrow. Wizards are considered as heavy user interface elements and should be used sparingly. They are used for multi-step tasks, especially if they are not frequently performed. You might consider some other alternatives to wizards—dialogs, task panes, and others. ff
The Next button is used only when advancing to the next page but without commitment, which means that the Back button is always available and presented after the Next button. According to Microsoft's guidelines, advancing to the next wizard page is considered a commitment when its effect cannot be undone by clicking on Back or Cancel buttons. Sounds quite logical, doesn't it?
ff
Commit buttons are as specific as possible; for example, you should use captions such as Print or Connect instead of Finish or Done. Generic labels such as Next should not be used because they are suggesting the next step and not a commit command. However, there are two exceptions: Finish can be used when there is a collection of settings to be applied and if specific responses (Get, Save, and so on) are generic. The Commit button should always start with a verb, never a noun.
ff
Command links are here for choices, not commitments. They are unifying the collection of radio buttons and the Next button. So when you are using command links, hide or disable the Next button but leave the Cancel button. This was exactly the case in our recipe where we have used two command links.
ff
Wizard is a tricky term; never use "wizard" in wizard names. But it is fine to use "wizard" when referring to it as a specific UI element.
ff
User choices must be preserved. This means that when users make a specific selection, then clicks Next, and after that Back, previous selections should be preserved.
ff
Forget about "welcome", "get started", and similar types of pages. Make the first page fully functional whenever possible. There are some exceptions but resort to them sparingly. You can use "getting started" pages only in situations where there are some prerequisites that are necessary for successful completion of the wizard, when the purpose of the wizard may not be clearly understandable from the first choice page, and you don't have enough space on first choice page for additional explanation. In any of these exceptions, the main instruction text should be Before you begin: and never some version of welcome, let's get started, or anything like that.
ff
Forget about "Thank you" or "Congratulations" pages, too. Wizard's final results should be clear and apparent enough for the users that you can just close the wizard after the final Commit button. You can resort to "follow-up" pages if you think that there are some usual follow-up tasks that users are likely to do as a follow-up. However, in that case, avoid using familiar, simple, everyday tasks. Follow-up pages are necessary after progress pages to indicate task completion. But again, if the task is long running (I'd say longer than five minutes) and can be performed in the background, then just close the wizard on the "commit" page and resort to notifications (such as balloons) to give a final feedback to the end users.
46
Chapter 1 ff
Commit pages are used to make it clear when users are committing to the task. As a general rule, the commit page is the last page of choices and it does not contain the Next button. Rather, the Next button is relabeled in a way that is described in the guideline about commit buttons (mentioned above). Sometimes, if the wizard was used for a really risky task or there is a significant doubt that the users have understood their selections, you might want to use a summary page and outline all of the selections and choices of the users, so that they can review them and act upon them.
See also ff
Action or command links
ff
Journal navigation
Progressive disclosure—showing additional controls on demand In some cases, your user interface needs to host a large number of different controls and present them to the end user. Instead of showing all the available controls at the same moment, you can take an approach where you will progressively disclose more controls on user's demand. This can save you some valuable space and, at the same, increase a user's productivity. Now I will show you how to implement this UI pattern in a simple WPF application. As always, the same methods, ideas, and principles can be applied to your Silverlight application as well.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... After your new WPF project has been created you should notice that under Objects and Timeline pane, Window and LayoutRoot grid controls are visible. 1. Click on Window and under the Properties pane change the following things:
Under the Layout section, set Width to 350 and Height to 240
Under Common properties, set Title to Files Search Sample
We will create a simple file search application but without real functionality. 47
Layouts and General Content Organization 2. On the toolbox, click on Asset Library | Label. Draw a label on your application. With the Label control selected, under the Properties pane locate the Content property (it is under the Common properties section) and set its content to Enter file name:. You can set its height and width to Auto (under the Layout section). 3. Now add the TextBox control in the same way and position it under the previously added Enter file name: label. Go to the Text property under Common properties and set it to none. 4. Add the Button control, position it right next to the TextBox control, and set its Content property to Search. 5. Now you will go and add an Expander control. Select it from Asset Library, draw it, and position it below the TextBox control on your form. Set its height and width to Auto. 6. In the Objects and Timeline pane, click on the Expander control so that you can access the Grid control contained within it. Double-click on the Grid control to make it active. We will add our additional controls into this Grid control. Under the Layout section, set Height to 80. 7. Once again, go to Asset Library and select the CheckBox control. Draw it onto the grid surface (be sure to make it this way, CheckBox must be the child element of the Grid control contained within Expander control). Repeat the procedure and add one more CheckBox control and position it below the previous CheckBox control. 8. Select the first CheckBox control and change its Content property to Search archived files, and set the Content property of the second CheckBox control to Search files in Recycle Bin. 9. Ensure that the IsExpanded property of the Expander is set to false (unchecked) under the Common Properties section. We want to keep Expander collapsed. Also, change Expander Header content to Show advanced options. 10. Hit F5. When your application starts, click on Show advanced options and your application should look like the following screenshot:
48
Chapter 1
How it works... Our sample application outlines the basic idea of progressive disclosure. We have created a simple file search interface where a user enters the filename and clicks on Search to search for files. That is the basic use case and it is available right after the user starts the application. By clicking on Show advanced options, users are presented with two more options that can refine their search results. I have assumed that majority of users will want to use basic search options and just smaller number of them would be interested in searching for archived files or files in the Recycle Bin. In this example, a progressive disclosure pattern has been implemented using the Expander control. The Expander control consists of two major parts—header and grid. The Header part contains a chevron and label (we changed its content to Show advanced options). The Grid part can be considered as a container in which you should put all of the controls that you want to disclose progressively to the end user. In this example, we have added two CheckBox controls with options to refine our search—they are not visible right away and therefore, they are not adding any visual clutter and distraction to users. If users do not want to use them, they can easily collapse the Expander control and hide those options.
There's more... The first part of this recipe has introduced to the basic idea of progressive disclosure. What follows are more details and design and user experience considerations you should take into account when designing and implementing this pattern in your application.
Changing the expander control's header label For the users to have a better understanding of the actions being performed and the changes being made when they click on chevron, it is highly recommended to change label from Show advanced options before clicking on the chevron to Hide advanced options after the user has clicked. Same goes for the other way around. To achieve that, we need some code. As we have created our project as a WPF C# project, we will obviously write our code in C#. 1. Under the Objects and Timeline pane, click on the Expander control. We will now change its name so that we can access its properties through the code easily. 2. Under the Properties pane, type expOptions in the Name field.
49
Layouts and General Content Organization 3. We will want to execute different code when users collapse it and when it expands our Expander control. To do that, we will define event handlers for the Collapsed and Expanded events. 4. Click on the Events icon under the Properties pane and you will be presented with a number of events. Let's add our event handlers for Collapsed and Expanded events. To do that, you will just have to type in the name for those event handlers and once you press the Enter key, Visual Studio will start and allow you to add code logic. You can use expOptions_Collapsed and expOptions_Expanded as names for your events. 5. Add the following code: private void expOptions_Collapsed(object sender,RoutedEventArgs e) { this.expOptions.Header = "Show advanced options"; } private void expOptions_Expanded(object sender, RoutedEventArgs e) { this.expOptions.Header = "Hide advanced options"; }
Everything what we are doing here is changing the content within the header part of our expOptions control. 6. Press F5 now and try clicking on the chevron and note how the label will change its content, making it easy for users to understand what has happened and what will their next action cause.
When to use progressive disclosure Many developers tend to expose each and every command and feature that they have built into their solution. Some even go as far as to argue that by doing that they will actually show to the end user how powerful and feature-rich their application is. I'd be happy to say that this story was just my exaggeration but I have witnessed such situations too many times. So, we are facing a challenge on how to enable users to use our application and make it feature-rich, but at the same time not to make it too cluttered. Guess what—users will not judge your application's power by the number of buttons, icons, and other UI elements that you have exposed to them. They will judge it, among other things, by how easy it was for them to get to the most needed options really quickly. That will make them feel that they are in control and will result in significant productivity gains.
50
Chapter 1
So, what to do? The first step is to identify the commands and controls that your users will use in most cases. Make a list of all use cases and assign a value to each of those use cases describing how likely users are to use that very option. You must ensure that users should be able to perform about 70-80% of the use cases easily, without having to look for hidden options within your UI. Of course, that percentage can scale depending on certain specifics, but practice has shown that the aforementioned range works very well. Okay, now you have a list with controls and use cases that your users will use in 70–80% of cases, and the rest will be used much less often. This is a great input and you can use it from this point on to define the look and feel of your UI. Add those most commonly used controls on your windows or pages. Remember, these are the ones that will be used frequently by your users, so ensure that they are visible and easily accessible. Now, create a separate section and add the rest of the controls to that section. Hide it and make it hidden by default to your end users. But, be sure to allow users to get to those options in a single click. You might consider using buttons with captions such as More details... or even chevrons (>>) as a part of the button or other control that is being used to show those hidden controls. It is extremely important that users are able to hide and show sections with additional controls with a single click. If you show additional controls by clicking on Show advanced options, then be sure to enable users to get out from those advanced options by clicking on a button saying something like Hide advanced options. As I said earlier, controls that are being placed in this "hidden section" will be used rather infrequently, but you must ensure that your users will be able to access them and leave them easily. If you are using chevrons instead of buttons (and that is what I do personally because I feel that they are visually lighter than buttons, and besides that, buttons are usually associated with launching other windows or executing commands), you must take care of rearranging their "pointing direction" after a user clicks on them. They should always point in the direction of the action being performed, which means the following: if the chevron is pointing down, when the user clicks on it, additional commands should appear below that chevron and now the chevron should point up. That will always give a clear understanding to the user what will happen when they click on the chevron. I strongly suggest that you use labels that will reinforce users' understanding of the actions being performed.
51
Layouts and General Content Organization Look
Behavior when user clicks Section will expand, hidden options will be shown, and chevron will change its direction to up, and text will change to something like Hide advanced options Section will collapse hiding the previously exposed options and chevron will change its direction to down, and text will change to something like Show advanced options
See also ff
Responsive enabling
ff
Contextual fade-in/-out
ff
Progressive disclosure-showing additional controls on demand
Control docking with DockPanel Windows Presentation Foundation comes with DockPanel—a really versatile control allowing you to architect and create layout areas within which you can position and organize child elements. When building your user interface, often you will want to ensure that specific controls and parts of your UI are always docked on the top, left, bottom, or right side. For example, the command bar area is usually docked at the top and the status bar is usually docked at the very bottom of your application. A good practice is to use the DockPanel control as a root control and organize other panel and layout types of controls within it. Of course, you can always think about employing some different approaches and using controls such as Grid, but the DockPanel control brings you docking capability right out of the box. In this recipe, I will show you some basic principles that you should be aware of when thinking about using the DockPanel control.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
52
Chapter 1
Apart from WPF, DockPanel is available as a Silverlight control as well. In order to be able to use it, you need to have Silverlight Toolkit installed. The introductory part of this book contains all the information you need to know about how to obtain Silverlight Toolkits and use controls contained in it.
How to do it... Once your new WPF project has been created you should notice that under the Objects and Timeline pane, Window and LayoutRoot grid controls are visible. 1. Right-click on LayoutRoot and in the pop-up menu click on Change Layout Type | DockPanel. This is the fastest way for us to use DockPanel as our root control. Of course, another possibility is to click on Asset Library located on the toolbox and then select and draw DockPanel as control. 2. Click on LayoutRoot to select it and under the Properties tab, within the Layout section make sure that the LastChildFill property is set to false (unchecked). Now, let's go and add several rectangles on our LayoutRoot so that we can understand basic layout principles. 3. Select Rectangle from the toolbox and draw it onto your LayoutRoot. With the first rectangle selected, under the Properties panel, locate the Layout section and from the Dock drop-down list select Top. Set Width to Auto and Height to 55. 4. Now draw another rectangle. Instead of selecting and typing in values, we can set the dock position in a different way. Select Rectangle and drag it towards the top. You will notice a large four-way cursor showing you directions for possible docking locations of your object. Dock this second Rectangle at the bottom.
53
Layouts and General Content Organization 5. Set the Width property to Auto and Height to 40. 6. Repeat this procedure for two more rectangles, but align them to the left and right side respectively. Set Height to Auto for both of them. For the left docked rectangle set the width to 200, and for the right docked rectangle, set the width to 170. Set different fill colors for each rectangle so that they are easier to notice and recognize. 7. Press F5 and start your application. It should look similar to the one in the following screenshot:
Now let's go one step further and add the Grid control to the central part of our application. But now, we want our Grid control to completely fill in the available space on the form, so that we can utilize it later; for example, when we decide to extend our application. 8. From the toolbox, select and draw the Grid control on the LayoutRoot control. Under Properties and under Brushes, select any color for its Background property. The purpose of this color selection is only to make our Grid control a bit more distinctive. 9. Now select the LayoutRoot element (the easiest way to do this is to select it under the Objects and Timeline panel just by clicking on it) and under the Properties pane, locate a property called LastChildFill, and make sure it is checked.
54
Chapter 1
10. Select the newly added Grid control and set its Height and Width properties to Auto. 11. Press F5 and you should get a layout that looks close to the one in the following screenshot:
Try resizing the form and you will notice that all our rectangles are keeping their positions docked to defined sides, and the central part (Grid) is filling in all the available space. I will explain this kind of behavior in more detail in the following paragraph.
How it works... The first thing we did after starting a new project was change the layout type. The default layout type is grid, but we wanted to use DockPanel so that we could explore its behavior. DockPanel enables us to dock specific child elements. In our example, we have added several rectangles and set their Dock property. It was obvious that we could dock our objects in two different ways—by manually setting the Dock property within the Properties pane or by simply dragging child objects over a large four-way cursor. We have set specific heights and widths for child objects, but please take into account that in order to achieve that your docked control will scale appropriately, you need to set Auto for its Height or Width properties, depending on their docking direction. At the very beginning of our recipe, we have set the LastChildFill property to false (unchecked it). the idea behind the LastChildFill property is to enable the last child element added to DockPanel to fill the remaining space. We achieved exactly that when we added Grid control and set the LastChildFill to true (checked it). 55
Layouts and General Content Organization So just to summarize: DockPanel arranges its child elements so that they fill a particular edge of the panel. What happens if you set up multiple child elements to have the same docking direction? They will simply stack up against that edge in order.
There's more... Change the docking order of child elements Once you have added child elements to your DockPanel you might want to change their order. That procedure is fairly simple. 1. Make your DockPanel active; the easiest way to achieve that is by double-clicking on it or selecting it under Objects and Timeline. 2. Click the child element and simply drag-and-drop it on the desired position (you are not dragging-and-dropping child elements on the artboard). Now you are dealing with them within the Objects and Timeline pane. Note that by doing this you are not changing the docking orientation (I will explain how to do that in next chapter); you are changing only the z-order. It is also sometimes called stack order. Try experimenting with this and you will notice that the actual docking order is pretty important when it comes to the overall UI layout. The reason for that is that when elements fill up the panel (and that usually happens when we set their heights and widths to Auto), some parts might be cut off depending on the screen and child element size.
Change the orientation of a dock panel Sometimes you will face situations where you want to change the docking orientation for specific child elements after you have already set them. You can do that by following these instructions: 1. Make your DockPanel active: the easiest way to achieve that is by double-clicking it or selecting it under Objects and Timeline. 2. Click the child element and simply drag-and-drop it on the desired docking position on your artboard. Once you start dragging elements you will notice a large four-way cursor showing you docking directions. Now you only need to drag the element over the direction arrow you want. You will notice that the direction arrow that you select is highlighted indicating the docking direction.
56
Another way of changing the docking orientation is to select child element and under the Layout section in the Properties pane, select Top, Right, Bottom, or Left from the Dock drop-down list.
Chapter 1
Personal view I will say it bluntly—I am not a big fan of the DockPanel control. Although it is a great and simple-to-use control that enables you to create a basic layout for your UI, I will always prefer the Grid control as my control of choice when it comes to layouts. The Grid control is slightly more complicated, but it is more flexible as well. Anything you can do with DockPanel can be done with the Grid control, and then some. Of course, DockPanel gets its credit when we talk about simplicity, and really, if your basic UI structure is really simple and you need to get things done in a fast and simple manner, consider using the DockPanel instead of Grid. Use Grid and other controls within DockPanel, work on their docking positions, and you will probably be able to create the UI you were looking for. If that doesn't work, you can always rely on Grid—the most powerful of all WPF or Silverlight layout controls.
See also ff
Fluid versus fixed layouts
Journal navigation Journal navigation enables you to utilize "back and forward" metaphors usually seen in web browsers even for your desktop (WPF) applications. As humans, we are often found in positions where we are thinking in a linear way and we tend to associate web page navigation and other UI related concepts with that. As web browsers do support this kind of navigation by default, more challenging is to achieve this kind of behavior for desktop (WPF) applications. In this recipe, I will show you how to utilize this model and enable users to go back and forth in their navigation history within your WPF application.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK..
How to do it... When you create your new WPF project in Expression Blend, you are presented with the Window object. In order to implement journal navigation pattern, you need to use Page. For this example, we will add two pages and show how to navigate between them and retain the navigation history. 57
Layouts and General Content Organization 1. Click on the Project pane and then right-click on the name of your project. From the drop-down menu choose Add New Item.... 2. A dialog box will appear showing you your possible choices. Select Page. Leave the name as it is (Page1.xaml) and be sure to have the Include code file option checked. 3. Repeat the procedure and in the same way, add Page2.xaml to your project. Now your project tree should look like the one in the following screenshot:
4. Now right-click on Page1.xaml and from the drop-down menu, select Startup. This will make Page1.xaml a startup object—the first one to appear when you start your application. 5. If you now hit F5, you should be able to see your Page1.xaml completely blank, but notice the navigation chrome with back and forward navigation buttons (sometimes also called "travel buttons") added automagically. It is not functional at this moment, but very soon you will be able to use it.
6. Let's change some properties and make our pages look a bit more distinctive so that we can recognize them easily later. 7. We will start with Page1. Under the Objects and Timeline pane, select the Page object. On the Properties pane, locate Common Properties, find the Title and WindowTitle properties, and set them both to First page. 58
Chapter 1
8. Repeat the procedure for Page2, but now set the Title and WindowTitle properties to Second page. (I will explain the difference between Title and WindowTitle properties later on.) 9. Now, let's add a button on Page1. We will use that button for navigating from Page1 to Page2. To add a button, locate it on the toolbox or add it from Asset Library and draw it on your Page1. 10. On the top of the Properties pane set its Name property to btnNavigate. Also, find the Common Properties section and change the Content property to Navigate to other page. 11. Now, we need to add some code that will enable us to really navigate to the second page when a user clicks on this button. Basically, we will define an event handler for the Click event. 12. Under the Properties pane, locate the Events icon and click on it.
13. Under Click, type in btnNavigate_Clicked—the name of your event handler. Hit Enter and Visual Studio will enable you to type in the code needed. 14. Add the following code in the event handler: private void btnNavigate_Clicked(object sender, RoutedEventArgs e) { ((NavigationWindow)(Application.Current.MainWindow)).Navigate( new System.Uri("Page2.xaml", UriKind.RelativeOrAbsolute)); }
15. And add the following line at the very beginning of the code: using System.Windows.Navigation;
16. Note that Page2.xaml is the file name we are navigating to. Now hit F5 and when the application starts, click on Navigate to other page.
59
Layouts and General Content Organization 17. Note the changes in the navigation chrome. Explore it by clicking on the back and forward buttons or drop-down menu.
How it works... We have added two Page items to our project: Page1.xaml and Page2.xaml. The basic idea of this recipe was to show you how to navigate from Page1.xaml to Page2.xaml. By setting Page1.xaml as the startup page, we have ensured that it will be the first page to be shown when the application starts. We have added a button and called it btnNavigate and associated the Click event handler. There is only a single line of code that enables navigation between pages: ((NavigationWindow)(Application.Current.MainWindow)).Navigate( new System.Uri("Page2.xaml", UriKind.RelativeOrAbsolute));
However, first we need to add a simple using directive: using System.Windows.Navigation;
The great thing about implementation of the journal navigation pattern is that the navigation chrome is automatically being updated. When I say that I am thinking about the fact that the back and forward button and the drop-down menu are being updated based on the current navigation context. This pattern is often seen in applications such as web browsers, Windows Explorer in Windows Vista and Windows 7, or in Microsoft Dynamics NAV and AX line of products.
60
Chapter 1
There's more... Journal Navigation pattern is very useful. Sometimes, however, you will want to remove the navigation chrome, or you might be wondering what's the difference between Title and WindowTitle properties. The following section will explain you that and provide you with even more information.
Removing the navigation chrome At some point, you might consider removing the navigation chrome and replacing it with your own implementation of the same. Although I won't be going into details and explaining how to replace it with your own, I will show you how easy it is to remove the navigation chrome with just a single line of code. All you need to do is add this line of code: this.ShowsNavigationUI = false;
As an example, and for demonstration purposes only, I've added a new button and called it btnRemoveNavigation and attached a new Click event handler called btnRemoveNavigation_Clicked. So my complete code looks like this: private void btnRemoveNavigation_Clicked(object sender, RoutedEventArgs e) { this.ShowsNavigationUI = false; }
If you now go and hit F5 to start your project and then click on Remove navigation, the navigation chrome will disappear.
Though you can remove the navigation chrome and navigation functionality will stay intact (one that you have implemented by adding event handlers), your users will suffer immensely if you don't implement some sort of navigation UI (that is, if your application is based on this pattern). 61
Layouts and General Content Organization You must ensure that simple, easy-to-use, and noticeable navigation chromes exist at all times while your users are using an application based on this pattern.
Difference between Title and WindowTitle In Step 8 of this recipe, I've mentioned that there is a difference between Title and WindowTitle properties. So, what's the deal? Both Title and WindowTitle are Page properties located under the Properties pane, in the Common properties section. The Title property sets a title for a specific page. What you enter here will be displayed in the navigation chrome (including a drop-down menu). WindowTitle sets the title for a specific Window object. Basically, this means that whatever you enter for the WindowTitle property will be displayed at the top of the window—in the title bar.
When to use journal navigation As people tend to think linearly (probably based on their everyday experiences with time flow and similar concepts), we also appreciate the ability to navigate through our applications in the same way. Journal navigation is a good pattern that provides us with a mechanism that can be used to go back and forth in the navigation history of our application. We experience software in the same, more or less single thread, single timeline manner. For example, recall using the web browser of your choice—when you are navigating from one page to another, you have the impression that the main view is being changed. Implementation of journal navigation enables us to track and revert to those views or pages in a pretty simple and straightforward manner. Journal navigation is not only good (or should I say mandatory) for web browsers but it is also a good choice for a number of different needs. Wizards, desktop, or RIAs (Rich Interactive Applications) are just some of the typical, potentially good candidates for this pattern. Windows Explorer in Windows Vista and Windows 7 uses this same pattern. Microsoft Dynamics NAV and Microsoft Dynamics AX are also great examples; they are combining journal navigation with breadcrumb bars.
62
Chapter 1
So, the basic principle about when to use journal navigation as a pattern is a situation where you want to enable the no forward-only navigational experience, and instead, you are to utilize abilities to go back and forth, thus enhancing the experience of moving from one page to another. Good practice suggests that you concentrate on three main areas when dealing with the journal navigation implementation. Luckily, when you are using WPF Page and the recipe described here, they are (mostly) all being taken care of, but just for your reference, I will describe them. The first field is surfacing the navigation chrome (user interface). It has to be obvious to the end user that they are dealing with the navigation UI. I've explained how easy it is to remove the default navigation chrome, but you must use some sort of navigation UI. Good practice is also to enable users to get access to back and forward buttons via the keyboard and not just by clicking with the mouse. As you can say by your own intuition or from your personal experience, when interacting with different applications, having a consistent, clear, and easy-to-use navigation system is crucial. It certainly enables users to feel more in control and empowered when using your application. Second important thing is to have some sort of history so that users can easily see where they have been previously and navigate through their history. In our recipe, that list is easily available by clicking on an arrow pointing downwards, which exposes a drop-down menu with the list of visited pages. The third and probably most important thing to take care of is the context of your application. Do you want to enable users to navigate back and forth or do you require a one-way task flow? What happens if your users navigate back while some action is still in progress: will you cancel the action, continue the action, or do something else? How will you notify your users? Never, and I mean never, use the Back button as an undo operation! Use a specific, single, understandable command for an undo operation. I've seen too many applications trying to use the Back button as a replacement for the undo command, and bluntly said, they "suck". You don't want your application to be characterized as the one that "sucks", do you?
63
Layouts and General Content Organization
See also ff
Wizards
Tabs Tabs provide a simple way of presenting sets of controls or documents on separate, labeled pages. They are quite popular and most commonly associated with typical property windows. On the Web, they are also very popular as a means for content organization. As a very general guideline, tabs are used when you are dealing with too much information on one page (it doesn't matter if it is a web or desktop application), which basically creates confusion making the specific content difficult to find and focus on.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... In this example, we will add the Tab control as a part of our Silverlight 4 project: 1. After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. The Tab control is not a part of the "default" Silverlight controls, so in order to use it, we have to add a reference to it. After you installed the Silverlight 4 SDK, you have obtained a library that contains a number of controls, among them TabControl. 3. Under the Project tab, go to References | Add Reference.... 4. The Add Reference dialog box will appear. Navigate to a file called System. Windows.Controls.dll, which is usually located in a path similar to: C:\
Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client.
5. Select the file and click Open. 6. Now you will see System.Windows.Controls.dll under your References folder. 7. Now, go to Asset Library available on the toolbox. Be sure to check Show All. Now you should be able to locate TabControl.
64
Chapter 1
8. Click on TabControl and draw it on the artboard. 9. Take a look at the Objects and Timeline pane and expand the visual tree so that you can see all parts of the TabControl.
10. Let's add the third TabItem to our TabControl. Right-click on TabControl under the Objects and Timeline pane and from the drop-down menu, click on Add TabItem. Now you should see the third TabItem added to your TabControl.
65
Layouts and General Content Organization 11. Click on the first TabItem and under the Properties pane, locate the Header property (located under Miscellaneous section), and type in First tab. Do the same for the second and third TabItem typing Second Tab and Third Tab, respectively. Your tab control should look like the one in the following screenshot:
12. As you will have noticed under the visual tree, each TabItem is comprised of the Header part and Grid. The Grid part is basically the Grid control in which we can put any content we want. 13. Select First tab and add two buttons (add them from the toolbox or Asset Library). Change their content (Properties pane, Common Properties section, Content property) to Button 01 and Button 02. Be sure that you have selected the Grid element of the specific TabItem to ensure that the buttons will be added to exactly that TabItem. 14. Repeat the same procedure: adding one button to the Second tab and one to Third tab. Set their content to Button 03 and Button 04 respectively. 15. With this, you must have got a pretty clear understanding of how you can add controls to different TabItems and how to add TabItems as well. 16. Now hit F5 or go to Project | Test Solution. 17. Your default web browser will start and you will see your tab control. Try clicking on different tabs and notice that you can see only the content that you have added to a specific Grid under specific TabItem.
66
Chapter 1
How it works... As TabControl is not a "default" Silverlight 4 control; we had to add a reference to the System.Windows.Controls.dll file (that file is part of the Silverlight 4 SDK pack). After adding the reference, TabControl has been added to our Asset Library and is available for use from there like all other controls. Right after you have drawn TabControl on the artboard, you will notice two tab items (colloquially called just "tabs"). By right-clicking on TabControl and using the option Add TabItem you get the opportunity to add more tab items. It is a general suggestion that you don't add more than seven tabs. Take a look at the There's more... section where I will go deeper into general guidelines for using tab as a control. The next step was adding titles for specific tabs. As shown earlier, specific TabItem is comprised of Header and Grid parts. By clicking on TabItem and locating the Header property, you have got the possibility to change the title for a specific TabItem. We have used just provisional titles, First tab, Second Tab, and so on. The next step was adding the specific content to specific tabs. Technically speaking, that content is hosted within the Grid control. That, of course, means that all layout, formatting, and other Grid-related mechanisms and properties are applied to all controls hosted. Grid is, without doubt, the most powerful layout control available in WPF and Silverlight. By hitting F5 and starting your web browser you got the opportunity to explore tabs and associated buttons (controls). 67
Layouts and General Content Organization
There's more... In the first part, you've been introduced to the tab control and its main characteristics. Now, you'll learn how to further customize the control itself and also get the professional and insightful guidelines for using the tabs in your real life applications - no matter what are you using, WPF or Silverlight.
Changing tab orientation Tabs are most commonly oriented horizontally, but TabControl, which is used in our example, supports different orientations. I will assume that you are continuing from the previous TabControl example. 1. Select your TabControl under the Objects and Timeline pane. Under the Properties pane, locate the TabStripPlacement property under Miscellaneous. The drop-down list offers you the following options: Left, Top, Right, and Bottom. 2. Select Left. 3. You will notice that the tab orientation has been changed. Hit F5 and investigate a new look within your browser.
As a small digression, Last.fm, a popular music and radio community website, uses this kind of layout for its profile page's design and I find it to be highly usable and pleasing.
Adding icons in tabs In the When to use tabs? paragraph, I will give guidelines regarding the usage of icons in tabs, so be sure to understand when it is correct and acceptable to use icons in tabs. Again, I will take it from our initial example where we have added TabControl and three TabItem elements (tabs). Currently, there is no property like Icon for each TabItem, but we can add them manually by modifying the Header part of TabItem. 68
Chapter 1
1. Let's just modify the Header for the First tab and you can apply the same method for the rest of them. 2. The idea is to add Image control and TextBlock into Header and then to place an icon into Image control and set the content of TextProperty to First tab. We want Image and TextBlock controls to be stacked horizontally, so we will put them in the StackPanel container. 3. Double-click on Header under the first TabItem; this will make it active. Now from the toolbox or Asset Library add StackPanel. Set its Height and Width to Auto and Orientation to Horizontal. You can do this by going to the Properties pane and locating them under the Layout section. 4. Now select the newly added StackPanel and add Image control and TextBlock. The easiest way do to that is just by locating them under the toolbox or Asset Library and double-clicking on them. They will be automatically added to the selected container, StackPanel in our case. 5. Select Image control and under Properties locate the Common Properties section. Find the Source property and click on Choose an image button (ellipses). From the dialog box, select an image—the one that you want to add as an image. I suggest using the PNG image with dimensions of about 16x16 pixels. 6. Now select TextBlock and change its Text property, which is under the Common Properties section within the Properties pane. Set it to First tab. 7. If you now take a look at the XAML code of the selected TabItem, it should look similar to this:
<StackPanel Height="Auto" Width="Auto" Orientation="Horizontal">
8. Structure, as can be seen under the Objects and Timeline panel, looks like this:
69
Layouts and General Content Organization 9. Press F5 now and your TabControl should look like this:
When to use tabs I've already mentioned that tabs are usually good in situations when we are dealing with large amounts of information on a single page or window and, as a consequence, users are having difficulties finding, using, and focusing on specific content and possibly, tasks. Tabs are really handy in such situations, as they allow us to break up related pieces of information and organize them on individual tabs, making them available one at a time. According to Microsoft's own Windows user experience guidelines, there are several questions that are to be asked when deciding whether you should use the tabs as control. They can be summarized as follows: ff
Can all your controls comfortably fit on a single page? If so, there's no need for tabs, and the same. The same holds true if you are using just one tab—do not use tabs just to use them. You might be tempted to do so thinking that this would make your application or web application more professional, but the reality is quite the opposite.
ff
Are you using tabs to organize settings and numerous options? Be sure to check if the changing of the options on one tab affects options and settings on other tabs. Each and every tab must be mutually independent. If that is not the case, use wizard pattern.
ff
From the hierarchical point of view, ask yourself: Are the tabs mostly peers (on the same levels) or do you have a clear hierarchy organization among them? Tabs must have a peer relationship, never hierarchical. Just think about it: they are linearly represented—an orientation that is implying the same hierarchy levels.
ff
Are you using tabs for wizard-like step-by-step processes where the first tab represents starting point and tabs that follow are next steps in the process? If that is the case, again, wizard is the appropriate pattern.
This list, of course, is far from comprehensive but offers you some initial guidelines.
70
Chapter 1
Real-world metaphor Tabs are taken from the real world and they do aim to leverage familiarity that most users have from tabbed folders. As we do use tabs in the real world to group related documents, the same idea must be used in the world of user interfaces. We benefit from organizing related elements and content onto individual tabs. Furthermore, you should think about the order of your tabs and set them in a way that will make sense to your users. Among other things, that is the reason why tabs are pretty popular events on the Web as navigational controls, although that is not and should not be their primary role.
Implementation guidelines In most cases, tabs will be presented horizontally or vertically. How do we decide? Again, Microsoft's and other UI guidelines suggest, among other things, the following: ff
Horizontal tabs should be used if you plan to use seven or fewer tabs and all tabs fit in one row.
ff
Vertical tabs are good for cases when you are dealing with eight or more tabs or if using the horizontal tabs would require more than one row (the case might be that you have five tabs but with very long labels in their header).
ff
Forget about using scroll bars for horizontal tabs. This pattern has poor discoverability while usage of scrolling for vertical tabs is acceptable. General idea is to have all tabs always visible. If you have too much content which must fit on a single tab, then put a scrollbar on that specific tab, not on the window that is hosting your tab control.
ff
By default, make your first tab selected in all cases. Exclusion from this can be only a specific case when users are likely to start from the last tab that they have selected before dismissing a window or page with tabs. In that case, make the last tab selected to persist on a per-window, per-user basis. My personal experience is that your exceptions like these are extremely rare and you will probably do a better job just by ensuring that the first tab is always selected for users.
ff
Don't use and put icons on tabs' headers. They add visual clutter and consume screen space. You might be tempted to use them hoping that they will improve users' comprehension but that is rarely the case. However, there are some cases when icons might be fitting:
Icons you are using are standard symbols, well known, and widely recognizable, and understandable Use icons if there is not enough space to display significant labels
71
Layouts and General Content Organization ff
Place the terminating buttons (OK, Cancel, Apply, and so on) on the area outside the tabbed area, onto the dialog. A good example for this is given in the following screenshot:
By doing that you will avoid confusion in respect to the scope of the actions being carried away when user clicks on those buttons. Actions triggered by clicks on terminating buttons placed outside the tabbed area are applied to the whole page or window.
See also ff
72
Wizards
Chapter 1
Adding a status bar area The area at the bottom of the primary application window can be used for a status bar— control that is suited for displaying the current state of the window and accompanying actions, background tasks, or some other contextual information. In this recipe, I will demonstrate how to add the StatusBar control to our WPF application and share some guidelines regarding the implementation and usage of this pattern.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears, select WPF and then WPF Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK..
How to do it... 1. Once your new WPF project has been created, you should notice that under the Objects and Timeline pane, Window and LayoutRoot grid controls are visible. 2. Go to Asset Library and from there click on the StatusBar control. Draw it onto your artboard. Note that the StatusBar control will probably be hidden, so you should make sure that the Show All option, located at the Asset Library dialog, is checked. 3. Select StatusBar by clicking on it. Now we will set up some properties. Go to the Properties pane and under the Layout section change the following:
Set Width to Auto and Height to 24
Set HorizontalAlignment to Stretch (last icon in the row)
Set VerticalAlignment to Bottom (third icon in the row)
Set all values for Margin to 0
4. Your StatusBar should now appear docked to the bottom of your window and stretched from side-to- side. 5. As you can notice, StatusBar looks completely blank. Let's add a single line at the top of our StatusBar just to make it appear more distinct from the rest of the window surface.
73
Layouts and General Content Organization 6. Under the Appearance section, set 1 for the Top Border value. Now under Brushes section, locate the BorderBrush, and click on it. Now click on the Solid color brush icon and pick some kind of dark gray. You can also enter RGB values: 123,123,123 or HEX: #FF7B7B7B.
7. Your StatusBar should now have a simple gray border at the top. Let's add some controls to our StatusBar. However, note that I am just adding random controls now and not following specific guidelines; those can be found under the There's more... section and you should refer to them when designing and implementing the status bar pattern. 8. Right-click on the StatusBar control and from the drop-down menu, select Add StatusBarItem; this will add the simplest possible item to your StatusBar. 9. Now, click on StatusBarItem to select it and under the Properties pane locate the Common Properties section. Enter Ready for the Content property.
74
Chapter 1
10. In order to change the Content property of StatusBarItem during the run-time, we need to assign it a name. At the top of the Properties pane, you will find the Name field; type myFirstItem in that field.
11. Now add a Button control on top of the LayoutRoot control. To do that, select LayoutRoot under the Object and Timeline pane and then from the toolbox or Asset Library draw a simple button on your artboard. 12. Give it a name btnChangeStatus (follow the same directions given under Step 26). 13. Set its Content to Change Status (This property is located under the Properties pane, in the Common Properties section). 14. The next step is adding an event handler that will change the Content property of StatusBarItem. 15. With Button selected, click on the Events icon under the Properties pane and you will be presented with a number of events. Let's add our event handlers for the Click event. To do that, you will just have to type in the name for those event handlers and once you hit Enter, Visual Studio will start and allow you to add code logic. You can use btnChangeStatus_Clicked as a name for your event.
16. Add the following code: private void btnChangeStatus_Clicked(object sender, RoutedEventArgs e) { this.myFirstItem.Content = "Status has been changed!"; }
75
Layouts and General Content Organization 17. Press F5 and your application will start. Click on Change Status and note that the text in your status bar area has changed.
How it works... After the StatusBar control was added, I set several of its properties. I've set the height to 24 (it was fairly arbitrarily defined in this particular case), and I've also set the HorizontalAlignment to Stretch (to ensure that the StatusBar will consume all the horizontally available space). Also, VerticalAlignment has been set to Bottom (to ensure that StatusBar will dock to the bottom). By setting values of all margins to zero, I've ensured that there will be no empty space around the status bar when docked and stretched. In order to make the StatusBar a bit more distinct (and to show a really simple way of customizing the control), I've changed the top border width and color. With all the positioning and the look set, the next step was to add a very simple element to the StatusBar—StatusBarItem. Later, I will demonstrate how you can add a number of other different elements to StatusBar, but StatusBarItem was the simplest to do and it served me well to show you how to update its Content property via code. This pattern might be used in real applications to update status messages during runtime, but in case your development knowledge is more advanced, you can take it to a more advanced level. But the idea remains the same: give the name to StatusBarItem and change its Content property.
There's more... Status bar can be used to host more different controls to help you build better and more solid user experience for your users. In this section, you will learn how to do exactly that but you will also gain knowledge and valuable guidelines for implementing and designing user interfaces which are utiling StatusBar control.
Adding other controls to StatusBar The previous example showed how to add the simplest of all elements to StatusBar. However, Blend enables you to add a number of other different controls to your StatusBar. 76
Chapter 1
You can take it from the last point in the first example. 1. Select the StatusBar control and under the Properties tab, locate the Common Properties section. Click on the ellipses button near Items(Collection) and the Collection Editor (Items) dialog will appear. At the bottom, click on the arrow pointing downwards near Add another item. From the list, select Separator, and press Enter. 2. Repeat the procedure but this time select Button control from the list. 3. In the right-hand part, scroll down to Common Properties and type Button Content in the Content property. Press Enter.
4. Click on OK and now press F5 to start and test your application. Now you should be able to see a button with the Button Content label in your StatusBar control.
77
Layouts and General Content Organization 5. If your button is not completely visible, try changing the StatusBar Height property to, let's say 32. Press F5 now and your application should like the one in the following screenshot:
What if we want to add controls that are not listed in the drop-down list the we have seen in the Collection Editor? For example, how can we add the ProgressBar control? 6. Under Objects and Timeline pane, select the StatusBar control. Now go to Asset Library and pick the ProgressBar control. The next step is just to draw the ProgressBar control on top of your StatusBar control. Alternatively, you can just draw the ProgressBar control on your artboard and simply drag-and -drop it on top of the StatusBar. If you press the Alt key while dragging, ProgressBar will be added as an element of the StatusBar.
Take into account, if you want to be able to set or get properties from objects added to StatusBar control, you need to name them and use that name when referencing them from code. 78
Chapter 1
Adding SizeGrip to StatusBar Size grip is a commonly seen and used pattern: it enables you to grab a corner of your window and pull it to resize the window. Here is how to add a size grip to your status bar and enable resizing. I will just continue from the last example. So, return to Expression Blend. 1. Under Objects and Timeline, select Window. 2. Go to the Properties pane and locate the Common Properties section. You will find the ResizeMode property there. 3. Click on the drop-down list and select CanResizeWithGrip. 4. You will now notice the size grip at the bottom-right corner of your window, on top of the StatusBar control. 5. Press F5 to start your application. Position your mouse cursor over the size grip and try resizing the form. As simple as that, zero lines of code!
When to use status bar A status bar should be used in cases where you want to provide status information to your users but without harsh interruption of their main activities. It is generally located at the very bottom of the main (primary) application window and stretches from left to right with no margins, though specific exceptions might occur. Information provided in a status bar is usually related to the current window's state, possible tasks in the background, or some contextual information. The single most important thing is that a status bar should be used to provide information to the end users without interrupting them, which also means that information provided in a status bar should not be extremely critical or something that requires immediate attention. So, displaying status of loading a web page is fine, but letting the user know that a virus has been found on their C drive is something that requires immediate attention and should not be communicated through status bars. 79
Layouts and General Content Organization Usually, a status bar uses simple text or images (icons) to communicate information, but a number of other controls can be also used. A progress bar (indicator) is one of them and it is often seen in web browsers showing the loading process of a web page. Also, menus for commands and options can be used in status bars. However, status bars have one disadvantage: they are not easily discoverable. It is fairly easy to overlook them or even to completely ignore them. What can you do to "fix" this? I hope you are not thinking about using some aggressive animations, blinking, vivid icons, or some other means of grabbing users' attention. Recall what I said a few lines earlier: information provided in the status bar should not be extremely critical or something that requires immediate attention. Ensure that the information you are placing into the status bar is relevant and useful and if that is not the case, well, then don't use the status bar. Also, if a user must see the information, then don't put it in the status bar—the status bar is not for critical information. So, to summarize, use the status bar for relevant and useful information, but never for critical information!
Implementation guidelines As always, throughout this book, the implementation and other guidelines provided here are not 100% comprehensive, rather they are suggestions and proven practices extracted from various resources. However, the ones presented in this book are those most commonly used and by following them you will avoid common pitfalls and ensure solid quality. ff
A status bar should be presented only on the primary window of your application. You should never use status bars on all of the windows of your application.
ff
Don't use status bars as places to describe usage of controls on your UI. In the past (and I still see that sometimes), there was a trend to display information relevant to specific controls in the status bar. For example, if you positioned your mouse pointer over the printer icon, you would get something like Click here to print current document in your status bar. You should use tooltips for this pattern, never the status bar. Same holds true for menu items.
ff
Is the information that you want to display in the status bar critical and/or does it require immediate action? If so, then don't use the status bar for it. Consider a dialog or message box, they will break the flow and grab user's attention.
ff
Although it's not a rule (because of their relatively low discoverability), status bars might not be suitable for programs intended primarily for users who are beginners.
80
Chapter 1 ff
When using icons in the status bar, always choose easily recognizable designs. Also, use icons with more unique shapes; if possible, avoid rectangular- or square-shaped icons. You can use tooltips for icons that are not accompanied by related labels.
ff
Don't change the status bar content too often. Status bars should present up-to date information, but they should not appear noisy or distracting.
ff
When using textual labels, make them concise. Don't use bold, italic, underline, or colors to put emphasis on status bar text labels. That will only add visual clutter and noise without really helping the users and communicating valuable information.
81
2
Actions and Commands In this chapter, we will cover: ff
Command buttons
ff
Classical menus
ff
Context (right-click) menus
ff
Progress indicators with known process duration
ff
Progress indicator with unknown process duration
ff
Menu buttons
ff
Command links
ff
Split buttons and creating one from scratch
ff
Multiple item selections with a simple ListBox
ff
Multiple item selections with a ListBox and CheckBox combination
Introduction Actions and commands can be considered the foundation of any user interactions in your applications— whether web or desktop, there's no difference really. As you will see in this chapter, a number of concepts are literally the same in both web and desktop, while some are a bit more different (for example, context menus are very common in desktop applications while on the Web, context menus are not as popular, and there are a number of reasons for that). Anyway, in this chapter you will learn how to create, design, and implement a number of different UI patterns targeting WPF and Silverlight.
Actions and Commands
Command buttons This recipe is a little bit different and the only one where I am deliberately modifying our "Getting ready—How to do it—How it works" scheme. Adding buttons in WPF or Silverlight is really a very simple procedure—you go to the Asset pane in your Expression Blend library and draw a command button on the artboard. However, buttons are widespread and one can argue that they are most common and most used element of the user interfaces—both on desktop and web environments. Therefore, this whole recipe will mostly be based on guidelines and design suggestions of when and how to properly use buttons in your applications.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears selectWPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Assets library and locate the Button control. Draw it on your artboard. 3. If you now hit F5, your project will start and you will be able to see your button. If you click on it, nothing will happen. 4. To execute an action we need to define an event handler for a specific button. Before you do that, select your button and set its Content property to Execute and its name to btnExecute.
84
Chapter 2
5. Now switch to Events and double-click on the field next to Click. Blend 4 will present you with code editing capabilities where you can define your code-behind logic for a Click event. Make sure that your code looks like this: private void btnExecute_Click(object sender, System.Windows. RoutedEventArgs e) { this.btnExecute.Content = "Clicked!"; }
6. If you now hit F5 and start your application and click on your button—its content will change to Clicked!
How it works... I can safely say that, in this whole book, this is the simplest recipe. We have drawn a button, changed its property, given it a name and assigned it an event handler. Again, this recipe is more about providing you with the guidelines for proper button usage rather than giving you some complex examples and too specific scenarios. So, let's start.
There's more... Command buttons are basic building block for the most of user interfaces available today. However, ability to use them properly and implement them in that way is something that is often being missed. In this section you will be able to learn more about UI guidelines for command buttons.
When to use command buttons? This question (and answer to some extent) might seem trivial but practice and reality show that it is not known widely. As a general but pretty good rule, you can say that the buttons should be used in cases when users are executing an immediate action. There are several exceptions: where we have been describing wizards we have been using buttons for navigating back and forward, but even in those cases we can argue that clicking the button has resulted in immediate action.
85
Actions and Commands In cases when you need to provide users with several choices, you can use the combination of radio buttons (in case there is only a single option that should be selected, like in the following screenshot), checkboxes (when you want to allow users to select several options), and command buttons.
When to use ellipses? I'm sure you have seen that some buttons (and even menu commands) are followed by ellipses (…). When do you use "normal" commands and when do you use ellipses at the end of button (or virtually any other command for that matter, for example, in menus)? Ellipses should be used in cases when you want to give a hint to your users that they will be able to make more choices (or even to cancel the action) after they click on that command.
86
Chapter 2
For example, consider the following from Microsoft Office Word 2007:
When the user clicks on Reapply then this action will be executed right away, but if users choose to click on Modify…then a dialog box with further options will be presented to the end user, and from there it will be possible to either cancel the whole action or change some settings. Does this mean that you should use ellipses each and every time when you are about to initiate a new (dialog) window? The answer is no, as ellipses should be used only in cases where more information from the end user is needed to complete the action. So, if you are showing Help or About windows, ellipses are not needed.
Tone and manner One word: verbs. Commands on buttons should be verbs since they are indicating specific commands. Be sure that labels you are using are concise and self-explanatory as much as possible-don't tell stories to your users, but do tell them what will happen when they click the button.
Default and cancel buttons Silverlight does not support concepts of the default and cancel buttons but WPF does. The idea is if a button is set as the default, then its command will execute when the user presses the Enter key and if it is set to cancel then its command will execute when the user hits the Escape key on the keyboard. Properties of interest in this case (for WPF) are IsDefault and IsCancel, located under the Common Properties section. As you might guess they can be set to True (checked) or False (unchecked). Make sense of defaults Make sure that, when setting a certain button to be the default you think about the real user's needs, and use the best guesses you can. Even better, if you can, conduct a user study to gain insights and valuable feedback about what actions users perceive and consider to be default ones.
87
Actions and Commands
General guidelines 1. Take care over button sizing—using too short or too long buttons is the best way to ensure that your user interface will look unprofessional. It is recommended that your buttons are 75 pixels long and 23 pixels tall. If you are positioning buttons close to each other, be sure to leave eight pixels' spacing between neighboring buttons. Of course, exceptions are possible, but these are my recommended dimensions. 2. Each and every button must have a label. The same goes for the access (shortcut) keys. Take a look at the recipe about classical menus to see more information about shortcut keys and how to define them—the basic idea is same for command buttons as well. 3. Though you may be tempted, don't go wild and try to combine text labels and images in command buttons. Use images only where they add significantly to the understanding of the action or command that is to be performed. Also note that, by default, neither Silverlight nor WPF support adding images directly into a button through a specific image property. But that is easily achievable. All you need is several lines of XAML code to achieve that: <Button x:Name="btnImage" Width="108" Height="30" > <StackPanel Orientation="Horizontal">
Also, you can use your tools in Blend and simply add those elements into your button control. In the long run, it might be faster for you to grasp those concepts. As you can see we have just added StackPanel within Button and then added Image and TextBlock as shown in the following screenshot:
More about command buttons You can find even more detailed guidelines (though without code samples) as a part of the official Microsoft Windows UX guidelines at http://msdn.microsoft.com/en-us/ library/aa511453.aspx.
88
Chapter 2
See also ff
Command links
ff
Classical menus
ff
Split buttons and creating one from the scratch
ff
Menu buttons
ff
Wizards
Classical menus If I had to bet on what is probably the oldest and best known thing in the world of classical graphical user interfaces (GUIs), I would probably bet on menus. Good, old, omnipresent menus. You can see them all around—on the web or on the desktop; simple, complex, single level or cascading—they are part of almost every user interface today. However, the fact that they are so widespread leads to the idea and common feeling that you can't really fail with a menu, no matter how you implement them. You must be doing a great job, as menus have been around for years and everyone uses them. Of course, the reality is different and, since menus are here and they are here to stay for a while, in this recipe I will explain how to add, design, and create menus for your solutions and, probably more importantly, I will give you advice on how to design and use menus in your solutions. Of course, you should take it with a grain of salt, as you should do with any advice given here or anywhere else, but guidelines presented here will certainly, help you in designing and implementing menus.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it.... 1. After you have created your new project, under the Objects and Timeline pane you will see Window and LayoutRoot. LayoutRoot is a Grid control hosted in Window. 2. The first step is to add a Menu control. Under the Assets pane type menu to search for Menu control, or you can just browse for it. Double-click on it and it will be added automatically to your artboard surface.
89
Actions and Commands 3. Consider the Menu control as a container of some sort. We need to add a number of MenuItems to construct and build a typical menu. So, the next step is to find the MenuItem control under the Assets pane. If you just double-click on MenuItem (while the previously added Menu is selected), it will be automatically added to the Menu control. Under the Objects and Timeline pane you should now be able to see something as shown in the following screenshot:
4. You can now understand that we will be dealing with a hierarchical organization of specific MenuItem controls used for building your desired menu. 5. Under the Properties pane, locate the Common Properties section and the Header property. Type File and hit Enter. Your MenuItem control should now have File as its caption. 6. How about adding other items and building your menu structure? It's easily done with Collection Editor. You can call it by clicking on the Items (Collection) button under the Common Properties section for your MenuItem control. 7. Bold enables you to add new MenuItems such as a Separator, Button, CheckBox, or a regular MenuItem. You can add them by selecting them from the drop-down box located in the bottom left. On the right-hand side you will have options available for every added MenuItem. 8. Let's create a menu that looks like the one shown in the following example:
90
Chapter 2
9. To achieve this you need to add several MenuItems using the Collection Editor and assign the properties as in the following table: MenuItem type
Header
MenuItem
_New
MenuItem
_Open
MenuItem
_Save
MenuItem
Save _As...
Separator MenuItem
Page S_etup
MenuItem
_Print...
Separator MenuItem
E_xit
10. Adding the underscore (_) in front of the specific letter in the Header property will render the specific MenuItem as underscored when users press the Alt or F10 keys. More about additional menu customizations can be found in the There's more…section. 11. At the end, select the Menu ("the container") and set its Height to Auto and Width to Auto as well. Set the HorizontalAlignment to Stretch and VerticalAlignment to Top. This will stretch it across the top of your screen. 12. Hit F5 and investigate your menu. You can hit ALT or F10, or access your menu using the shortcut keys.
How it works... The working mechanism is fairly simple. It is based on a hierarchical model where Menu serves as a root element while MenuItem defines specific menus and items. 91
Actions and Commands Let's take a look at XAML code listing: <Menu VerticalAlignment="Top"> <MenuItem Header="_File"> <MenuItem Header="_New"/> <MenuItem Header="_Open..."/> <MenuItem Header="_Save"/> <MenuItem Header="Save _As..."/> <Separator/> <MenuItem Header="Page S_etup..."/> <MenuItem Header="_Print..."/> <Separator/> <MenuItem Header="E_xit"/>
As you can see, a hierarchical model is present here, and the Header property describes the appearance of the text being shown to the end users.
There's more... Previous recipe has shown the simplest menu form, with basic menu items, and has explained how to design a very simplified menu. In this section I will go a bit deeper and explain several more additions and menu features.
Executing commands The primary idea of menus is to organize information and options available to users, and execute commands when users select or click on the specific menu item. Executing a command associated with a given MenuItem is fairly simple. 1. Select the desired MenuItem. You can do it by either clicking on the MenuItem on your artboard or by selecting it from the Objects and Timeline pane. Let's first select MenuItem (New). 2. Under the Properties pane, at the very top give the name mnuNew to the selected MenuItem. Click on the Events icon (looks like lightning). You will see a list of events—double-click on the field next to Click. This will enable us to define a Click event handler for this specific MenuItem. Also, you can type in an event handler name if you don't want to use the one that Blend is adding automatically. Just type it in and hit Enter to go to the code-behind file. 3. Expression Blend will now switch you to the code-behind file, and here you can edit the desired code. Note that our event handler is automatically generated and we can just add the desired code. 92
Chapter 2
4. We want to show a simple message saying that the specific item has been clicked on. The complete code looks like this: private void mnuNew_Click(object sender, System.Windows.RoutedEventArgs e) { MessageBox.Show("New item has been clicked!"); }
5. If you now hit F5 and select File and then New, a message box will appear. You can also hit ALT>F>N and the same command will be executed.
Adding accelerator / shortcut keys I'm sure you have seen accelerator and shortcut keys that enable you to execute specific commands by using key sequences; like CTRL+C (copy) or CTRL+V (paste) and so on. It's fairly simple to add those into your WPF menus as well. We need to take care of the InputGestureText property. 1. Select the first MenuItem (mnuNew) and locate the InputGestureText property under the Properties pane. Enter CTRL+N. 2. If you now take a look at your menu you will see this:
3. Note, however, that InputGestureText only places the keyboard shortcut in the menu item. It does not associate the command with the specific MenuItem. The application must handle the user's input to carry out the action. 4. You can define that event handler under the KeyUp event in your Window. The complete code listing looks like this: private void Window_KeyUp(object sender, System.Windows.Input. KeyEventArgs e) { 93
Actions and Commands if
((Keyboard.Modifiers (e.Key == Key.N))
==
ModifierKeys.Control)
&&
{ MessageBox.Show("New command!"); } }
5. If you now hit F5 and then CTRL+N after your application has started you will see message saying New command!
Creating cascading menus Up to now we have been dealing with simple, single level menus. Often, however, there are situations where we have a need for menus with several levels of hierarchy. Achieving that in WPF is simple. 1. Click on any MenuItem that you wish to add child-elements to. Let's say we will use Save MenuItem in our case. 2. With the desired MenuItem selected, again locate the Collection Editor and create a new menu. 3. If you take a look at the XAML code, it may look somewhat like this, depending on your menu design: <Menu VerticalAlignment="Top"> <MenuItem Header="_File"> <MenuItem x:Name="mnuNew" Header="_New" Click="mnuNew_Click" InputGestureText="CTRL+N"/> <MenuItem Header="_Open..."/> <MenuItem Header="_Save"> <MenuItem Header="Sub item _1"/> <MenuItem Header="Sub Item _2"/> <MenuItem Header="Save _As..."/> <Separator/> <MenuItem Header="Page S_etup..."/> <MenuItem Header="_Print..."/> <Separator/> <MenuItem Header="E_xit"/>
4. And if you hit F5 and start your application, you will notice an arrow pointing in the direction of the new cascading menu.
94
Chapter 2
Adding icons Adding icons is also one of the common procedures when designing menus. I will show you how to assign an icon to a specific MenuItem. 1. Be sure that you have added an .ICO file to your project. 2. Let's use our mnuNew as the MenuItem of our choice in this sample. Select it under the Objects and Timeline pane and then right-click on it. From the drop-down menu select View XAML. 3. Replace the existing code with the following: <MenuItem x:Name="mnuNew" Header="_New" Click="mnuNew_Click" InputGestureText="CTRL+N"> <MenuItem.Icon>
4. Note the part between the MenuItem.Icon tags. Basically, we are saying that our MenuItem will use an Image object as a source for our icon. In this particular case it's called favicon.ico though your file will almost certainly be different.
95
Actions and Commands 5. If you hit F5 and start your application you will notice a new icon right next to the MenuItem.
Creating checkable menu items In most cases MenuItems are not just plain, simple labels (with or without icons) that you click on but they also trigger some action. MenuItems can be checkable, meaning that you can check certain values and act upon those. 1. Thanks to the IsCheckable and IsChecked properties you can set on and off check marks near your MenuItems. 2. Select the desired MenuItem and under the Properties pane locate the IsCheckable (under the Common Properties section) and IsChecked (under the Appearance section) properties. 3. Check them both on and take a look at your menu item.
4. If you click on the already checked menu item, it will be automatically be unchecked. If you click on it again, it will be checked and the check mark will appear. 5. The XAML code is really simple and straightforward: <MenuItem Header="Always as JPG" IsCheckable="True" IsChecked="True" /> 96
Chapter 2
Well, now you know how to create checkable menu items, but how to use them and in which situations? The next section will answer that and number of other related questions.
Menu design and usage guidelines The guidelines are as follows: 1. It is good to enable and disable certain menu items depending on the current context. For example, the option Burn to CD should be disabled if there is no CD burner present on the computer. However, don't change menu items' names dynamically, since that harms your users' ability to learn and memorize parts and commands in your user interface. 2. Keep the number of top-menu categories (File, Edit, View) under 10. 3. Don't put the commands with the same name under different menu categories. Users will not benefit from this pattern-it might lead to confusion, since they will not be able to remember where they saw the command. 4. The same goes for command buttons—use short, concise, and self-explanatory labels. Use ellipses when needed (This was explained in the recipe about the command buttons, so please refer to that for more details). 5. Don't put more than 20 (maximum 25) menu items under a single menu category. This does not include items under submenus. 6. Feel free to use separators for organizing menu items in groups within menus. 7. Regarding order—don't go by alphabetical order but set them in a logical order. 8. Don't use more than three levels of submenus. Never! They will end up being so hidden that your users will not be able to locate and make use of those commands. 9. Checkable menu items are used only for options. Never use them for commands. 10. Use icons sparingly, only when they do add additional value for end users, and even if you end up having lots of icons under one menu, don't feel the pressure to provide icons for each and every menu item you have in your menus.
See also ff
Context (right-click) menus
97
Actions and Commands
Context (right-click) menus Be sure to check the previous recipe about classical menus. This recipe will build on the premise that you have read and understood the design principles and ideas behind classical menus. Context menus, however, do have some specifics and that is the reason I have not included them in the previous recipe. The basic idea behind context menus is that they are activated, in most cases, by right-clicking on the specific UI element and, depending on the context (hence the name), a drop down menu appears with available commands.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see Window and LayoutRoot. LayoutRoot is a Grid control hosted in Window. 2. From the Toolbox, select Rectangle and draw it on top of your artboard. Go to properties and under the Brushes section set its Background to any color (other than white, let's say red). 3. We will add a context menu to this rectangle—meaning that when the user right-clicks on the rectangle, a drop-down menu should appear. 4. With the rectangle selected on your design surface, locate the Miscellaneous section in the Properties pane. 5. Locate the ContextMenu property and then click on the New button. 6. The section will expand; from there find the Items(Collection) property and click on the ... button. Collection Editor will appear, the very same dialog as in the previous recipe about classical menus. 7. Create your menu. You can follow the instructions from Step 6 of the previous recipe. 8. After you are done with designing your context menu, hit F5 and start your application. Right-click on the rectangle and your context menu will appear.
98
Chapter 2
How it works... Virtually any UI element can have its own context menu. Of course, having context menus defined for some UI elements does not make any sense. However, a number of situations do require context menus. Luckily, in WPF and with Expression Blend 4 it is simple to create a context menu for the desired UI elements. In our specific scenario we have added a context menu to a rectangle— all you need to do is just locate the Common Properties section and create a new menu. A number of other properties will be exposed, but the most important is to locate the Items(Collection) property and to define your menus' structure and appearance. You can follow instructions given in the previous recipe for adding icons, checkable items and so on-after all, a context menu is just a menu with a slightly different invoking mechanism. The guidelines for context menus are somewhat different from those for classical menus, so be sure to check them in the following section.
There's more... Be sure to read and understand context menu design and usage guidelines. They will help ensure proper implementation, and, at the end, better user satisfaction.
99
Actions and Commands
Context menu design and usage guidelines The guidelines are as follows: 1. Contextual menus are only for contextual commands and options. 2. Commands that appear in contextual menus should also be present in other, classical menu toolbars. Don't keep them only in contextual menus, since that might lead to poor discoverability. 3. Avoid using submenus for context menus. You will want to enable your users to have quick and efficient access to available commands. 4. Keep the number of items under 15. Studies have shown that having significantly more than 15 proves to be difficult for users to handle and efficiently locate commands they were looking for. 5. Access keys should be assigned to all items without exceptions. 6. All other guidelines (icons, separators, labeling) are same as those for the classical menus. With icons, however, you are encouraged to use them in order to help users locate most commonly used commands (yes which means you should add icons to the most commonly used commands).
See also ff
Classical menus
ff
Split button and creating one from the scratch
Progress indicators with known process duration There are two possible UX patterns when we are dealing with progress indicators. In some cases the duration of the specific process cannot be calculated or resolved, and still we might want to consider showing the progress indicator. In most cases, however, we do have certain information and knowledge regarding the process' duration and progress. Silverlight, as well as WPF, does support both of these situations through a control called ProgressBar. This recipe describes situations where the process duration is known or can be calculated programmatically.
100
Chapter 2
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... We will create two examples—the first one will demonstrate liquid layouts, and the second one fixed layouts. 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the ProgressBar control. Draw it on your artboard. 3. Under the Properties pane set its name to prbProgress. 4. Scroll down through the Properties pane and locate the Common Properties section. You can find a number of interesting properties here. For now, set them as in the following table: Property
Value
IsIndeterminate
False (no check mark)
LargeChange
1
Maximum
100
Minimum
0
SmallChange
0.1
Value
69
5. If you now hit F5 and start your application you will see something like this:
6. As you can see, the progress bar has filled in exactly 69 percent of the control's length (since we have set the Value property to 69 out of 100 which is the Maximum possible value in this case). 7. Okay, this was simple since we have set the Value during the design time. In reality, you will need to connect the current ProgressBar control's Value property with the actual duration and progress of the specific process.
101
Actions and Commands 8. An easy way to test that behavior is to just write few lines of C# code to mimic the possible real-life situation. 9. Add a new button to your design surface from the Asset library. Set its name to btnStart and Caption to Start. 10. We will use this button to trigger a simple event and change the Value property programmatically. 11. With the btnStart selected, switch to Events view on the Property pane (lightning icon) and double-click on the field near the Click event handler. Expression Blend 3 will create some code and placeholder for our code. Make sure your code looks like this: private void btnStart_Click(object sender, System.Windows.RoutedEventArgs e) { this.prbProgress.Value = this.prbProgress.Value+1; }
12. If you hit F5 and click on your Start button you will notice that your progress bar is changing, and that for every click you can see it being "filled in".
How it works... After you added the ProgressBar control, you set up some of its properties. Probably the most prominent of those are Minimum, Maximum, and Value. Minimum and Maximum tell us the range of values your ProgressBar control is able to show. For example, if we set the Minimum value to 0 and Maximum value to 100 this means that we will use a "regular percentage scale", so 50 percent of the process' progress will be described by setting the Value property to 50. Of course, you can set, for example, the Minimum value to 0 and the Maximum to 55 (or virtually any other value) but the corresponding Values in that case won't be the same as the percentage of the relapsed process duration. The Value property is one that should be updated to reflect the actual process progress. In this simple sample I've showed you how you can change the Value by increasing it up 1 every time you click on the button. In real life situations, you will need to hook up the Value property with the real process duration and update it.
102
Chapter 2
There's more... Progress bar with known process duration is often present in today modern user interfaces. This section will give you professional and easy to use, understand and implement guidelines for this specific pattern.
General guidelines 1. Don't use the progress bars if your operation is expected to last five seconds or less. In that case you should set your mouse cursor to busy. You can achieve that by setting the Cursor property to Wait (Cursor="Wait"). 2. In some cases your application might be performing operations that are sometimes really quick (under five seconds) but sometimes they take longer. In those cases you might consider showing the afore mentioned Wait cursor and if after five seconds the operation still has not been completed then you can display the progress bar. 3. If you are dealing with a very lengthy operation (over two minutes), enable users to set the window with the progress bar in the background and notify them later when the operation has been completed. 4. If you can't calculate and track progress of the operation then use the progress indicator with IsIndeterminate property set to True. The next recipe (Progress indicators with unknown process duration) explains all the steps needed for that. 5. Whenever possible consider providing the users with feedback about what is currently going on. For example, in the case of downloading or uploading a file, use the label under the progress bar control and change its content to reflect the current percentage, speed, or some other valuable information.
6. With Windows Vista, disk space availability is now presented in Windows Explorer. Though in this case we do not see the progress exactly, we see rather space availability, that pattern is implemented with progress bar control.
103
Actions and Commands 7. Providing a useful animation depicting the current process is also helpful. It gives the user an idea of what is going on and helps them to visualize the operation.
8. The recommended sizing for progress bars is 355 pixels long and 15 pixels tall. 9. Labels above or below the progress bar should be at least five pixels apart. 10. Official Microsoft Windows guidelines explain in detail about progress bar controls, so feel free to use them as a reference: http://msdn.microsoft.com/en-us/ library/aa511486.aspx
See also ff
Progress indicators with unknown process duration
Progress indicators with unknown process duration This second recipe describes situations where process duration is unknown, or it can't be calculated programmatically. Be sure to read and understand the previous recipe.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
104
Chapter 2
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the ProgressBar control. Draw it on your artboard. 3. Under the Properties pane set its name to prbProgress. 4. Scroll down through the Properties pane and locate the Common Properties section. You can find a number of interesting properties here. For now, set them as shown in the following table: Property
Value
IsIndeterminate
True (set check mark)
LargeChange
1
Maximum
100
Minimum
0
SmallChange
0.1
Value
69
5. If you now hit F5 and start your application you will see something like this:
How it works... It is clear that this kind of progress indicator does not allow you to see overall progress. By setting the IsIndeterminate property to True, you are transforming the classical progress bar into a progress bar used in cases where you can't get the actual duration of the process. All other property values set in the previous table are being ignored; the only property that makes sense is the IsIndeterminate property.
105
Actions and Commands
There's more Indeterminate progress bar are close relatives to the "regular" progress bar. And while majority of user interface guidelines can be used for them, there are some specific cases where you need to pay additional attention. This section is covering those for you.
General guidelines 1. This type of progress bars (also called an indeterminate progress bar) should be used only in situations where the length of the process cannot be determined. 2. If, during the process, length becomes possible to calculate, switch immediately to a regular progress bar so that users can get feedback and a clear understanding of the progress and when it will be finished. 3. Never combine this type of progress bar with a percentage complete figure (remember, we are using this progress bar type since you don't know the information about length and completeness). Also, don't combine them with animations. If you take a closer look you will notice that this type of progress bar is animated itself. So having two or more animations at the same time, for the same concept, does not bring any new value to the end users and should be eliminated as such. 4. The rest of the guidelines can be applied from the previous recipe describing the progress indicators when the process' duration is known or can be calculated and presented.
See also ff
Progress indicators with known process duration
Creating menu drop-down Later in this chapter, one of the recipes explains how to create a split button from the scratch. This recipe is fairly similar to that one, and I will show you how to create a simple menu button control. A typical menu button control and associated drop-down menu is shown in the following screenshot, taken from Microsoft Dynamics AX application:
106
Chapter 2
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see Window and LayoutRoot. LayoutRoot is a Grid control hosted in Window. 2. We will create our menu button by modifying the control template. 3. From the Asset library (or from the Toolbox) select Styles and from there select and draw a SimpleButton on your design surface. 4. Right-click on the button and from the dropdown menu select Edit template > Edit copy. A new dialog box will appear. Type MenuButton for name and leave the other settings the same (we will create this menu button just for this current window, though we can define in it separate resource dictionary and reuse it later). Hit OK when you are done. 5. If you now take a look at the Objects and Timeline pane. You will notice that our scope has been changed to Template and that now we are editing the button's template.
107
Actions and Commands 6. Select the Grid and on the design surface you will notice a blue border around your button. You might want to zoom in to have a better overview (you can use the mouse scroll button for zooming in and out). We need to divide our Grid into several columns. Position your mouse cursor at the top of the button, on the blue border, and you will notice that your cursor changes so that you can add grid lines. Set two of them as shown in the following screenshot:
7. Note that we have defined three columns. In the first one we will have our button's main content, and the second column will be just a small separator, dividing the textual content from the down-pointing arrow which will be located in the third column. 8. We need to define some sizes for our columns. If you go to your XAML code you will notice a XAML code part describing Grid.ColumnDefinitions. You should set them to be like this:
9. This means that our first column will have its size adjusted depending on the content within it, the second column will be fixed in size and will always be five pixels, while the third column will take up the rest of the available space. 10. With the Grid control selected, add the TextBlock control from the Assets pane or library. Just double-click on it and it will be added as a child element to our Grid control. But, as you will notice, it won't be located exactly where we need it to be (third column). 11. To achieve that, select the TextBlock control from the Objects and Timeline pane and under the Properties pane locate the Layout section. Set the Column to 2. 12. WPF starts counting columns from zero, so our first column is considered as zero to WPF, making the third column for us second one for WPF. You should now be able to see your TextBlock control added in the third column. 13. We will set its Text property to a small black triangle / available as a Webding font: use Word > Insert > Symbol and then 6. So you can copy and paste it into the Text property of your TextBlock control. Be sure to change the Font to Webdings for this control and set its size to 9. 108
Chapter 2
14. Make sure to set all margins to zero, HorizontalAlignment to Left and VerticalAlignment to Center. Also, set the button's name to btnMenuButton so we can reference it within the code later. 15. Your Objects and Timeline pane should now look somewhat like this:
16. Click the Return scope to Window button—the upward pointing arrow near the MenuButton (Button Template) label. 17. Now your button should look like this:
18. Of course, you can always play with the margins and other settings, but that is not the current focus of this recipe. 19. The next step is to add a drop-down menu and make it visible when the user clicks on the button control we have just added. 20. First, define ContextMenu and position it properly. 21. Before we do that, let's set the Content property of our button to Format. 22. Now, with the button selected, go to the Miscellaneous section under the Properties pane, and hit the New button next to the ContextMenu property field. Collection editor will appear and there you can create your context menu. For more details you can refer to the Context menu recipe in this chapter. 23. After you have defined your context menu, be sure to set the Placement property of your context menu to Bottom.
109
Actions and Commands 24. The next step is to give a name to our ContextMenu so it can be referenced later on. Go to your XAML or Split view (switch with F11). Locate the piece of code that looks like this: <Button.ContextMenu >
<MenuItem Header="Font..."/> <MenuItem Header="Paragraph..."/>
25. Add the x:Name part and make it look like this:
With this, we have called our context menu LeftClickMenu and we can reference it later on. 26. As I have mentioned in the Context menu recipe, a context menu is triggered when the user right-clicks on the object with the associated context menu. In this case, however, we want to show the context menu when user clicks with normal, left button. To achieve that, we will resort to a bit of C# code and a simple event handler. 27. With your btnMenuButton selected, go to Events and double-click on the field close to the Click event. The code editor will open and a placeholder for your code will be created. Add these two lines of code: this.LeftClickMenu.PlacementTarget = this.btnMenuButton; this.LeftClickMenu.IsOpen = true;
28. If you go and hit F5 to start your application and click on the Format button, you will notice a drop-down menu positioned exactly how we wanted it to be.
How it works... The crucial part in this recipe was the modification of the SampleButton control. We have modified the template—basically, we added a TextBlock with the downwards pointing triangle as static content, and made it an integral part of the buttons control. Adding the context menu, positioning, and handling it has been already described in detail in recipes about creating split button and using the context menus.
There's more... Guidelines applied to a split button can be used for menu button as well, but there is single major difference between a split button and a menu button. 110
Chapter 2
Split buttons are always used for grouping several variations of the same command, while menu buttons are used for organizing smaller sets of related commands. Menu buttons are good as a replacement in cases when we want to avoid menu bars. Those situations are cases with dialog boxes, or virtually any other window without a menu bar.
See also ff
Context (right-click) menus
ff
Split button and creating one from the scratch
Command links One of the new UI elements introduced with Microsoft Windows Vista was the command link. They are now in Windows 7, and are even finding their way into RIA applications. A typical dialog with number of command links looks like this:
Command links are used in situations where users can select a single response to a main instruction and move on to the next step in a task or process. They are simple, clean, and lightweight. They contain a main instruction, an icon, and an optional description. Later in this section you will find detailed guidelines on how to use command links. 111
Actions and Commands
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. We will build a custom control and expose a number of properties. This means that our command links control will be reusable within your Silverlight project, and very flexible for that matter. 3. So, first step is to go to File > New item and then select UserControl. In the Name field type CommandLinks.xaml. Hit OK. 4. This will open a new design surface where we will design our control. We would like to have a control looking like this:
5. We will create it from four elements. We will use a Border control as a container, two textboxes (for the main instruction and description text), and an image control for the icon. 6. I will not go into too much detail regarding positioning of the controls—after all, you can find the source files at the download location, so you can examine the architecture there. But let's go through the most important properties you need to set for specific controls:
112
Object
Property
Value
Border (brdBorder)
Padding
10 for all
Background
#FFFFFFFF
BorderBrush
#FFFFFFFF
BorderThickness
1 for all
CornerRadius
3
Chapter 2
Object
Property
Value
TextBlock (txtMainInstruction)
Width / Height
Auto
Text / Font
Segoe UI
Font size
12 pt
Foreground
#FF003399
HorizontalAlignment
Stretch
VerticalAlignment
Top
Margin
23 for Left, 16 for Top, 0 for the rest
Text
Main instruction text
Width / Height
Auto
Text / Font
Segoe UI
Font size
9 pt
Foreground
#FF003399
HorizontalAlignment
Stretch
VerticalAlignment
Top
Margin
23 for Left, 21 for Top, 1 for Bottom and 0 for Top
Text
Enter the description here if needed
Width / Height
16
HorizontalAlignment
Left
VerticalAlignment
Right
Margin
5 for Top, 0 for rest
Source
Image1.png (depends)
TextBlock (txtDescription)
Image (imgIcon)
7. Add the txtMainInstruction, txtDescription, and imgIcon objects on your artboard. Select them all and right-click on them. From the drop-down menu select Group Into > Border. Name the border brdBorder. You will notice that a Grid control has been automatically added to host the Image control and TextBlock controls, since a border can host only one child element. 8. Find a the PNG or some other graphic file sized to be 16 x 16 pixels. You can use those in the source files as well, which is your icon for this our example. 113
Actions and Commands 9. If you have done everything properly your design surface should look like this:
10. Next thing we have to do is make the brdBorder control change its Border color when the user hovers its mouse cursor over it, and to reset it to white when users moves the mouse out of the control. 11. Blend 4 has introduced the concept of Behaviors—reusable code samples and parts of interactivity that are specifically designed to help designers and developers to achieve different levels of interactivity without really writing the code by themselves. We will use the ChangePropertyAction behavior for our needs. 12. From the Asset pane select Behaviors and then click and drag the ChangePropertyAction to the brdBorder control. Now select the added Behavior and you will see its properties under the Properties pane. Set the properties like this: Property
Value
Name
behMouseEnter
EventName
MouseEnter
PropertyName
BorderBrush
Value
#FF88E6FF
Duration
00:00:00.10
Ease
None
13. This first behMouseEnter will handle the event of user's mouse cursor entering the border. Now lets create a new Behavior—just click and drag it again and set the following properties:
114
Property
Value
Name
behMouseLeave
EventName
MouseLeave
PropertyName
BorderBrush
Value
#FFFFFFFF
Duration
00:00:00.10
Ease
None
Chapter 2
14. The next step is to expose the properties. Since we are building this as a custom, user control, and we want it to be reusable and have some properties exposed we need to add some code. Go to your code-behind file (CommandLinks.xaml.cs). You can access it from the Projects pane by expanding the node close to the related XAML file. 15. Add the following lines of code under your namespace: public partial class CommandLinks : UserControl { public CommandLinks() { InitializeComponent(); } public string MainInstruction { get {return this.txtMainInstruction.Text;} set { this.txtMainInstruction.Text = value; } } public string Description { get {return this.txtDescription.Text;} set { this.txtDescription.Text = value; } } public ImageSource Icon { get { return this.imgIcon.Source; } set { this.imgIcon.Source = value; } } }
16. With this code, we will expose MainInstruction, Description, and Icon properties to the end users. 17. Now let's build our project and control. Go to Project > Build Project. 18. Return to your main XAML file, the one that was first to appear there when you started your project. From the Assets pane, locate the Project, click on, it and on the list locate the CommandLinks control. Click on it and draw it on top of your artboard.
115
Actions and Commands 19. With the control selected, scroll to the Miscellaneous section of the Properties pane and you should see our exposed properties:
20. Now you can change those properties, define your own event handlers, and treat this control as any other you used to work with before. 21. If you now hit F5 to test your project and hover your mouse over the command link you just added then you will see that its border will change the color exactly as we have defined it by using the ChangePropertyAction Behavior.
How it works... The main idea in this recipe was to create a flexible user control and expose a number of its properties. Of course, we could take the approach of creating the command buttons manually by drawing all the constituent elements every time we need them. Soon, we would see that this approach is not very good, especially in situations where you need to reuse the control and set its properties through the code. Therefore, we created a new UserControl as a part of our Silverlight project. The next step was designing our control. It is important to point out that designing of the UserControl does not differ from the "regular" UI design when we are building the UI from the pre-built controls. All ideas, tooling capabilities, and philosophy stay exactly the same. So, we added a border control as a container, two text boxes (for the main instruction and description text) and an image control for the icon, and set their initial properties. An important thing to note is that we have named all those objects, so we can reference them through the code later. At one point we decided to utilize the new concept introduced with Expression Blend 3 Behaviors. We wanted to change the border color when the user positions the mouse over the control, and reset it to original color (white) when the mouse cursor is moved out of control. We have used ChangePropertyAction to described both cases and required property changes, depending on specific events (MouseEnter and MouseLeave). This is a very powerful concept since it enables pretty high levels of interactivity without writing a single line of code. 116
Chapter 2
Okay, after we have designed our control and set the behavior, we have arrived at the point where we need to expose properties that could be set and used when utilizing our control. We have decided to expose three properties: MainInstruction, Description, and Icon. In the code-behind file we have added several lines of code to enable this. The next step was to build the project and return to our main file (startup), and locate our newly created CommandLinks control. After we had drawn it on the artboard and selected it, we could see its properties exposed under the Miscellaneous section and set them or change them from that location. This has enabled us to add a virtually unlimited number of CommandLinks control from the Asset pane or library to our project. without the need for creating them from the scratch. Furthermore, all exposed properties are visible even in a coding environment—meaning that you can set and change exposed properties, during the run time via code instead of just changing them through Blend's UI. Also, if you are using Visual Studio as your development (hopefully not design) environment, you should be able to set this control's properties even through the Visual Studio IDE.
There's more... Command Links are a somewhat new addition to the control toolbox and therefore guidance for their proper implementation and usage was really needed. In the following sections you will be exposed to those guidelines so that you can safely and professionally use and implement Command Links control in your user interfaces.
Guidelines At first sight you might consider command links as a distant relative of the radio buttons; after all, they are used in pretty much the same manner-to chose only one option from the several ones that are available. This means that they always appear in sets, never isolated. As I said in the introduction to this recipe they appear lightweight, clean, without heavy borders; resembling hyperlinks (hence the name). The other part of name, "command", makes a lot of sense, since by clicking on the command link users are either committing the command and closing the window, or proceeding to the next page (if used within the wizards as it was the case when I was explaining the wizards apostrophe pattern). So, here are several most important guidelines regarding the usage of the command links. 1. Command links should be used only in cases when they are presenting mutually exclusive options. Simply stated, users can select one and only one available option.
117
Actions and Commands 2. When the user clicks on the command link, it will execute the command and close the window (or dialog) or it will proceed to the next step if used within wizards. This implies that they cannot be used within property windows or within tabs, since they are closing the window after the user clicks on them. Of course this holds true for desktop applications. In web space and when designing RIA Silverlight applications you should use them in the same manner. You can either use them in pop-ups, modal dialogs or, as parts of a wizard, and then navigate to next page. 3. If you are using them within wizards they should serve for gathering users' choices and selections, not processing them and committing them right away. There are at least two good reasons for this. The first reason is that when users see command links, they will intuitively connect them with regular hyperlinks seen on the Web and make an assumption that they are connected with flow and navigation. The second reason is that sometimes users will want to return to their previous step and select a different option—you must enable them to do so. 4. Never use less than two command links, and try to keep the number on the same window or page up to five or so. Never use a single command link. The fact is that, though they look lightweight in their appearance, command links do take up some serious screen space. Therefore, if you need six or more options, consider using radio buttons. 5. If you have really short explanations or commands then consider using regular command buttons. 6. Description is optional. Provide it when it makes sense to the users but don't put too much text. Users should be able to see and make decisions fast. Also, if the main instruction is self-explanatory you don't need to use descriptions. Remember, they are optional. 7. With dialog boxes, when gathering information from users and when clicking on a command link, it will execute a command and close the dialog, hence make a clear and explicit Cancel or Close button (depending on the context). That way, the user will be able to cancel their operation fast and they will not need to read through the command links. 8. If, after the user clicks on the command link, an action is not executed right away, then display a busy cursor. If that lasts for longer than five seconds, consider showing the progress bar. For detailed guidelines on progress bar usage, take a look at the related recipe. 9. An icon is not optional; all command links must have an icon. The arrow icon is the default one, use it in all cases except the following:
118
If there is a need for an immediate response (user account control dialog will appear...) then you should use a shield icon
Chapter 2
Adding a custom icon will help better communicate and visually identify a specific option. The arrow icon is 16 by 16 pixels, but you can use larger icons—32 by 32 pixels are standard. If you need to position a shield on top of existing icon, then always go for 32 by 32 or, if space allows, consider using 48 by 48 pixels icons.
10. Command link labels should be clear, concise, and understandable. If the option they are presenting is complex, you can use descriptions but, again, keep in mind that they are optional and should not be overused.
See also ff ff ff ff
Command buttons Wizards Progress indicators with known process duration Progress indicators with unknown process duration
Split button and creating one from scratch Unfortunately, WPF lacks a simple Split Button control. Basically, it is the regular button usually used to consolidate a set of variations of a command, especially when one of the commands is used most of the time. Typical (expanded) split button might look like this one shown from Outlook 2007:
119
Actions and Commands In this recipe we will create a really simple but effective split button with accompanying dropdown menu.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select WPF and then WPF Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see Window and LayoutRoot. LayoutRoot is a Grid control hosted in Window. 2. We will create our split button using two buttons and context menu. Be sure to check out the recipe about context menus to help you understand some related concepts. 3. From the Asset library (or from the Toolbox) draw a button on top of your design surface. Call it btnContent and set its Content property to New. Set the Height to Auto and Width to 82. 4. Now add a new button, calling it btnDropDown. Set its Height also to Auto and Width to 105. 5. We will use btnDropDown as a part of the split button that, when clicked, opens a drop-down menu. For that reason set its Content to 6 (downward pointing rectangle, available as a Webding font, you can use Word > Insert > Symbol and then 6. So you can copy and paste into Content property of your btnDropDown. Be sure to change the Font to the Webdings for the button. 6. Furthermore, set the HorizontalContentAlignment property of the btnDropDown to Right to make sure that the triangle is right-aligned. Also, set the HorizontalContentAlignment property of the btnContent to Left and left Padding to 5 to move the string New a bit from the left edge. 7. Position the btnContent on top of the btnDropDown. They should look somewhat like this:
120
Chapter 2
8. We have now basically achieved the split menu look; now we need to add a drop-down menu that will appear when the user clicks on the triangle part in reality, our btnDropDown. 9. With btnDropDown selected, define a new context menu for it. Go to the Miscellaneous section under the Properties pane and hit the New button next to the ContextMenu property field. Collection editor will appear and there you can create your context menu. For more details you can refer to the Context menu recipe explained earlier in this chapter. 10. Be sure to set the Placement property of your context menu to Bottom. 11. After you have created your context menu, you need to give it a name so it can be referenced later on. Go to your XAML or Split view (switch with F11). Locate the piece of code that looks like this: <Button.ContextMenu > <MenuItem Header="Mail"/> <MenuItem Header="Note"/>
12. Add the x:Name part and make it look like this:
With this, we have called our context menu LeftClickMenu and we can reference it later on. 13. As you know by now, a context menu is triggered when user right-clicks on the object with the associated context menu. In this case, however, we want to show the context menu when user clicks with normal, left button. To achieve that, we will resort to a bit of C# code and a simple event handler. 14. With your btnDropDown selected, go to Events (remember the lightening icon?) and double-click on the field close to the Click event. Code editor will open and a placeholder for your code will be created. Add these two lines of code: this.LeftClickMenu.PlacementTarget = this.btnDropDown; this.LeftClickMenu.IsOpen = true;
121
Actions and Commands 15. If you now hit F5 and click on the part of the button with the arrow symbol, you should see something like this:
16. Adding event handlers, icons, and everything else to this menu is the same as it was described in recipes regarding classical and contextual menus. 17. To make handling this split button easier you might want to select both buttons, right-click on them and from the menu select Group Into > Grid. It will just group both buttons in one grid control so you can handle it more easily.
How it works... Note that we have a used simple, but very effective trick here. We have combined two buttons, positioned it in a specific way and set the content for each of them. Visually, it was straightforward and a simple thing to do. We decided to go for context menu and to launch it when the user clicks on the btnDropDown. After we have defined it and set its name we have added two lines of code. First line: this.LeftClickMenu.PlacementTarget = this.btnDropDown;
is saying that placement target for the specific context menu (called LeftClickMenu) is our btnDropDown control. And the second line: this.LeftClickMenu.IsOpen = true;
says that our menu should stay open unless the user clicks somewhere on the design surface to close it. Notice that we have defined this event handler for a Click event and basically just ensured that the context menu will appear upon left-click. By setting the Placement property to Bottom we have ensured that our context menu will be aligned to the bottom of the PlacementTarget; in our case, it was the btnDropDown. Again, even in this recipe you have seen how easy it is to combine different controls and achieve desired behaviors. 122
Chapter 2
There's more... In the following sections you will be exposed to interesting approaches how to implement this specific pattern in Silverlight as well as to professional user experience and design guidelines you should be aware of when implementing this user interface pattern in your solutions.
How to do it with Silverlight? Silverlight 4 does support contextual menus (not the Split Button though), but this recipe is showing you how to implement this type of pattern using the WPF. Ideas, approaches and methods shown here can be used for your Silverlight projects as well. Positioning buttons, changing their content, and related operations are the same. The difference is in the part that, instead of the ContextMenu object you can use the control called Popup and handle its Visibility, HorizontalOffset, VerticalOffset, and related properties. Since Popup control exposes Grid control, you can add any content into that Grid and mimic the typical menu look and feel.
Guidelines 1. The split button is always used for grouping several variations of the same command. In our recipe we have used New as a 'main' command but consolidated other related options like Mail or Note. 2. Clicking on the right portion of the button will reveal a drop-down menu and users can select one of the available options. After they click on the specific option, the left part of the button should be changed to the last option selected (note that I have not implemented this in this recipe, but it is fairly simple to do so). 3. The rest of the guidelines regarding labels and other elements can be used from the guidelines for command buttons.
Multiple item selections with simple ListBox This pattern works well for relatively small item lists when you are looking into a simple way to enable your users to select several items from the predefined set.
123
Actions and Commands There are number of different implementations of this pattern, but simplest one of them is based on the ListBox control, both in Silverlight and with WPF.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. From the Asset pane select the ListBox control and draw it on top of your artboard. 3. Right-click on it under the Objects and Timeline pane and from the drop-down menu select Add ListBox Item. Repeat the procedure 7-8 times to have that number of ListBox items generated. Make sure that you always have ListBox selected while adding new items to be sure that they will be properly added. 4. Now locate the SelectionMode property under the Common Properties section (in the Properties pane) and set it to Extended. 5. Hit F5 and your application will start. Now, with Control key pressed use the mouse to select multiple items. It's the same way you might select files and folders in Windows Explorer.
6. The only thing you need to do now in your code-behind file is to figure out which items are selected and process them or execute your desired command. 7. To do that, go to ListBox.SelectedItems, which will give you the list of all selected items which you can easily process in any way you deem appropriate for your needs.
124
Chapter 2
How it works... This is extremely simple recipe. I have added a ListBox control and several ListBoxItem elements. For the sake of brevity, I haven't changed their labels. The next step was setting up the SelectionMode property. I've set it to Extended. That value allows users to select multiple items by holding down the Control (CTRL) key and clicking on the items to select them. It also allows them to use Shift key to select several items in range without the need to click on every item individually. This behavior is the same as seen in Windows Explorer when users are selecting files. The only thing that is needed at the end is to handle the selection of the items and process them in a way that is required for the application to work properly. You can do this by using the ListBox.SelectedItems option.
There's more... There are three values that can be used for the SelectionMode property. We have used Extended in our recipe, what about Single and Multiple?
Explaining the SelectionMode property There are three available values for the SelectionMode property—Extended (explained in this recipe), Multiple and Single. Let's investigate them a little bit. Multiple If you set the SelectionMode to Multiple, start your application, and then start clicking on the items you will notice that they all get selected the first time you click on them, and deselected when you click again. This "sticky" mode can be also used for selecting multiple items, although I would not recommend it since (based on my own user study) most users are not expecting this kind of behavior for this control. Single Setting the SelectionMode to Single will disable the ability of the ListBox to select multiple items at the same time. Of course, you will still have the ability to select one and only one item (hence the name for this value), but there is no way of selecting multiple items in this particular case.
Personal note I won't give you any specific guidelines, as my personal opinion is that this UI pattern might be abandoned in the future and instead of using this one, you should resort to the next recipe where, instead of using ListBoxItems I am using CheckBoxes as they give users a better understanding of the underlying concept. 125
Actions and Commands If you want to make your users' lives easier then you should try to avoid this pattern, or at least complement it with the one described in the previous recipe, letting the users choose how they prefer to use this pattern. Skip to the next recipe where I will explain how to achieve the same pattern but with the help of CheckBoxes. You might wonder why I even bothered to show and explain this pattern in the first place. The reason is that this pattern is still widely used. As I said, even Windows Explorer is still using it. And while it might be good for expert users, novice users will never understand this pattern right away. Who is used to trying to click on several items while holding the Control or Shift key pressed? That said, you might consider allowing your users to switch to this pattern if they are already familiar with it and see no clear advantage in havings checkboxes based version of this pattern.
See also ff
Multiple item selections with ListBox and CheckBox combination
Multiple item selections with ListBox and CheckBox combinations This recipe basically continues the previous recipe, so I would suggest that you go and read the previous recipe before taking on this one.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. From the Asset pane select the ListBox control and draw it on top of your artboard. 3. Under the Properties pane locate the Common Properties section and Items(Collection). Click on the browse (...) button and Object Collection Editor will appear.
126
Chapter 2
4. From the drop-down list at the bottom left-hand side (marked with Add another item) select CheckBox. 5. On the right-hand side of the Object Collection Editor you can see properties related to the specific item you have just added. Locate the Content property and set its value to, let's say, Item. Repeat this procedure several times and when you have added several CheckBox controls click on OK. 6. For the ListBox, set the SelectionMode property to Single. 7. If you now hit F5 and start your project you will see that now you can easily check and uncheck multiple items at the same time.
8. Only thing you need to do now in your code-behind file is to figure which items are selected and process them or execute the desired command. 9. To do that you can go to ListBox.SelectedItems which will give you the list of all selected items which you can easily process in any way you deem appropriate for your needs.
How it works... Like the previous recipe this is a very simple recipe. We have added a ListBox control and several CheckBox items. By doing this we have enabled users to select multiple items without having to struggle with Control and Shift keys. Only thing that is needed at the end is to handle the selection of the items and process them in a way that is required for the application to work properly. You can get a collection by using the ListBox.SelectedItems.
127
Actions and Commands
There's more... As I said in the previous recipe I'm a firm believer that this pattern should be the one that is used for novice users. However, I can agree that by having check boxes close to every item you are drawing a lot of attention to the selection, maybe even more than to the specific items. Therefore, I'd suggest using this pattern if you cannot safely tell that your users are power users. If, however, you are dealing with users who are experienced and familiar with Control / Shift key combinations, consider using the previous pattern.
General guidelines 1. I would suggest having the number of visible items in the list below 10. You can have more and make use of the scroll bar appearing in those cases, but even then try to keep the number as small as possible since users often do need to have a global overview of items they have selected. 2. If you don't have any hierarchical or logical ordering, you should order them alphabetically. 3. It's a good idea to add a label below the ListBox indicating how many items have been selected. This will give your users clear understanding of the number of selected items. 4. When picking the height of the ListBox make sure that an integral number of items is always visible. It is unprofessional to see, for example, five items completely while the sixth item is being partially obscured. 5. If there is a clear advantage in having the ListBox resized with the parent Window then you should enable that behavior. This is especially useful if you are dealing with long item labels and users will benefit from wider list box. http://msdn.microsoft.com/en-us/library/aa511484.aspx
See also ff
128
Multiple item selections with ListBox
3
Searching, Finding, and Navigating In this chapter, we will cover: ff
Designing prominent action points
ff
How to create faceted navigation and classification
ff
Creating tree views
ff
Creating and using expanders and collapsible panels
ff
Creating and using paging patterns
ff
Using titled sections
ff
Creating and using task panes
ff
Creating and utilizing promoted actions
Introduction This chapter deals with one of the most prominent tasks every user faces when he is using web or desktop applications. A number of different features, data, and files are just a part of the elements that the user is navigating through. Without proper organization and efficient navigation, the user will fail in his/her attempts, and it won't be his fault. Every user experience designer must approach challenges related to navigation with care and with deep understanding of his/her user's needs. Being humble and understandable also helps a lot.
Searching, Finding, and Navigating A user must always be in control of his position. His ability to navigate to other parts of the application and to have a clear understanding of what he can do next must never be compromised. A user needs to know and understand the current state of the application or the web page that he is using, and how can he find the resources and the information he is looking for. Difficult navigation has been proven to be one of the major reasons users get frustrated and leave your web page or application. Alan Cooper and Robert Reimann (authors of the famous book About Face) think that poor navigation is the number one problem in the design of an application or website. I could not agree more! In this chapter, a number of different patterns for content organization, search, and retrieval of information will be described.
Designing prominent action points This is probably one of the simplest UI patterns described in this book, yet, it is so powerful, and enables your users to get to the tasks and features as fast as possible. Clear entry points can really make your application stand out, but they are not suitable for every type of application or interface. Their main purpose is to enable users to get to a specific part of the application or website, or to show off the most prominent action. As such, applications utilizing this UI pattern are mostly task oriented and are, in most cases, used rather infrequently. In this recipe, you will learn when and how to implement this specific UI pattern, and in which cases that makes most sense.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Asset library and locate the Button control. Draw three buttons of the same size on your artboard. 2. As this is a really simple recipe without any real coding, you don't need to go too deep into specifics, but just set the names of the buttons to btnBuy, btnSel, and btnExit.
130
Chapter 3
3. Set their Content properties to Buy, Sell, and Exit, respectively. If you now press F5, your UI should look like this:
4. Notice that you can see the StockTrader label and gradient in the background; you can change the appearance and adjust it for your own needs. 5. If we were building a real application, our next step would be to define event handlers and assign them code logic. But for the sake of this recipe, this is enough.
How it works... By adding three buttons to serve as main entry points of this application, we have designed a simple, robust, and straightforward interface. Users are presented with three options regarding stock trading—selling, buying, and leaving the application. Of course, this is a highly oversimplified version, but the idea is to explain that by adding three very prominent and clear commands, you can cover the majority of the needs of your users. As mentioned before, prominent action points, also known as clear entry points, are used in cases where you can say, for certain, that users will always use smaller sets of commands. Obviously, that works very well with task-oriented applications where a large amount of commands, toolbars, menus, and other user interface elements might be too complex. With this pattern, it is clear on first sight what this application is for and what you can do with it.
131
Searching, Finding, and Navigating A good real life example is the Bing search engine (or pretty much any major search engine these days). You have a very prominent search input field and you know that you need to enter your search query to use it.
There's more... If your application is heavily task-oriented and the majority of its functions can be exposed and accessed through several clear and prominent entry points, then this is the pattern you should utilize. It is especially good for users who are beginners, or if your application is being used only occasionally and with a limited number of choices and options. For example, ATM machines usually utilize this kind of user interface pattern—you have several options and you are not sitting in front of the ATM machine for several hours every day. Your entry points should be visible to all your users, right from the beginning. Do not force users to activate some option to get through to this kind of interface. There is no clear consensus on how many entry points you should have on your user interface, but don't go for too many. If you put numerous entry points, they will lose their sense and in that case, using some other UI pattern might be a better idea.
132
Chapter 3
It is well-known from the theory (and practice) of user experience design that user interfaces should be optimized to cover the majority of needs that the majority of users need. People come to Bing or Google to search for information and data in the vast majority of cases. Sometimes, they will go further and will require some advanced options, but the fact is that while both Bing and Google do support those advanced options, their user interface is optimized for the simplest and yet the most commonly used operation—search. With this philosophy in your head, you should design your user experiences. Optimize for the most common scenarios, but provide choices for others as well. Some usability experts argue about the size of the elements representing entry points, stating that some correlation between the importance and the dimensions of buttons (or other elements) should be established. While I might find some good reasons for this, I would put emphasis on a specific position instead of on dimensions themselves. In our example, the Buy and Sell buttons are listed first, while the Exit button is the third one, as it is reasonable to think that users will start an application to buy and sell stocks first and to exit after that.
See also ff
Promoted actions
How to create faceted navigation and classification Creating and designing faceted navigation necessarily brings us to the question of faceted classification and, in broader terms, to information architecture. So, according to Wikipedia (not the best reference material around, but for this particular use it was suitable), a faceted classification system allows for the assignment of multiple classifications to an object, enabling the classifications to be ordered in multiple ways, rather than in a single, predetermined, taxonomic order. Furthermore, as A.G. Taylor points out in his Introduction to Cataloging and Classification, a facet comprises of clearly defined, mutually exclusive, and collectively exhaustive aspects, properties, or characteristics of a class or a specific subject. For example, a collection of books might be classified using an author facet, a subject facet, a date facet, and so on.
133
Searching, Finding, and Navigating A good example of faceted navigation in practice is Bing Travel (http://www.bing.com/ travel)—a website offering you faceted navigation and classification related to your search for airline fares.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. Though there are a vast number of controls that could be used for specific facet values, in this recipe, we will go with CheckBox, as it is capable of covering most of the desired scenarios. 134
Chapter 3
How to do it... Once you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a grid control hosted in UserControl. 1. Go to the Asset library and locate the TextBlock control. Draw it on top of your artboard and set its Text property to Price range and the text weight to Bold. 2. Now add several CheckBox controls, position them under the Price range label, and set their Content properties to: $0 - $10, $11 - $50, $51 - $100, and $101 and more respectively. 3. If you press F5 now, your interface should like this:
4. Now you can repeat the procedure and add more facets and their respective values and end up having an interface like the following screenshot:
135
Searching, Finding, and Navigating 5. So if we imagine that we have been building faceted navigation for some online apparel store, the above selections could be interpreted in the following way: The user is looking for some apparel, which costs more than $51, it is blue or black in color, and he wants only Lacoste and Zara as brands. The final result might be a number of different items satisfying those criteria, and users have had a really easy-to-use interface to help them narrow their search. 6. If you are about to take this pattern to the next level and add to it some sort of real code and interactivity, you would need to define event handlers and assign some code to them. The main objective is to respond to the users' selections. We can either use some sort of commit button that would require users to click on it after it has made its selections using the CheckBox controls, or we can update the result sets immediately after the state of the CheckBox controls has been changed. In the latter case, you will need to take care of the Checked and Unchecked events assigned for specific CheckBox controls and add some code to those event handlers. The basic idea is as follows: private void chkZara_Checked(object sender, System.Windows.RoutedEventArgs e) { // TODO: Add event handler implementation here. } private void chkZara_Unchecked(object sender, System.Windows.RoutedEventArgs e) { // TODO: Add event handler implementation here. }
Note that if updating and retrieving the result set takes longer than few seconds, you might need to implement some sort of progress indicator so that users are aware that there is something going on, and that their results will be displayed after a while.
How it works... We have designed our faceted navigation using the TextBlock control for captions and CheckBox controls for specific faceted values. There are two basic ways for updating and retrieving result sets. We could add a button and then run through all the CheckBox controls and check their states (using the IsChecked property), or we could update and display the result sets right after the specific CheckBox has been Checked or Unchecked by implementing those event handlers. 136
Chapter 3
However, as you are probably guessing by now, the real challenge of the implementation of this user interface pattern in Silverlight is not about how we handle specific events or even how we retrieve results sets, it's about how to properly classify and organize specific items. In the next paragraph, you will be able to learn more about that.
There's more... The main use for this particular user interface pattern is in those situations where you are dealing with a number of different items, characterized by different properties, but you have only a slight idea of what are you looking for. Remember our recipe example: we had a situation where a user was looking for apparel that satisfies very specific criteria regarding the price range, color, and brand. To address those scenarios, you will implement this user interface pattern and enable users to gradually find what they are looking for. That can be achieved by some investment and careful architecture the user interface. Be sure to organize it in a way that it provides your users various, relevant facets that can be then used to filter out their results sets. Your user interface might benefit from a faceted navigation and classification pattern, if you are dealing with large sets of information where filtering is really necessary. Also, it is a good choice only if your items do share some common properties—facets. For example, if you are selling shoes online, common facets are price, color, brand, size, and some others as well. But the crucial part is that those facets are known and understandable by the end users. As I've said earlier, the real challenge with this UI pattern is not in the sole Silverlight (or any other platform) implementation; it's about the selection of good facets, which is closely related to the extremely important field of information architecture. You should take care of the fact that facets must be contextually related to the result set—meaning that if you allow users to refine their search, those facets must be updated accordingly. Position of the facets is an important element as well—the most common positions are on the left-hand side or above the result set. Personally, I'd always go for the left-hand side; my personal user researches have shown that eight out of ten users look at the left-hand side for a location, even if both the locations, left and top, are available and filled with facets. There is an ongoing discussion about the possibilities for selecting different values under the same and other facets. In this recipe's example, I've used checkboxes and users can select any number of different values under any number of facets. Some UX theorists suggest the following: "it is ideal to allow the user to select multiple facets at a time, but only one value for each facet at a time". And last but not least, if your technical and architectural foundations allow for it, do show the number of items found in a given facet value; it will enhance your users' perception of the size of the result set. 137
Searching, Finding, and Navigating
See also ff
Progress bar
ff
Tiled sections
Creating tree views A tree view is a UX pattern that is useful when we want to provide our users with a simple way to view and interact with hierarchically organized data and item collections. In those cases, we can, depending on our specific case and need, allow users to select single or multiple nodes. Tree views as a pattern are rather common in today's applications. For example, if you take a look at Windows Explorer and explore the file structure, you will notice one of the possible tree view implementations.
A tree view is strictly a hierarchical pattern and its structure is pretty strict and predefined. Generally, a tree is built from a number of nodes. If a node contains other objects, then it is called a container node. However, if a node contains data then it is called a leaf node. 138
Chapter 3
There is a root node (obviously, it is a top-level node) and it is always a single one. Sometimes, expressions such as "parent" and "child" are used for describing mutual relations between nodes.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a grid control hosted in UserControl. 1. Go to the Asset library and locate the TreeView control. Draw it on top of your artboard. For now, just ignore the sizes, alignments, and other related elements. We will just focus on adding different items to the TreeView control. 2. Adding items is a simple process. Right-click on the TreeView control and from the drop-down menu, select the Add TreeViewItem option. You will notice that a new TreeViewItem has been added to your original TreeView control. Be careful when adding new instances of TreeViewItem: they will be added as child elements under the currently selected parent element, which means that you need to select proper parent elements to build the desired architecture. 3. Apart from regular TreeView items, you can add a number of different controls to your TreeView. One of the most popular and often used controls is a checkbox enabling you to make multiple selections. 4. To add a checkbox, select a parent TreeViewItem (in our case and in the sample code, it will be our root node) and from the Asset library select and draw the CheckBox control. 5. It will be visible on both your artboard and under the Object and Timeline pane. You can click and drag on it within the Objects and Timeline pane and reorder your CheckBox control as you wish. 6. Usually, the next step is customizing and setting properties for specific items. You can easily do that just by selecting a specific TreeViewItem or any other control (such as the CheckBox we added) and setting its properties and characteristics under the Properties pane.
139
Searching, Finding, and Navigating 7. Note that under the Properties pane, there is a Common Properties section with the Items (Collection) button. You can click on the … button and a new Object Collection Editor will appear. You can use it for setting up and modifying properties for all items that are added to your TreeView. 8. Most likely, you will be setting the Header property (visible under the Common Properties section), or the Content property, if the CheckBox control is being used as a TreeView item.
9. After you have created and arranged your TreeView control, all you need to do is press F5 and see the result in your web browser. One simple example is visible in the following screenshot:
140
Chapter 3
How it works... Silverlight comes with native support for the tree view pattern in the form of the TreeView control. TreeView control is available from the Asset library within Expression Blend. It is important to understand that you need to add different TreeViewItem controls in order to create a fully implemented tree view UX pattern. Also, as it was explained in the recipe itself, you are not limited only to the supported TreeViewItem controls, you can add CheckBox and a number of other different controls. However, keep in mind that the fact that you can add virtually any UI controls as an item to the TreeView control does not mean that you should do so; a number of them are completely inappropriate for this specific pattern. In the next section, you will be able to learn more about how to properly use and implement a TreeView control, and what to take into consideration while designing and implementing this specific pattern.
There's more... Before you decide whether the tree view is a good UX pattern for your specific case, ask yourself the following questions: ff
In its structure, is the data you are trying to represent hierarchical?
ff
Can you see and organize at least three levels of hierarchy, not counting the root?
ff
The hierarchical organization: does it appear to be logical and familiar to most of your potential users?
ff
Are your users more advanced, and not completely new to the system?
If you answered "Yes" to these questions, then a tree view might be the pattern you are looking for. It is important to notice that the fundamental element of the tree view is its hierarchical structure. Therefore, certain levels of relationships are also expected between nodes and their positions. However, you should not use the tree view pattern for every situation where you are dealing with hierarchical relations between separate objects. 141
Searching, Finding, and Navigating One of the main challenges when designing and implementing this specific pattern is discoverability. In some cases, tree views can be very exhaustive and their structure can be very rich. Finding the specific node and item then proves to be quite a challenge. For that reason, you should always try to design and organize your tree views so that they relate to the user's mental models. Notable authors like Cooper and Reimann are going go further and argue that the tree view, as a pattern, is something that is loved by developers but that the general public and end users do struggle with them, and have trouble understanding tree views. This, of course, just adds to the fact that you should use and employ this specific pattern only in those cases where hierarchical structure and specific relations coming from it would be easily recognized and used by your end users. The afore mentioned authors do go that far, and even say that "using a tree view to represent arbitrary objects organized in an arbitrary fashion at the whim of a programmer is asking for big trouble when it comes to usability".
Some guidelines for usage Because a tree view is a fairly complex control, a number of presentation, interaction, and organization guidelines have been put in place by a number of different software vendors. As was the case during the course of this book, I'll be relying to the guidelines developed and tested by Microsoft, but taking into account the specifics of the platform that we have opted to use in this case (Silverlight and WPF). ff
Sort the items within a container in a logical order. One good way to achieve this is to utilize the so-called "card sorting" technique where you let your test users generate their own architecture of the tree view. However, even if you don't use real users (though I'm a strong believer that you should!), do your best and organize the items in a logical order.
ff
If you are dealing with large data sets, don't load the complete tree view, go for the first two levels of containers and don't expand the second one.
ff
If you are allowing your users to expand and collapse your tree view, implement the "save state" option, so that if your users are using the tree view to navigate to different parts of application, you can preserve their selection.
ff
Though I can agree that connecting lines do add some amount of visual clutter, you might want to add them in order to emphasize connections and a hierarchical relation between elements. Even if you decide to drop the lines, use the indents (both WPF and Silverlight TreeView control support those) to emphasize the hierarchical relations.
142
Chapter 3
ff
To emphasize different high-level containers and their content, consider using different icons so that users can easily differentiate them.
ff
If appropriate, utilize the right-click (Context) menus for items where that makes sense, and enable users to execute those commands.
ff
Favor breadth over depth. Your tree should not have more than four levels (not counting the root) and the most important items and elements should be easily accessible within the first two levels.
ff
Try to avoid using horizontal scrollbars. Vertical scrollbars are fine in most cases. Also, you should take care that the width is be about 30% longer than the longest string. This is also good in cases when you are looking into localization plans.
ff
All nodes need to have labels. There are no exceptions here. Make those labels clear and understandable. Use sentence style capitalization.
See also ff
Progress bar
ff
Titled sections
ff
Context menus
Creating and using expanders and collapsible panels When you are dealing with vast amounts of user interface elements, or data for that matter, you are generally interested in reducing the complexities and enabling your users to be able to use and find all options, but not at the cost of visual complexity and screen estate. In those situations, usage of collapsible panels and expanders can be a very good method for achieving your goals. 143
Searching, Finding, and Navigating By organizing your tools, user interface controls, or some additional information into separate expander controls (more about later) or collapsible panels, you can ease the job for your users.
In fact, a number of today's mainstream applications are utilizing this specific UX pattern. One of the most prominent examples you'll see is the Expression Blend 3 user interface, especially the Properties pane with the number of different collapsible panels.
144
Chapter 3
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. There are two controls available within Silverlight enabling you to implement this specific pattern—Accordion and Expander. In this specific case, we will use the Accordion as it provides most of the desired features. Those features can be mimicked by combining several expanders in a StackPanel control with a vertical orientation, and then handling their behavior. So, for the sake of simplicity, the Accordion control will be used.
How to do it... Once you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Asset library and locate the Accordion control. Draw it on top of your artboard. It looks just like a blank rectangle for now. We need to add content to it and in this case, it would be a number of AccordionItem elements. 2. Right-click on the Accordion control under the Objects and Timeline pane and from the drop-down menu, select Add AccordionItem. 3. Repeat the procedure several times so that you can have four to five different AccordionItem elements. At this point, your control should look somewhat like this:
4. If you take a look at the single AccordionItem and expand it under the Objects and Timeline pane you will notice two main parts—AccordionItem itself and the Header part. 145
Searching, Finding, and Navigating 5. Select AccordionItem and under the Properties pane, locate the Header property and set it to First header. Also, locate the Content property and set it to This is 1st sample content. Your control should now look somewhat like the one shown in the next screenshot:
6. This was all easy, but what happens if you need more flexibility and not just plain text for your content? You can add a number of other different controls to the currently selected AccordionItem. 7. Let's add the Button control. All you need to do is draw a Button on top of your design surface. Then, click on the button with the Selection tool and drag it on top of the AccordionItem. A screen tip will appear saying that you need to press the Alt key while dragging the button and add it to AccordionItem. Press the Alt key, drag and release and the Button control now appears as a content of your AccordionItem.
146
Chapter 3
8. If you now hit F5 and start your project, you will be able to click on different headers and see them expanding and collapsing. You can notice that at this point only one panel can be opened at a time. However, Accordion control supports a number of different options where you can have one or more panels being allowed to be opened at the same time. To set those options, locate the SelectionMode property, which is available in the Common Properties section under the Properties pane of your Accordion control. You can set that property to: One, OneOrMore, ZeroOrOne, or ZeroOrMore, each corresponding to one of the supported scenarios.
How it works... We've decided to utilize the Accordion control to implement this pattern. It is a new control, now a part of the Silverlight toolkit; but it is expected to find its way directly in to a Silverlight release (possibly version 4), though there is no official confirmation on Microsoft's side for this. Accordion control allows you to add a number of different AccordionItem elements and then use them as hosts for additional content. In this specific recipe, it was shown how you can add a Button control, but in real life scenarios, adding some of the layout containers such as Grid would make more sense. This is because in that case, you would be able to host more controls in the Grid control itself and organize the content and controls in a way that is most appropriate for the specific case. The really neat features are the ones that enable you to set different ways of keeping your AccordionItem elements opened or closed at the same time. These are set through the SelectionMode property. Keep in mind that this control allows for a number of different configurations and organizational schemes, but you should always try and follow recommendations given in the following sections about the organization and proper design and implementation of this user experience pattern.
There's more... We can agree that this specific pattern fits into the class of organizational patterns (like a number of others in this chapter). That also means that the biggest challenge when designing and implementing this pattern is about structuring and organizing pieces of information you are looking to arrange.
147
Searching, Finding, and Navigating You will use this pattern in cases when you can clearly identify groups and collections of those items. Also, every group must have a clear and understandable name, which is not only broad enough to cover all of the items under a specific group, but also, at the same time, specific enough to communicate the exact and correct meaning. You can rely on the "rule" of thumb that elements organized in this pattern should be always one-click away. Also, bear in mind that actions and options provided in this pattern are almost always contextually dependent. This means that they will be applied on a specific document or a selected element, or a part of it.
Why would you use this pattern? Apart from the reasons described and derived from the broader context in the previous paragraph, there are a number of reasons for using this pattern. The obvious rationale is using it as a space-saver and this is what makes it somewhat related to tabs. But there is a significant difference—this pattern allows users to have more than just one panel open at the same time. And, as you know, with tabs, you can see the content of only one tab at a time. Most authors on this topic agree that using this specific pattern also serves as a tool for minimizing visual distraction. The reason for that is the fact that items are organized and can be shown or hidden depending on user's choice. There is one piece of real-life advice I'd like to share with readers now. Although I've mentioned that organizing items in clearly defined and logical groups is of utmost importance for using this specific pattern, there is one more thing to consider when organizing: you should always try to organize specific items in groups according to their relation for specific tasks. The reason for this is because, ideally, you want to minimize the user's distraction by opening and closing a number of panels just so that they can perform some actions simply, keep related actions in same groups, taking into account their logical organization and how often they are used in typical scenarios. When it comes to the position of the collapsible panels, they are usually positioned at the left or right edge of the screen. This also implies that items and commands presented there are somewhat secondary. Of course, this does not mean that they are never used or less important, but certainly, they are not used as much as the commands in toolbars or menus. The bottom line is that you should never put critical and often-used commands in collapsible panels. That could lead to user's frustration, as those commonly used commands would be somewhat hidden and not clearly visible. When it comes to the implementation of this pattern, luckily, the control described in this recipe is well-designed and in most cases, you won't need to do any modifications. However, it's good to know that this kind of pattern implementation should always allow users to open and close panels by clicking on the group names. Adding specific visual cues (arrow pointing in the action direction for expanding or collapsing) is also really helpful, because it encourages users to utilize this specific behavior of the panels. 148
Chapter 3
Often, the whole group can be positioned in a larger container so it can be moved or resized. You can easily adjust this recipe and position Accordion control in Grid, then separate it from the rest of the application surface with the GridSplitter control and utilize it as described earlier. This is also considered to be a mainstay in today's UI design practice; a good example for this is Microsoft Outlook or the aforementioned Expression Blend 3.
See also ff
Titled sections
ff
Faceted navigation and classification
ff
Tabs
Creating and using a paging pattern A paging pattern is one of the patterns used when dealing with larger sets of data. Good examples are search results from search engines such as Google or Bing. It's used for separating data sets into different pages so that the navigation is simpler and more straightforward in those scenarios. Concrete implementations can vary. Also, this pattern is used not just for search results. In fact, in our recipe, we will use it for paging and navigating the results within one of the data-presentation controls. Typical paging pattern implementations are shown in continuation.
Bing.com
WordPress blog administration section
Maybe the best known pagination pattern—Google.com 149
Searching, Finding, and Navigating
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. Note that this is a fairly complex recipe involving sample data generation—a new feature introduced with Expression Blend 3-and adding some code to the C# code-behind file. You will be guided step-by-step in this recipe, but depending on your level of experience you might want to be especially careful.
How to do it... After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Asset library and locate the DataGrid control. Draw it on top of your artboard. Repeat the procedure and now draw the DataPager control right below the previously added DataGrid control. 2. Name the DataGrid control dtgGrid and the DataPager control dtpPager. We will use these names later in the code-behind file so that we can easily reference them. The idea here is to display some data in the DataGrid control and then use the DataPager to support pagination and navigation through that data. First of all, we need some data. Expression Blend 3 (and newer versions, such as Expression Blend 4) supports so-called Sample Data Generation, enabling you to generate sample data, bind your controls to it and later, if needed, replaces it with real data. 3. Locate the Data pane (if it is not visible), go to the Window menu, and then check the Data. At the very top of the Data pane, you will notice two icons. Click on the first one (Add sample data source) and then from the drop-down menu click on Define New Sample Data….
150
Chapter 3
4. Now, the Define New Sample Data dialog will appear. Leave the SampleDataSource as the Data source name and make sure that the option Enable sample data when application is running is checked.
5. After you click on OK, you will notice that SampleDataSource has been added and defined as a Collection with two Property elements. You can edit those later and play with them, but for the sake of this recipe we will just keep the defaults. 6. Now that we have defined our data source, next step is to bind it to our DataGrid. 7. Drag-and-drop the Collection on top of DataGrid control.
151
Searching, Finding, and Navigating You will notice the screen tip. Just release the mouse button and you will notice that the data has now been added and is visible within your DataGrid control.
8. Now let's wire up our controls—DataGrid and DataPager. To do this, go to your code-behind file, it is probably called MainPage.xaml.cs. 9. We need to add several using statements at the top of your document if they are not present there. We will need to add the following: using System.Windows.Data; using System.Collections; using Expression.Blend.SampleData.SampleDataSource;
10. Now, locate the InitializeComponent(); line and right below that line add the following lines of code: var data = App.Current.Resources["SampleDataSource"] as SampleDataSource; if (data != null) { PagedCollectionView dataView = new PagedCollectionView(data.Collection); dtpPager.Source = dataView; dtgGrid.ItemsSource = dataView; }
Under the How it works... section, it will be explained what these lines of code actually do. For now, just keep going through the recipe. The next and final step is to change several properties of our DataPager control. 11. If you are still in your code-behind file, return to the design view and select the DataPager control. Under the Properties pane, locate the PageSize property and set it to 5. Also, under the DisplayMode you will notice a number of different options for displaying data navigation controls, for now select the FirstLastPreviousNextNumeric. Also, be sure to check the AutoEllipsis property. 152
Chapter 3
12. If you now press F5 and start your project, you will be able to navigate to your data using the DataPager control. 13. If you want to add more data to your DataGrid control, go back to the Data pane and click on the Edit sample values located near Collection.
14. A new dialog will appear from which you can further modify and change the generated data. Pay attention to the Number of records field at the bottom of the dialog. Enter 50 as the value in that field and Blend will automatically generate more sample data for you, allowing you to do even more realistic testing.
How it works... In this recipe, we used two main controls—DataGrid for the data representation and organization and DataPager for data navigation. The DataPager control can be used with a number of different controls supporting the data-binding concepts, but it is most commonly used with DataGrid. In order to make this recipe work, we needed some data. You can always use some external data sources; SQL databases and XML files being just two of the available options. However, Expression Blend 3 enables you to generate sample data that can be used throughout the project and can be bound to different controls. By utilizing this feature, we've created a DataSource called SampleDataSource. Later, in the code behind file we bound the DataGrid to that DataGrid. But the really interesting part here is the behavior and the architecture of the DataPager control.
153
Searching, Finding, and Navigating The DataPager control provides you with the configurable user interface for paging through the defined data collections. As a consequence, the DataPager control can be used with virtually any IEnumerable collection, but you should wrap it within the PagedCollectionView class in order to provide the full-paging functionality. In the end, all you really need to do is to assign the DataPager.Source property to the ItemsSource property of the desired control, in our case that was the DataGrid. They need to share the same data collection, in our case that was the dataView defined in our code-behind file. After doing this, the only thing left to do was to set several properties dealing with the actual representation and behavior of the DataPager and you're good to go!
After all, it wasn't all that difficult and the final result is pretty cool, right?
There's more... A simple rule can be derived for using this pattern: Use it in those cases where you are dealing with more data than you can easily and comfortably present on a single screen. The truth is that this pattern is most commonly used on the Web, especially on search engines, but it can be effectively utilized in standard desktop or RIA (rich internet applications) as well. There are two major characteristics of this pattern that should be taken into account, no matter how the actual design and implementation will look. The first is that this pattern enables users to navigate large data sets and the second is that it also provides them with a sense of how big a specific data set is. For example, how many records or pages are available or returned as results of search, filter, or some third action. In relation to that, it also provides them with an understanding of how many they have already checked out and how many remain. An important thing for implementation is also the fact that items should be shown in a consistent format with a well-defined start and end.
154
Chapter 3
There is also a psychological effect added to this—breaking the large content in smaller chunks gives users a better sense of understanding of the amount as well as the context. It also provides them with the opportunity to have some breaks, and time for making a decision whether they will navigate further or stop at some point. From your own experience you probably know that breaking a larger, complex system into smaller, more graspable parts usually makes look simpler and easier to use. The control that we've used in this recipe is a solid implementation of this specific pattern. In case you decide to use this control or develop some other, you should take into account that in any case you must give users an idea of how many pages or items there are, what is their current position, and how to navigate back and forth. Also, you might want to add the ability to jump to the first and the last record at any moment your users want to. A good idea is to use arrows or similar elements to emphasize directions (Previous, Next) and to make clickable areas around numbers fairly large so that the users have an easier job clicking to specific number representing a page or similar object. And when it comes to position, paging controls are in most cases found at the bottom of the page or just below the associated control. The reason for this is that in this case, the pagination pattern is usually perceived as a logical choice offering the users to continue reading through the data set or to engage in some other action.
See also ff
Titled sections
ff
Faceted navigation and classification
Using titled sections Using titled sections is a fairly simple pattern but it helps users when it comes to presenting large amounts of data. The basic idea with the titled sections pattern is organizing and grouping information into sections and adding clear prominent titles to them. This pattern is generally visible and used on websites though it can be effectively used in desktop as well as in RIA applications with a slightly different implementation. Several real-life samples are shown below.
155
Searching, Finding, and Navigating The following screenshot displays the footer from the UXPassion.com blog:
The next one displays the Internet Options dialog:
156
Chapter 3
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. This is a very simple recipe using only three different controls: Image, TextBlock, and HyperlinkButton.
How to do it... Once you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Asset library and locate the TextBlock control. Draw it on top of your artboard and set its Text property to Information for…. Set the text weight to Bold and text size to 9 pt. 2. Now add several HyperlinkButton controls and stack them below the TextBlock control. Set their Content properties to: Developers, Designers, Consumers, and Press. 3. Also, set the Foreground color for every HyperlinkButton to #FF414141. 4. Now you can add Image control right next to the TextBlock or you can use (just for the sake of this recipe) the Rectangle control and set its Fill property to #FF5973A8, set its Stroke property to #FF8098C5, and to make the corners slightly rounded, set both RadiusX and RadiusY to 4. 5. If you now click F5, your final results should look somewhat like the next screenshot:
Of course, you can add more sections like this one and even organize them in more meaningful chunks. Just be sure to follow common sense, good practices, and the design or implementation ideas presented under the There's more... section.
157
Searching, Finding, and Navigating
How it works... We have designed this titled section pattern by using three really simple controls. By using TextBlock, you can create the title itself. Make sure it's more prominent than the rest of the elements (HyperlinkButton) positioned below. You can achieve that by setting its text weight to bold and/or increasing the font size. Then, we've just stacked the number of HyperlinkButton controls and set their captions so they make sense when used under the specific section. The key thing here is, as described in the next paragraph, to ensure that categorization and organization makes sense to the end users. And finally, by adding an image (or in our case, colored rectangle) right next to the section title, you can help users differentiate specific sections and identify them easier.
There's more... If you are dealing with data and information that can be organized in logical groupings, and you can find meaningful headers or titles for those groupings, then this pattern can be used. It is important to note that in order to use and implement this pattern, global groupings should be established on a predefined information architecture and logical classification. You should not try to enforce this pattern in every case that might seem to be appropriate. The best results are achieved when you can find clear, meaningful, and intuitive relationships between information architecture organization and your groupings. Also, titled sections should not be the first pattern you are looking into to implement when dealing with this kind of information – consider using menus if you are dealing with commands and options, or other patterns such as faceted navigation and classification or collapsible panels.
Why would you use and implement this pattern? It is a well-known fact, confirmed in a number of psychological studies that we as humans are much better at absorbing, remembering, and understanding information if it is separated and broken into smaller chunks. And if you stop for a moment and think about it, isn't this principle present in virtually most of the patterns described in this chapter or the whole book, in fact? It doesn't come as a big surprise, but it is actually interesting to see these everyday real-life experiences and practices being utilized and implemented within user interfaces. After all, it all comes down to user experiences, no matter if it is during offline interactions or interactions with software interfaces. The addition of the prominent titles at the top of the titled sections adds to the users' perception of the separate information chunks, enhancing the "browsing and scanning".
158
Chapter 3
Considerations for implementation Clear, logical, and meaningful groupings are of utmost importance. Adding descriptive and prominent titles is the next important thing. Titles should be prominent, but not too intrusive—using slightly larger font (maybe even in CAPS). A different font color from the rest of the elements under the same group is a must. Using icons or a different background to enhance the visual representation is also encouraged if performed within some aesthetic standards.
The above screenshot is taken from Microsoft Windows' website, and though the overall organization is really nice and logical, the title treatment could use some help from making the headers a bit more prominent, maybe positioning them on top of a contrasting background or different font (color). Apple.com is does this slightly better:
159
Searching, Finding, and Navigating I'm sure you get the idea by now. I'd always suggest you to use the real, targeted users and to test your groupings. You can also try it yourself-take a break and then try to find a specific piece of information. Are you able to find it where you expected it to be? Were your test users as successful? Whenever possible, include users, real users, in your UX design work and testing. Jakob Nielsen argues that having just five test users can help you recognize and identify a vast majority of UX and usability challenges and issues. My personal experience confirms with that.
See also ff
Faceted navigation and classification
ff
Expanders and collapsible panels
ff
Task panes
Creating and using task panes (aka Action Panels) Task panes, also known as Action Panels, are user interface elements seen in a number of mainstream applications, both on web and desktop platforms. They are mostly used in cases when there are too many items and actions to be organized in a menu or a toolbar. They are most commonly implemented in the form of a panel with organized groups of related actions. Microsoft Office 2003 and earlier versions have been filled with task panes, though in their modern versions such as Microsoft Office 2007 and Microsoft Office 2010, ribbon is the most prominent UX pattern. Here are several examples of task panes found in today's applications:
160
Chapter 3
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
161
Searching, Finding, and Navigating This recipe should be considered a conceptual one—it describes how to implement the basic behavior for this pattern without going too much into specifics. However, as developers and designers, you are encouraged to take it a step further, especially if you see that this pattern fits for your specific needs.
How to do it... Once you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. First step is to create a very basic layout by splitting the LayoutRoot Grid control. We need to have two rows and two columns. Basically, we need to achieve a layout similar to the one shown in the following screenshot:
2. You can either manually split the LayoutRoot like that or you can just use the following piece of XAML code and paste it:
162
Chapter 3
3. This will make the top part (let's call it the header) 50 pixels tall and our left part (pane) to be 150 pixels wide, while by using the so-called star-sizing, the rest of the space will accommodate. At this point, we've laid out the foundation for our pattern. 4. From the Asset library, draw a rectangle on top of the header part. Set its Fill color to #FF4B6DAB and under the Layout section within the Properties pane make sure that the Row and Column values are set to 0, RowSpan is set to 1, and ColumnSpan is set to 2. Also, be sure that both the HorizontalAlignment and VerticalAlignment properties are set to Stretch (last icon in both rows) and that all margin values are set to 0. This will make sure that the rectangle is now occupying whole header part. 5. Now let's deal with the pane part. Draw the Grid control and be sure to name it grdTaskPane. Set its Background color to #FFBBBBBB. Under the Layout section be sure that the Row, Column, RowSpan, and ColumnSpan properties are all set to 1. Furthermore, ensure that both HorizontalAlignment and VerticalAlignment are set to Stretch (last icon in both rows) and that all margin values are set to 0. 6. Now, take the GridSplitter control from the Asset library and draw it right next to the pane part, from its left side. Its Row, RowSpan, and ColumnSpan values should be set to 1 while Column and Row should be 0. Also, HorizontalAlignment should be Right, VerticalAlignment should be set to Stretch, and all margin values should be 0. Be sure that the Height and Width properties are both set to Auto. 7. If you now hit F5 and run your project, you should be able to see something similar to the next screenshot:
163
Searching, Finding, and Navigating Play around with the GridSplitter control, you will see that you can easily change the width of the pane part. You can now see that we are mimicking the appearance of the task pane within Microsoft Office applications—our header part is mimicking the ribbon control and the pane is a placeholder for the real task pane.
How it works... The first step was to set a simple but efficient foundation that would be able to mimic the header and pane part of this pattern. By splitting the Grid named LayoutRoot, we've been able to achieve this. We've added a rectangle and made sure that it stretches through both the columns and fills in all the available header space and we've done a similar thing with the pane part. However, we used the Grid control there, as Grid is a powerful container control and can be used for hosting virtually any other Silverlight control. This Grid control, called grdTaskPane in our case, is the essence of this pattern. While we haven't gone into the customization and organization of the data and UI controls over there, we've created a nice and simple foundation. By adding GridSplitter, we've been able to introduce one more level of flexibility. What is left to be done? Of course, in the real life scenarios, you will show and hide task panes depending on the current context and application needs. You can implement that in this foundation by playing with the grdTaskPane Size and Visibility properties and programmatically linking them to the specific logic of your application. I am aware that there are third-party solutions for this pattern, but once again, the recipe here is to help you understand and perceive the challenge and under the There's more... section, you will find more information on how to design and implement this specific pattern in your real life applications.
164
Chapter 3
There's more... After reading this chapter and all these recipes (I am assuming that you have been reading them in a row), you might find yourself asking—okay, but how should I decide whether to use task pane, collapsible panels, or titled sections, because they all seem to be somewhat similar. And this is true, they are similar and that is why we have organized them in the same chapter dealing with navigations, searching, and finding. The main reason for using the task pane pattern is in those cases where we are dealing with larger numbers of related actions, and we need a somewhat richer UI to represent them and organize them. This pattern allows you to use and combine a number of different controls and combine them in different UI patterns. I will give you some ideas a bit later on.
Why would you use and implement this pattern? Arguably, people find a number of commands today in task panes which are similar or the same as the commands that are found in toolbars or menus. But in cases where you need to make your actions and options more visible and obvious, the task pane comes as a good solution. Also, the reason can be the fact that the operations and commands that you are exposing are difficult or require more than just one or two simple steps. In that case, organizing commands in an action pane makes sense, as you can create and implement rich user interfaces within them. So, it all comes down to one major point: use task panes if you need visibility and richness of interface. Although commands on action panes are always visible and presented to users, task panes themselves can be hidden and not visible at all times, so there must be a way for showing them, when either the user explicitly asks for it or when they are contextually driven.
Some implementation hints Task panes should be always visually related to the context they are being used in—which means that their appearance and their location should always be somewhat close to the object or the surface to which its commands relate. Common practice today is to set aside fairly large blocks of screen estate for task pane and to place it below or to the side of the target of the action.
165
Searching, Finding, and Navigating The next screenshot from Microsoft Office PowerPoint 2007 depicts this nicely:
What controls can you host in task panes? This was the question a client asked me during one of our UX consulting sessions on a major project. And the answer was fairly simple: (almost) anything. While titled sections are mostly used for simple, link-like commands, task panes can be utilized as real user interface containers. If you are designing a fairly complex interface and actions that are complex as well, you can use a number of different UI elements and their combinations within task panes. Take a moment again and look at the upper screenshot from the PowerPoint 2007 showing a custom animation task pane. You can see buttons, simple list, drop-downs, and other UI elements. Though you can use a variety of different controls, try to present them in a linear way. See if you can organize your workflow in that way and map it to your UI layout. If the user always performs actions in pretty much the same, linear way, organize your task pane in the same way—logical fashion is really appreciated by end users. 166
Chapter 3
Also, notice that as the task pane allows for it, you can use somewhat more freedom when it comes to labeling and marking different controls. Labels can be more descriptive and you can use multiline labels as well. However, don't push it too much. Again, the greatest thing to do is to do the usability test for your user interface with real, targeted users and discover if there are any pain points, and how can you solve them for your users.
See also ff
Titled sections
ff
Faceted navigation and classification
ff
Collapsible panels
Creating and utilizing promoted actions When dealing with user interfaces with a large number of the same or similar looking controls, there is a challenge that users will not be able to recognize them and differentiate them. This is often prominent when dealing with web forms. Most web forms today are comprised from a number of input fields, drop-downs, and at the end, in general, there are buttons for committing specific data or canceling the action. Other scenarios, which are often visible in desktop applications, are depicted in cases when toolbars are filled with commands that look all the same, and users don't get a real sense of the importance of specific controls. Implementing the promoted actions UX pattern can help users recognize and differentiate more important commands from the rest of them. A prominent example in the world of desktop applications can be noticed within popular ribbons in Microsoft Office applications. The following screenshot is from Microsoft Office Word and Excel 2007.
167
Searching, Finding, and Navigating You can see that Paste is prominently displayed because user research has shown that Paste is the command that is most likely to be used in this specific clipboard group. A good example from web interfaces the WordPress blogging engine.
In this sample, you can notice that the Publish command is more prominent than Save Draft and Reset. And one more example (also from WordPress) is on the next screenshot:
Here, you can notice that the Update Post command looks like a real button while Delete is really depreciated and looks like a much less intrusive hyperlink.
168
Chapter 3
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. This recipe is extremely simple as it uses only a small number of really simple controls. However, the main value of this specific recipe is contained within the There's more... section where you can find some ideas and practical advice related to this pattern implementation and design.
How to do it... Once you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Asset library and locate the TextBox control. Draw three of them—one above other. Make the last one the biggest, somewhat like this:
2. Now, add three TextBlock controls and position them next to the TextBox controls that you've just added. Set their Text properties to: Your name, Your e-mail, and Your message respectively. You should now have your basic form looking like this:
169
Searching, Finding, and Navigating 3. The last step now is to add two controls—one for submitting the data entered in this form and the other for canceling the entry. We will use a Button control and set its Content property to Send. Also, we will use the HyperlinkButton control and set its Content property to Cancel. Align the Button to the right and the HyperlinkButton to the left side of the form. 4. Also, set the Foreground color of the HyperlinkButton to #FF414141. 5. If you now hit F5 and start your application, it will look somewhat like this:
How it works... There is not much to explain here: we've created a really simple form with a Send and a Cancel button. We've decided to use Button for Send control and in that way, to actively promote that action. The other action, used less often, is Cancel and in order to make it less important, we've used a HyperlinkButton control, which is significantly lighter (visually speaking) than the Button control. How and when to use promoted controls and what things need to be taken into consideration is discussed in the following paragraphs, so pay close attention to it, as the implementation itself (from the technical point of view) is extremely simple.
There's more... As it was mentioned in the introduction to this recipe, a prominent action pattern is used in cases when you are dealing with a number of commands and actions looking the same or similar, therefore making it more difficult for users to make correct and fast choices. The solution is fairly simple—make the important action more prominent and do the exactly opposite for the actions that you don't need to make prominent.
170
Chapter 3
However, you should bear in mind that sometimes you want your users to stop for a while and think before executing some action. Therefore, a good rule when deciding whether to implement this pattern is to ask yourself one question: "Is there a known primary action that people will be using significantly more often than the other commands, or you would like them to use it more often?". In both cases, you have a good argument for implementing this pattern.
Some implementation hints By this point, you already understand that this specific pattern has some similarities with the pattern called "Prominent action points". A major similarity is in the fact that in both cases, for recognizing good default actions, you need to know what your users will be using in most cases. Again, a simple usability study can help a lot with this. But your job does not end there. Let's assume that you have recognized and identified prominent actions, now you are faced with the challenge—how to make them prominent. One example is to make the command visually larger and more visible by changing the colors and visual design. Be sure to consult with the visual designer if you are not it. Another idea-make the primary action in the form of button (our concrete recipe) and display secondary action using form of hyperlinks. But beware, if you do this, you will clearly send a message to the users that the button is an important command (your intention), and the link is less important (also your intention). But sometimes, users want to use exactly the command that you have set as secondary, and they might have challenges locating it if it is too hidden and too subtle. Again, do usability testing and learn from your user's behavior—that is, by far,the best thing that you can do for your users and for yourself as well! Ask Luke Wroblewski... There have been a number of discussions and research around how positioning and other changes affect a user's ability to recognize and execute proper actions. My all time favorite is from Luke Wroblewski who gives really nice results in his primary and secondary actions in web forms (http://www.lukew.com/resources/articles/ PSactions.asp). I strongly recommend you to read this article and use it in practice. The ideas, research, and results given there are something you should take into account when designing primary (prominent) and secondary actions for web forms and similar UX patterns.
171
Searching, Finding, and Navigating At the end, I will cite Luke, saying: While the primary goal of most web form designs is to get people through a form as quickly and painlessly as possible, there are situations where slowing people down is advisable. When choosing between primary and secondary actions, visual distinctions are a useful method for helping people make good choices.
See also ff
172
Prominent action points
4
Date and Time Input, Tables, and Ratings In this chapter, we will cover: ff
Date picker
ff
Calendar
ff
Time input
ff
Star-based rating
ff
Alternating row colors
Introduction This chapter deals with data input controls, primarily those related to date and time input since those data formats are somewhat specific. Fortunately, Silverlight comes with good support for these data types and implementations; design and development involving those controls is pretty straightforward. Forms design and implementation is a huge topic. Books have been written on this topic and this recipe is not intended to serve as a replacement of any kind for those books. Instead, a number of recipes in this chapter (Date picker, Calendar) will show you the basic principles regarding design and offer a number of different suggestions and ideas on how to use the existing Silverlight controls in order to help you build and design great user interfaces. Star-based rating is a relatively new pattern in modern user interface designs. Silverlight comes with the support for this interesting and yet easy-to-use control so you can find a recipe describing how to implement and use an interface featuring this cool looking control.
Date and Time Input, Tables, and Ratings When faced with a fairly large amount of data presented to you in different rows and columns, it is helpful to somehow differentiate rows and make them visually distinctive. One of the recipes in this chapter will show you how to implement this fairly simple and very practical and useful pattern. Please note that from this chapter and all the way till the end, instructions on how to add and modify properties for specific controls and related elements will be somewhat more concise compared to the previous chapters. Until now, everything has been explained in a pretty detailed way and by this point in the book it is reasonable to presume that you have developed your own fluency regarding Expression Blend.
Designing date picker interface Dealing with dates is far from simple. Different cultures, a globalized world, and fast information exchange require simple and error-prone ways to keep date formats correct and adjusted to locale and other user preferences. Silverlight and its Toolkit are now equipped with the Date Picker control, enabling you to easily pick and get date formats. This recipe shows you how to implement and design this kind of interface.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the DatePicker control. Draw two DatePicker controls and add two TextBlock controls above them with Text properties set to Start date: and End date:, respectively. Basically, you need to create a simple UI that looks like this:
174
Chapter 4
3. As this is really a simple recipe without any real coding, let's just go and hit F5 and explore the current, out-of-the-box supported features. 4. If you click on the calendar icon close to the Start date DatePicker you will see that a drop-down calendar control appears, allowing you to select the date from the calendar interface. You can see that the current date is selected and that by clicking on the header part of the calendar you can easily navigate between months or even years. This all allows for a really fast date selection mechanism. 5. Also, after you select the date, note that it will be displayed in the text field part and it will be formatted according to the local computer settings. The next picture shows you example where user has it's settings set to Croatian( Croatia). In this specific setting, dates are being formatted in the following way: dd.mm.yyyy (Date / Month / Year)
6. The same date for the users with Culture settings set to English (United States) looks like this:
7. Of course, the DatePicker control allows for some modifications. Select the DatePicker control and under the Properties pane set the SelectedDateFormat to Long. Your date representation will now look somewhat like this:
8. From the developer's point of view, having different date formats and representations might look cumbersome and difficult when it comes to handling this information. However, no matter how your date is represented it's easy to get all the required information and manipulate them. 9. For example, the following lines of code are responsible for selecting the day, month, and year and it's completely irrelevant which culture settings you might have. txtDay.Text = dtpStart.SelectedDate.Value.Day.ToString(); txtMonth.Text = dtpStart.SelectedDate.Value.Month.ToString(); txtYear.Text = dtpStart.SelectedDate.Value.Year.ToString();
175
Date and Time Input, Tables, and Ratings 10. The result might look like this:
11. Also note that there are a number of different methods available for manipulating the date elements. For example, you can use the AddMonths method and add any number of months to the current selection. This might be useful in scenarios where, for example, end date is always calculated as starting date plus one month. Simple code for that would look like this: txtMonth.Text = dtpStart.SelectedDate.Value.AddMonths(1).Month. ToString();
How it works... The DatePicker control is one of those rich controls providing you with a broad spectrum of functionalities and out-of-the-box supported features. We've added the DatePicker controls and it was easy to interact with them. Just by clicking on the calendar icon users have gained simple and familiar interface for them to select any given date. The current date (today) is clearly marked and navigation through months, years, and even decades is supported. Support for globalization and different time formats is also available. DatePicker will automatically recognize the culture settings on your computer and apply them. Also, by changing the SelectedDateFormat to Long you've been able to see that the date format can also be selected. After that, several lines of simple C# code explains how you can get values for the day, month, or year and even perform some manipulations on them that can be used in real life projects. However, this pattern lacks some more sophisticated support for continuous date range selection. This scenario is explained in the recipe dealing with the Calendar control and related user interface elements.
176
Chapter 4
There's more... As I said at the beginning of this recipe, dates come in many different forms depending on the cultures or event on the specific user settings. A good user interface will automatically adjust itself and allow users to input date in the format that is appropriate for the specific needs and depending on the specific culture. However, the simplest and probably the most error prone method is to present the users with the simple and very familiar calendar control. No matter their cultural background, it is safe to assume that everyone is familiar with the calendar metaphor and can easily select the year, month, and a date when presented with one. Date picker in Silverlight comes with a control that looks like a simple text box enabling you to type in the date in a specific format, but it also features the calendar control activated by clicking on the calendar icon. Then, the calendar drops down enabling the users to select a specific date.
The rationale behind this pattern is in the calendar metaphor, one that is practically universal and easily understandable.
Some guidelines General guidelines regarding the implementation of this specific UX pattern are fairly simple. Mark the current date on the calendar and by default display the current months. Of course, be sure to allow users to select different dates. However, you might want to limit their ability to select dates in the past depending on your particular functionality being implemented in the application itself. This specific control implementation in Silverlight is well done. There are arrows enabling you to jump backwards and forwards for months and selecting the specific date closes the calendar part and the date is then represented and shown in the text box. The specific date format being displayed depends on your locale settings and properties set for the specific control, as explained in the recipe. 177
Date and Time Input, Tables, and Ratings Please note that confident and experienced users might wish to enter dates directly into the text box part, especially if dates occur far in the past or future, so clicking through the calendar might be somewhat ineffective. Also, take into account that this specific pattern is best used with mouse-oriented users. Navigating through the calendar, though it is supported, is not quite the easiest and fastest way to get around with this control. One thing to consider is regarding the locale of your users and the display of the information on the calendar part. More on that can be found in the following recipe regarding the usage and implementation of the calendar interface itself.
See also ff
Using and implementing the calendar interface
ff
Time input
Using and implementing the calendar interface This pattern is closely related to the previously described one, but this specific implementation in this recipe goes a step further, enabling the users to select a single date or even a range between two dates. It is simply implemented with the Silverlight's Calendar control. This recipe will explain how to select a single date, how to implement contiguous date selection, and even how to deal with disjointed data selection.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl.
178
Chapter 4
2. Go to the Asset library and locate the Calendar control. Draw it on top of your artboard. Add the two TextBlock controls right below the Calendar. We will use them to show the selected date in one of them. Basically, you should be aiming for a simple UI looking like this:
3. Let's add the following code under the SelectedDatesChanged event of the Calendar control: txtSelectedDate.Text = calStart.SelectedDate.ToString();
4. With the textBlock control previously named txtSelectedDate, after you hit F5 and select any date on the Calendar control, that value should appear right below the Calendar as shown:
5. In the same way as it was possible in the recipe dealing with the DatePicker control (designing date picker interface), you can easily select Day, Month, or Year. 6. However, Calendar control comes with a rich set of other functionalities for when you need to handle more date-centered tasks. For example, several selection modes are available. 179
Date and Time Input, Tables, and Ratings 7. With the Calendar control selected, locate the SelectionMode property under the Property pane. First, set it to SingleRange and hit F5 to start the application. Click and drag to select a single date range.
8. Then, go back to the application and set the SelectionMode property to MultipleRange. Hit F5 and now use the CTRL+click to select dates on the Calendar. Note that this selection does not need to be continuous, allowing you to select any possible date pattern.
9. Also, sometimes you will need to allow users to select not the exact date, but rather to start their selection at the level of months, years, or even decades. You can set those options by changing the values of the DisplayMode property. Available values are Month (it's the default value), Year, and Decade. The following screenshot shows a case where the Decade value is used:
180
Chapter 4
10. Sometimes you will want to restrain users from selecting the specific dates. For example, if users are trying to book a flight on specific date when there are no flights available, it's a good idea to let them know that the specific date cannot be selected. 11. Following lines of code will set the January 10th 2010 as a date which cannot be selected. calStart.BlackoutDates.Add(new CalendarDateRange(new DateTime (2010,1,10)));
12. In that case, the Calendar control will look like this, and it won't be possible to select January 10, 2010 as a date:
13. Of course, it is possible to set the date range for those "blackout" dates. For example, to set the whole week from January 10 to January 16 to be blacked out, you will use the following code: calStart.BlackoutDates.Add(new CalendarDateRange(new DateTime (2010,1,10),(new DateTime (2010,1,16))));
And in that case, the Calendar control will look like this:
181
Date and Time Input, Tables, and Ratings
How it works... As you can tell just by following the recipe, Calendar controls are very versatile and feature rich. This is also where the main difference between DatePicker and Calendar control is. If you need to simply select a date then you will use DatePicker, but if you are looking for different selection mechanisms, being able to set some dates as not selectable, and a richer experience overall, then you should go for Calendar control. In this recipe it was explained how you can easily get the selected date using the SelectedDate.ToString(); method. After that, we played with the SelectionMode property and explored the default, SingleDate, allowing you to select just a single date from the Calendar. Then, we explored SingleRange, allowing you to select a date range but in a continuous manner. The last, but most flexible option was with the MultipleRangle property value, allowing you to select any data pattern by utilizing the well known CTRL+click approach. Apart from the selection modes, the next step was to explore different DisplayMode property values. As you can probably tell by the name of the property itself it is responsible for the different ways the Calendar control appears, whether it is the default Month, Year, or Decade property value. Last but not least, especially from the user experience point of view, is the ability to render specific dates or even date ranges as being not available for selection. That can be achieved by utilizing the BlackoutDates property. Please note that this property is also available for the DatePicker control itself and can be used in pretty much the same way as it was described here in this recipe.
There's more... This pattern is generally used in cases where you want to allow users to select dates from the calendar interface without forcing them to enter the date in the textual format. Furthermore, by utilizing the calendar metaphor users will be able to select more than just a single date and in this recipe it was explained how to select a date range in two forms—contiguous date selection and disjointed date selection. Though entering the information in its textual form might sometimes be faster, it is significantly more error prone.
When to use this pattern and some general guidelines Since calendars are well known to almost all users, they also feel confident using them. Therefore, utilizing this specific UX pattern is suitable for scenarios which are not really simple or too trivial.
182
Chapter 4
A general case for usage is connected with the need to enter a range across dates—either in contiguous or disjointed selection mode. A fairly simple and yet well known case is one where you want to enable your users to book a hotel. This pattern is capable of supporting a number of different scenarios—allowing user to select arrival and departure dates on the single calendar, or to use the two different calendars, the first one for the arrival and the second one for the departure date. However, in the second case, the Date Picker control (as described in previous recipe) might be a better solution. In the long run, Date Picker is a very close relative of the pattern described in this recipe. Remember, you want to make sure your users feel comfortable, safe, and confident with the user interface. They want to be sure that they have checked right dates and range. Alternatives like text input might be sometimes efficient and faster but you are risking errors. For example, a date like 12/3/2010 might mean December 3rd or March 12th depending on the current locale. With the calendar control and pattern there are no worries regarding such cases. You select the date in the same way as when you are looking at the calendar. Let's refer to our hotel room booking case. If you are using two calendars (or as suggested for this case, date pickers) be sure that after the users selects the first date (arrival) you set the date in the second part (departure date) on the next day after the arrival. That way the user will be able to easily modify the departure date and since most of the users will be staying in the hotel for a reasonable period of time, making a same-month selection is considered to be a "good default" value. Also, disabling the ability to navigate in the past and select dates from the past as an arrival or departure date is a good idea. As well as it is to check and see if user has selected departure date to occur before arrival date. Make sure that you inform your users about those scenarios or, better yet add some coding logic and prevent illogical choices right from the start. But even in that case, explain to users what has happened; they like to know what's going on and they hate it when they feel constrained. So you need to take care about that as well. Too much help and "safe measures" can actually lead to users' frustration though your sincere intention was to help them. As a rule of thumb you can rely on the fact that if your application is going to be used on an everyday basis by the same or experienced users you can probably be more flexible. And in the case that your users are novice users or ones who only use the solution quite rarely, then imposing more failsafe mechanisms is probably a good idea. Again, conduct a usability test and even before you do that get to know your users, their needs, habits, and experiences. It's the ultimate resource when designing and implementing user interfaces of any kind. Of course, this pattern can be used for the past events as well. For example, if you are designing an email client and you want to filter all your e-mails received between two dates in the past you will also utilize this pattern. Be sure, in that case, to enable the date selection for the past in your Calendar control.
183
Date and Time Input, Tables, and Ratings
See also ff
Date picker
ff
Time input
Designing time input interface In its nature this pattern is almost the same as the Date Picker and Calendar pattern and virtually everything in those recipes can be applied in this recipe. In fact, time input controls and interface are in most cases combined with the two previously mentioned patterns, and provide common date and time input interfaces.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the TimePicker control. Add two TimePicker controls and several TextBlock controls. Set their Text properties to look exactly as in the following screenshot:
3. Set the Name of the first TimePicker (Arrival) to tmrArrival and the second one to tmrDeparture. Also, set the names for the TextBlock controls under Actual culture and Forced culture to txtActual and txtForced.
184
Chapter 4
4. With the tmrDeparture selected set the Culture property to, let's say English (United States) or to any other available culture other than your own computer settings. The idea here is to show how TimePicker controls are being affected by the differences in cultures. 5. Now select the LayoutRoot and go to the Events pane. Add a new event handler for the Loaded event. You can do that just by double-clicking the empty field next to the Loaded event label. New event handler code and a placeholder will be generated. 6. It should look like this after you add all the required code: private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e) { txtActual.Text = tmrArrival.ActualCulture.EnglishName; txtForced.Text = tmrDeparture.Culture.EnglishName; }
7. If you now hit F5 you will be able to interact with your interface. Set different timings in both TimePickers and you will be able to see how differently they are being rendered, depending on the culture settings.
8. There are several out-of-the-box supported functionalities. You can go through them by reading the How it works... section.
How it works... Since most of the desired features are implemented and supported within the DatePicker control itself, it's also simple to understand how this recipe works. We've created a simple UI that allows users to select two dates—one for arrival and the other for departure. Also, we've (intentionally) selected two different cultures so we can investigate different date formatting abilities and globalization support. First, the TimePicker control is time formatted according to current culture (one that is based on users' settings) and second one was "forced" by setting the Culture property. The code snippet shown in the recipe is doing just one thing—when your application loads it is populating specific TextBlock controls with the names of selected cultures. 185
Date and Time Input, Tables, and Ratings Apart from these, there are a number of different supported features, and here is the brief overview for some of the most important ones.
Features rundown If you want to select the current time then just click on the empty TimePicker field and you will see a small pop-up box appear allowing you to select the current time.
Apart from selecting the time value from the drop down list (after you click on a clock icon), you can just type in the time in free form, let's say: 1234 will be rendered as 12:34. If you type a value like 923a then it will be recognized as 9:23 A.M. if your culture is set to one that supports AM / PM notation. A little pop-up box will even follow your entries as you type and try to guess what you are typing in:
Cycling through different values is also really simple. Just position your mouse cursor on hours and then click the up-down buttons and you will cycle through values. The same holds true for minutes, seconds, and AM/PM marks. Talking about the seconds there are a number of different time formats supported. You can set them by setting up the Format property under the TimeInput section. Try setting it to hh:mm:ss to display seconds as well.
There's more... This pattern is generally used in cases where you want to allow users to enter time from the predefined interface without forcing them to enter it in the textual format. Time formats suffer the same problems as specific date formats. Different cultures have different time input formats. Therefore, by utilizing the TimePicker control you will enable users to select dates from a predefined list of available dates. 186
Chapter 4
Some guidelines Offer the users time formats based on their current location. For example if your users are from the USA then usage of the A.M. and P.M. elements is necessary while users from, let's say, Croatia will differentiate 7:00 A.M. and P.M. by displaying them as 7:00 (in the morning) or 19:00 (in the evenings). Silverlight offers great support for different cultures and time format styles so you should use those and enhance your user's experience. Regarding the time selection be sure to allow users to select different times from the drop down list as well as you should be able to allow them to manually type in the time. However, as it was the case with the date selection you might want to limit their ability to select time periods in the past. Again, this will depend on your particular functionality being implemented in the application itself. Be sure to allow users to quickly enter the current time. Recipe shows you how to do that. Also, once the users have entered or selected a specific time, be sure to allow them to change and adjust their selection. Common practice follows the fairly well-known interaction model where users position their mouse cursor on the hour's part, click, and then by using up and down buttons they can cycle through hours. The same holds true for the minutes—users can click on the minute's part and cycle through them. You should think about the amount of hours or minutes being changed by a single click on those buttons. Sometimes you want to limit all minute selections to be in brackets of five minutes—00, 05, 10, 15, and so on—while sometimes you want to make sure that your users can select any time like 12:34:56. As it was the case with the DatePicker, experienced users will generally appreciate the ability and freedom to enter the time selections manually. That functionally is supported out-of-thebox, but will need to take care with some validations and prevent users from entering bogus data. However, if your user wants to enter 12:34:56, then they can just go into the TimePicker control and type 123456 and depending on the locale / culture settings this data will be automatically parsed and formatted in the right way. (At least for the most part to be honest, and that's the reason you should be careful about entering the time and date since those parts of the application can be critical. You definitely don't want your users to be angry and frustrated for booking their hotel stay or flight at wrong time and date because of your poor interface).
See also ff
Date picker
ff
Calendar
187
Date and Time Input, Tables, and Ratings
Implementing star-based rating With the Web 2.0 advent, but even before that, users wanted to have a simple and easy way to leave their feedback on a website. Movie or vine review, article or DVD users like to rate and grade content. A typical star-based rating implementation looks like this one from the CNET's Download website:
A general guideline for implementing this specific UX pattern is the social aspect of the website. Basically, if you are dealing with a consumer goods website or more importantly, if a site has a social and sharing aspect to it then implementation of this pattern is justified and good choice.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the Rating control. This control is the central part of this recipe though number of other controls is also being used. Those are primarily TextBlock controls and one Rectangle control. 3. As always, you can see the full example in the code but the basic idea is to build a simple user interface looking like this:
188
Chapter 4
4. As you can see, we are mimicking a typical case where a user can rate a specific item such as a book, a DVD, or something else. A user is invited to click on the stars and rate the item. 5. It is recommended that by default, the rating value is always set to 0. Also, the TextBlock control containing the information about the average rating and number of votes should be (in a real life case) updated to reflect the actual value and rating. 6. Select the Rating control and under the Properties pane look at the following properties and set them as follows: Background: set it to White (RGB: 255/255/255) Foreground: set it to some tone of Yellow, let's say RGB: 255/197/0 SelectionMode: set it to Continuous Value: set it to 0 ItemCount: set it to 5 7. If you now hit F5 and position your mouse cursor over the Rating control you will notice that stars are change their colors and reflect the current user's choice. You can click on the star and later can change your choice. 8. In order to read and set the values for average ratings you'll need to programmatically deal with the property Value. 9. A good idea is to update the value every time user changes the Rating control's Value property. You can read or set that property in C# like this: rtnRating.Value = 0.5; 189
Date and Time Input, Tables, and Ratings This will set the value to 50 percent. Meaning, if you have five stars visible (you set that number via the ItemCount property) then only 50 percent of them will be marked 2.5. Allowed values are from 0 to 1, where 0 is 0 percent and 1 is 100 percent.
How it works... This is a really simple recipe and the Rating control is pretty straightforward itself. Also, concrete guidelines and advices for implementation are listed and well explained under the There's more section. However, let's explore some more interesting parts. The Rating control supports two basic modes of functioning determined by the value of the SelectionMode property. In this recipe SelectionMode has been set to Continuous enabling users to select any given value for 1 to 5 (or some other value set by ItemCount). However, if you want to select a single value then you can set the SelectionMode property to Individual. In that case, your control in action would look something like this:
Note that even in this case, the Value property has been set to 1 (100 percent) but this value is within the context of a "single star" since we are in the "individual" mode now. Also, though it's not part of this book, by editing the Rating control's control template you would be able to change star shapes to different objects.
There's more... Often users need a way to leave a quick and simple feedback or their opinion on a specific item or an object. While you can always implement a rich form interface and allow them to write their review, a very popular solution is to implement the "star-rating" UX pattern. This pattern, as described in this recipe, allows users to rate a specific item without breaking their current flow of actions or confusing them. This pattern is very popular these days all around the Web, and it is most commonly used in combination with product reviews and similar content. Also, one of the nice things about this pattern is its light appearance and simple user interaction model. 190
Chapter 4
Some guidelines for design and implementation The star rating pattern generally involves stars but other icons and graphics elements are also used sometimes. Be sure that they are clickable and that they always change their color on rollover. That serves the purpose to display and clearly points out that users are able to click on those elements. When users arrive for the first time on the website, the default state should be that all stars are "blank". Good practice, according to numerous sources, is to include an invitation such as text stating something like Click to rate!, or something similar in the tone and meaning. While users are moving the mouse cursor above the stars they should be automatically updated and change their rating status, most likely through a color change indicating the current user's choice. Also, you might consider providing users with the contextual descriptions for specific rate, let's say from Bad to Excellent or Great when all stars have been filled-in. The interaction part of this design is of average rating. Every time a user rates an item, that grad should be added to the previously added ones and averaged over the number of all grades received. This value (average rating) should be displayed near the rating stars, but somewhat separate from them. A good practice is to allow users to be able to change their rating later if they decide to do so. However, that might be a bit more complex and involve user authentication, saving and remembering user's rates and other elements.
Designing list views with alternating row colors Research shows that, when presented with large amounts of data displayed in rows, users find it difficult to visually concentrate and connect all the information pieces in a given row. The solution is fairly simple—alternate the background color of rows in your controls and make it easier for users to locate and differentiate each row.
191
Date and Time Input, Tables, and Ratings A number of websites are already using this simple and yet so useful pattern. Here is the example from the Google Finance website:
You can see that the rows have alternate colors making it easy to follow pieces of information presented in this table. However, Google Finance is inconsistent with respect to the alternating coloring, so finding tables looking like the next one is common as well:
But note that even in this case there are grey lines delimiting rows, making it easier to differentiate between rows.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application, make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it... 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Go to the Asset library and locate the DataGrid control. Draw it on top of your artboard. 192
Chapter 4
3. We need some data so we can populate our DataGrid control. Starting from Expression Blend 3, you can use the automatic data generation feature and populate the controls with the date and use it directly within the application. 4. Go to the Data tab. If it is not visible in the current configuration then go to the Window menu and turn on the Data pane. Click on the first icon reading Add Sample Data Source and from the drop down menu select Define New Sample Data…
5. A new dialog box will open asking you for the Data source name. Just leave it to its default value and be sure that Enable sample data when application is running option is checked. Hit OK when you are done. 6. Now, you should be able to see several items under the Data pane. Click on the Collection and drag it over with your mouse and release it when you are positioned above the DataGrid control.
7. Your DataGrid control will now be populated with some sample data elements. You can always edit this data by clicking on the Edit sample values next to the Collection item under the Data pane. 8. As you will see, DataGrid features the alternating row coloring scheme by default, but let's see how you can change those values and make them suit your user interface better. 9. Select the DataGrid control and under the Properties pane go to the Brushes section. Note the AlternatingRowBackgroud item. Change its color to red (RGB: 228 / 42 / 42). Also, be sure that the Alpha value (A) is set to 100%.
193
Date and Time Input, Tables, and Ratings 10. The next step is to define the RowBackground color. Click on it and set its value to blue (RGB: 0/90/180) and also set the Alpha value to 100%. You should now be able to see your DataGrid with rows colored in blue and red:
11. Of course, you will not leave these colors to be red and blue; it was only for demonstration purposes. You will find more practical guidelines under the There's more section later in this recipe.
How it works... DataGrid is a common control in Silverlight, and it's extremely rich in terms of both functionality and ability to be customized. It is used mostly in cases where you need to present data in a table-like interface. DataGrid is a great candidate for this recipe and UX pattern. After you've added the DataGrid control to the artboard the next step is to generate sample data in order to populate the DataGrid control. Of course, you are able to add real, live data source, XML file, for example. But from Expression Blend version 3 you can use the sample data generator and populate the number of different controls with the sample data. Of course, you can edit and customize this data in many different ways, but for the purposes of this recipe we've just created a simple data source and connected it to the DataGrid control. New rows have been generated automatically and filled with data. The step is to modify Brushes. Setting the RowBackground and AlternatingRowBackground values for those two Brushes is the key part of this recipe since those two Brushes, as their names suggest, are responsible for the coloring alternation.
194
Chapter 4
Refer to the next section for more information about specific guidelines and how to set and make good color choices for row colors.
There's more... When presented with the information in rows, people usually have problems visually connecting those. A simple and very effective solution in this case is to use different colors for neighboring rows, a so-called alternating coloring pattern. There are several cases when implementation of this pattern makes most sense. In order to make the most of it, consider using it in situations where users will be presented with the table containing enough rows to make the usage of the entire table at once uncomfortable. It's hard to give an exact number of rows since this depends on typography and information type, but I'd generally suggest that if you are going over 10 rows you should consider alternating coloring. Also, this pattern makes most sense if you are dealing with three or more columns in the table. And some resources are citing that this pattern is actually good if you want to remove the visual clutter that appears if you are using border lines for each row to visually separate them. Again, I'd argue that this depends on the actual implementations of the border lines, their color, thickness, and many other attributes.
Roots from the real life situations Do you remember where you have seen alternating row coloring in the real-life? Pretty much in the same as file folders from the office cabinets have found their way into the graphical user interfaces, alternating row coloring followed the same path. Green bar reports are really iconic and have been around since the earliest days of the computer industry. Perforated on both sides with the light green and white rows they are alive and well as an UX pattern described in this recipe. Green bar reports and today's alternating coloring pattern share the same purpose—making it easy for users to look, follow, and use tables and the data present within them.
A few design guidelines As it was pointed out earlier in this recipe, you should not implement this pattern if you are dealing with a small number of rows. In this case alternating coloring might have just the opposite, distracting effect, as my own usability research has shown. Also, purely from designer's point of view it is a bad idea to combine grid and column lines with alternating coloring. This is exactly what some table predefined designs within Microsoft Office Word or Excel 2007 come with and it certainly creates tremendous visual clutter.
195
Date and Time Input, Tables, and Ratings Use the proper colors and you will achieve great results with respect to the row differentiation. General colors advice would be to stick with the nonintrusive colors (red and blue are a really bad combination; yellow and purple is probably even worse). Good practice is to make one of the colors exactly the same as your UI background—in most cases that would be white. Stick with the pairs of low-saturation colors that still contrast well. Blue and white, beige and white, light green and white, or two combos of gray shades might work very well. Be sure to make the text on the top of both dark enough so its readability is not affected by the color choice.
196
5
Maps, Pop-up Windows, and Escaping the Browser In this chapter, we will cover: ff
Pop-up window
ff
Responsive UI enabling
ff
Adding maps to Silverlight applications
ff
Full-screen Silverlight applications
ff
Out-of-browser experiences
Introduction In this chapter, a number of different concepts are being introduced. Even from the first days of the Web in its current form, designers and developers have been looking for a way to break from fixed, single-window experiences. We all remember the pop-up hell, which still rules large portions of today's web. And while pop-ups are extremely annoying when used in inappropriate scenarios, their proper usage can lead to really good and high-quality experiences. The first recipe in this chapter will give you ideas and approaches on how to utilize this pattern directly within Silverlight and without frustrating your end users.
Maps, Pop-up Windows, and Escaping the Browser The complexity of UI in general (or specific UI elements for that matter) can be significantly reduced by a number of techniques. One of them is both reducing the visual complexity, and is also helping users and guiding them through the UI is called responsive UI enabling. Using this approach, different parts of the UI are becoming accessible depending on the user's previous choices. This pattern is covered in the second recipe of this chapter. Mapping (geo)location, and maps in general, is becoming one of the major trends these days on the Web. Applications such as Foursquare and Gowalla have pioneered this trend and today, it is becoming more and more useful. Adding Bing maps to your Silverlight application and related mapping patterns are explained as the third recipe in this chapter. Often, you need to utilize all the screen real estate available to you. Even if you maximize your browser window you will still be limited with the different toolbars, title bars, and status bars. This recipe will show you how to show your Silverlight applications in full screen and utilize all the available space. The final recipe will help us escape from a browser. Though Silverlight is primarily a web-based technology, since version 3 it supports the so-called out-of-browser experiences. These basically allow you to take your Silverlight application and install it on an end user's computer (like any other application). Then, you can update it at any moment and support a number of different scenarios. Is there a better way to conclude this chapter by escaping from the browser itself?
Implementing pop-up window (modal dialogs) in Silverlight Pop-up windows are usually connected with ads, spam, and a bad user experience. They are intrusive, aggressive, and all but user friendly. However, often there is a justified need for breaking from the single-window experience and providing users with "pop-ups". From its third incarnation, Silverlight provides a special window type called ChildWindow, enabling you to do exactly that—launch a new window from your application. This scenario can be utilized in a number of different forms—either in cases where you want to launch a simple dialog or a typical message box. In either case, ChildWindow is the way to go.
198
Chapter 5
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it – adding ChildWindow After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to File | New item... and from the New Item dialog, select ChildWindow and then click on OK. This will add the ChildWindow1.xaml file to your application. 2. Now add the regular Button control on top of your MainWindow.xaml design surface. We will use this button to launch a ChildWindow when the user clicks on it. 3. With the Button control selected, go to the Events pane under the Properties pane and double-click on the Click event. A code-behind file will open allowing you to add interaction logic. 4. We will keep things simple with this: for now, we only want to launch our ChildWindow. All you need to do is to add the following two lines of code: ChildWindow1 dlg = new ChildWindow1(); dlg.Show();
5. If you now press F5 and then click on the button, your new ChildWindow will appear. 6. Of course, you can add different controls to your ChildWindow object to make it look the way you want and to fulfill the role within your application. 7. One thing to note—you are not able to select anything behind ChildWindow while it is launched; it waits for the user's action or dismissal. This is the so-called modal window type. You can also notice that the background is now grayed, though you can change that color, as it will be explained a little bit later.
199
Maps, Pop-up Windows, and Escaping the Browser
How to do it – changing the background color of ChildWindow As you've noticed from the previous recipe, when you launch the ChildWindow, the main window's background changes its color. You can modify a number of properties that are related to that color. 1. Go to the design view of your ChildWindow1.xaml object and select the ChildWindow object from the Objects and timeline pane. After that, navigate to the Properties pane. Under the Brushes section, you will notice the OverlayBrush element. Select it and then from the color picker tool select any color (you can even go with a gradient if you want to).
2. If you now press F5 and launch the ChildWindow by clicking on the Button, you will notice that the background color now reflects your choice—the one made within the color picker tool. 3. You can also change the opacity by changing the value of the alpha channel (marked with the capital letter A and set to 50% by default).
200
Chapter 5
How to do it – removing a close button from ChildWindow One of the common tasks is how to remove a Close button from a ChildWindow object—it is really simple to do. 1. With your ChildWindow selected, go to the Properties pane and locate the Miscellaneous section. 2. Take a look at the HasCloseButton property and be sure that it is unchecked if you want to have your ChildWindow appear without the close (X) button in the top-right corner.
How to do it – positioning ChildWindow By default, ChildWindow will position itself in the center of the screen. We can, however, change that: 1. Select your ChildWindow and under the Properties pane, locate the Layout section. Notice that the HorizontalAlignment and VerticalAlignment values have been both set to Center by default. This will always position your ChildWindow in the center of the screen. 2. Set VerticalAlignment to Top and then under the Margin values, set the Top Margin value to 35. 3. If you now go and press F5 to start your project and launch a ChildWindow, you will notice that it is not centered anymore but it's rather positioned exactly 35 pixels from the top. 4. You can use margin values to play around and set the position of the ChildWindow object the way you want.
How it works... In the previous several recipes, you've been able to learn how to add, modify, and reposition ChildWindow. As you now know, ChildWindow is a new object available to you from Silverlight 3. It can be used in typical UX scenarios where modal windows or dialogs are used. You add it to your project in the same way as you'd do with a regular Page or other available objects and call it through the code in the same way like you'd do with the WPF Windows or Silverlight pages. In our really simple scenario, we've added a Button control and added some code to the Click event handler. 201
Maps, Pop-up Windows, and Escaping the Browser After we added ChildWindow, the next step was to change several properties—the first one being the overlay color. Today, often you can notice those gray-looking backgrounds that are supposed to bring your focus and attention towards the available dialog. You are not able to click anywhere else before dismissing the modal dialog window, either by committing some action or by clicking on the Close button. The next recipe was dealing with the close (X) button and here, it was demonstrated how easy it is to remove the Close button just by setting the HasCloseButton property. The last recipe was dealing with the position of ChildWindow. By default, as it was explained in the recipe itself, ChildWindow will position itself in the center of the screen. However, by changing the HorizontalAlignment and VerticalAlignment properties and furthermore, by setting the different values of Margin properties you can modify and change the desired startup position of your ChildWindow.
There's more... Before we lay out some guidelines and ideas for proper usage and considerations, let's be sure that we all understand the concept of the so-called modal dialogs of which ChildWindow is a typical example. Generally speaking, a modal window is always a child window that requires users' interaction before it can be dismissed or closed. It is essentially every window that prevents you from continuing your operations unless you dismiss it somehow. In UX and UI lingo, this type of windows is often called a modal window, a modal dialog, or in later time, and especially in the context of the Web—a lightbox. Some UX practitioners argue (author of these lines included) that lightbox is a term that should be used only for those cases where a modal dialog is displayed against the darker (commonly grayed) background. In those cases, lightbox brings the users' attention and focus to the dialog itself thus eliminating the users' confusion and clicking around, thinking that they are able to continue their operations without dismissing the currently open window.
Typical usage scenario and case for lightboxes Modal windows are used in a number of different scenarios, both on the Web and on typical desktop applications. But some of those scenarios are criticized by usability experts as they have proven to be ineffective. You should use modal dialogs with caution and only in cases where they are critically needed and when you need to communicate to the end user and expect feedback and interaction from them before moving on. This is most often recognized in one-off tasks, which, as a rule, do require completion before continuing.
202
Chapter 5
One of the scenarios is usage of modal dialogs to draw attention to vital information pieces, but some experts (Joel Spolsky and especially Aza Raskin from "A List Part" with the "Never Use a Warning When you Mean Undo" article come to my mind) have criticized this approach. However, if we are about to stick to what other UX and usability practitioners have to say, then I'll cite Jakob Nielsen stating back then in 2008 that lightbox was the interaction design technique of the year. He was praising the fact that lightboxes do have the ability to draw the users' attention to them and their message by dimming the background and making the lightbox the only bright part on the screen. There is no way to miss that, right? Nielsen also outlines some of the downsides of this interaction technique, and you should be aware of them as well. Downsides We can all agree with the fact that lightbox (or modal dialog in general) is a pretty aggressive pattern that is literally stopping you from whatever you have been working on and demands all your attention. This means that often it breaks your current workflow and from a psychological point of view, it can cause a rather expensive brain context change. So, a rule of thumb would be to use them in rare situations—only when you need to communicate high-priority messages and demand critical actions from your users. Some exceptions are here known—for example, browsing the image galleries and similar scenarios where you know that users will continue using the lightbox presented to them for a while. Special attention needs to be given to the following scenario types. Imagine you are launching a Search or Find dialog in your web page and that you are using lightbox. You enter a search string and click on the Find button. In the background, you can see the text being searched for but you can't for example scroll the document underneath the dialog or employ a typical copypaste scenario while your lightbox is displayed. The scenario that I've just described was actually present in Google Docs while it was very early in the development cycle. Today, Google Docs have dropped this pattern and opted for something different: they position their tools for search or replace on top of the document, similar to the following screenshot:
203
Maps, Pop-up Windows, and Escaping the Browser
Context and position Questions of context and position with regards to modal dialogs and lightboxes are fairly complex matters. Due to the form of this book, we can't really go too deep in discussion, but some ideas can be shared. For example, sometimes it makes sense to position modal dialogs near the point where they are contextually relevant, that is, if you click on a button which is positioned in the top-left corner of the main application window, it might make sense to show the ChildWindow close to that button if information is contextually relevant and privileged. In that case, you need to take care of the position and potentially the chance for obscuring the relevant screen parts. A good approach is to place the ChildWindow out of the way (real-life experience and common sense suggest offsetting the object's position down and to the right) so that the button (or any other element of invocation) isn't covered by the ChildWindow.
See also ff
Window management and positioning
Designing responsive enabling user interface As UI and UX designers, we are often faced with the challenge of how to add all of the controls and commands that are needed but, at the same time, keep the user interface clean and easy to grasp. You can probably recall a number of different poorly designed property dialogs and pages cluttered with controls without a clear starting point or clear sense on how to proceed. The main problem can be summarized in a statement that in such interfaces, too much attention is being drawn to the information that is most likely unnecessary at the moment and, as such, can seriously distract users. However, a really simple solution exists and it will be described in this recipe and explained under the There's more... section, as always.
Getting ready Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK. Please note that the ideas and methods described for Silverlight solutions can be applied to Windows Presentation Foundation (WPF) solutions as well.
204
Chapter 5
How to do it... After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. We will create a simple dummy page with several different controls on it. Basically, we want to achieve the following look:
2. As you can see from the previous screenshot, you will need to add the following controls and set their properties like this: Control type
Name
Property and value
RadioButton
rdbAutoDetect
Width=Auto Height=Auto Foreground = #FF000000 Content=Auto-detect settings IsChecked= True IsEnabled=True
RadioButton
rdbManual
Width=Auto Height=Auto Foreground = #FF000000 Content=Manual configuration IsChecked= False IsEnabled=True
Label
lblProxy
Width=Auto Height=Auto Foreground = #FF727272 Content=HTTP Proxy:
205
Maps, Pop-up Windows, and Escaping the Browser Control type
Name
Property and value
TextBlock
txtProxy
Width=157 Height=Auto IsEnabled=False Text: NONE
Label
lblPort
Width=Auto Height=Auto Foreground = #FF727272 Content=Port:
TextBlock
txtPort
Width=69 Height=Auto IsEnabled=False Text: NONE
3. Arrange all these controls like they look in the screenshot under the first step in this section. The idea here is to demonstrate how to responsively enable or disable parts of user interface. We will now add some code and create event handlers, and the logic will be explained under the How it works... section. 4. Click on the rdbManual control and under the Properties tab locate the Events button and click on it. After that, double-click on the box near the Checked event and the code editor will appear. Add the following code: lblProxy.IsEnabled = true; lblPort.IsEnabled = true; txtProxy.IsEnabled = true; txtPort.IsEnabled = true; lblProxy.Foreground = new SolidColorBrush(Color.FromArgb(255,0,0,0)); lblPort.Foreground = new SolidColorBrush(Color.FromArgb(255,0,0,0));
5. Follow the same procedure and again, with the rdbManual control selected, doubleclick the field near the Unchecked field and add the following code: lblProxy.IsEnabled = false; lblPort.IsEnabled = false; txtProxy.IsEnabled = false; txtPort.IsEnabled = false; 206
Chapter 5 lblProxy.Foreground = new SolidColorBrush(Color.FromArgb( 255, 114, 114, 114)); lblPort.Foreground = new SolidColorBrush(Color.FromArgb( 255, 114, 114, 114));
6. Press F5 now to run your application. Try checking the Manual configuration and you will notice that the HTTP Proxy and Port fields are now accessible. If you check the Auto-detect settings radio button again, fields will become inaccessible again.
How it works... We have created a simple user interface that allows users to either rely on an auto-detection process or to enter the required data manually. By default, the Auto-detect settings radio button is checked, rendering the HTTP Proxy and Port labels and fields inaccessible (disabled). If the user decides to manually enter the required information, it will check the Manual configuration radio button and the HTTP Proxy and Port labels and fields will now become enabled allowing you to enter values. If you select the Auto-detect settings again, these fields will again become disabled. This is a fairly commonly used and a well-known pattern. In order to make it work under this Silverlight-based scenario, we need to take care of several things. Radio buttons allow only a single choice, so that the interaction is already in place and we don't need to think about it too much. We just need to take care of two events—what happens when a specific radio button is checked and what happens when it is unchecked.
207
Maps, Pop-up Windows, and Escaping the Browser As you can see in the recipe itself, two event handlers have been defined. The first one is dealing with the case where our rdbManual control gets selected. In that case, through the code, we will enable parts of UI and set the Label control's color to black. But if the user clicks on the Auto-detect settings radio button again, then the Unchecked event will get triggered on the rdbManual control (remember, only one radio button can be selected at a time, so if you select the first one, second one will get disabled automatically), and the code that has been added to the Unchecked event will be executed. The code is pretty much self-explanatory (we are just changing the IsEnabled property values), but there is a part where we are playing with the colors, and here is why. If you set the Label control's IsEnabled property value to False, the color will still be the same (black). So, if you want to make it resemble the rest of the user interface when it is rendered as disabled (gray tones), then you need to change the color through the code. That's why we used the following lines of code to make it gray: lblProxy.Foreground = new SolidColorBrush(Color.FromArgb( 255, 114, 114, 114)); lblPort.Foreground = new SolidColorBrush(Color.FromArgb( 255, 114, 114, 114));
And then to revert it to black, it is enabled again: lblProxy.Foreground = new SolidColorBrush(Color.FromArgb(255,0,0,0)); lblPort.Foreground = new SolidColorBrush(Color.FromArgb(255,0,0,0));
What is FromArgb? Color.FromArgb is a method that enables us to create a color structure from the four ARGB components (Alpha, Red, Green, and Blue, hence, the ARGB values). Values for each component can be from 0 to 255, as you'd expect from your previous RGB experiences.
There's more... Usually this pattern is implemented by showing all the UI to the end users but enabling only those UI parts that the users might be interacting with at the start. Depending on a user's progress or selections, we enable or disable other UI parts. Be sure to clearly mark and identify those parts of the UI that have been disabled by treating them visually—graying out the areas or font colors and utilizing the similar techniques available. What is the main benefit that is being achieved by using this pattern? Without question, there are at least two major reasons for using this pattern in a given context. Firstly, it will enable users to see all of the options available to them before they actually make any choice, and secondly, it will help them stay focused on the only options that are available to them at a given moment. 208
Chapter 5
However, despite the fact that implementation of this pattern seems fairly simple and easy, it is necessary that you pay a lot of attention to the development and code logic because a user's ability to execute and perform some tasks is directly related to the availability of the options to them. So, be sure that users are always in control, but try and help them to stay focused on their tasks or mission, if I may put it that way.
Single most important fact here—context! No matter how you are approaching the implementation of this pattern (either from strictly the code and development side of the spectrum or from the interaction design and information architecture arena), context is relevant here. Remember from the introduction to this recipe: "You can probably recall a number of different poorly designed property dialogs and pages cluttered with controls without a clear starting point or a clear sense of how to proceed. The main problem can be summarized in a statement that in such interfaces, too much attention is being drawn to the information that is most likely unnecessary at the moment and, as such, can seriously distract users." Your task here is to help users understand the overall idea and to help them stay focused, based on the context they are dealing with. May that be the point of inspiration for you when you are designing user interfaces in general, not just for this particular pattern.
See also ff
Progressive disclosure—showing additional controls on demand
Adding maps to Silverlight applications Adding support for maps and mapping capabilities in applications is becoming a major trend these days. All started with Google Earth and Microsoft Virtual Earth, and today, a number of social networks are supporting or even concentrating around Geolocation services and related metaphors. Gowalla, Foursquare, even geotagged Twitter tweets, and imagery on Flickr—maps are here and they are here to stay. Adding mapping support to your Silverlight applications and embracing that kind of user experiences is now fairly simple; thanks to the specially made control that supports this kind of scenario. In this recipe, you will be able to learn how to add a simple map, and change some of the properties, and you will get resources to help you get started with the Bing Maps Silverlight control.
209
Maps, Pop-up Windows, and Escaping the Browser
Getting ready Before you start, you will need to obtain a Bing Maps key to be able to authenticate your application. Because this key is private, this recipe does not contain the full source code with the key due to licensing constraints. However, I've provided you with all of the samples, the source code, and the resources for the online testing ground. All you need to do is to add your own key in the XAML code, and I've marked those locations clearly for you. You can obtain the Bing Maps key by going to https://www.bingmapsportal.com/ and creating your Bing Maps Developer account. Click on the Create a Bing Maps Account link and sign in using your Windows Live ID. (In case you don't have your Windows Live ID, you can get it at https://www.bingmapsportal.com/SignIn/Logon.) After you follow the required steps and enter the required information, you will get your key. You will need to click on Create or View Bing Maps keys to get them. Please note that you can have up to five Bing Maps keys. Once you have obtained your Bing Maps key, you are ready for the next step—getting and installing the Bing Maps Silverlight control. The best way to get the most recent version is to go to http://www.microsoft.com/downloads and enter the search query "Bing Maps Silverlight Control". Download and install the Bing Maps Silverlight control. You are now ready to start developing and using the Bing Maps in your Silverlight project. Start your Expression Blend 4 and then select New project... From the dialog that appears select Silverlight and then Silverlight Application. Make sure that Language is set to C# and Version is 4.0. At the end hit OK.
How to do it – adding Bing Maps Silverlight control After you have created your new project, under the Objects and Timeline pane, you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 1. Go to the Project pane and right-click on the References folder. Select Add Reference… from the drop-down menu and navigate to the location where you have installed your Bing Maps SDK. You will need to find two files within the Libraries folder: Microsoft.Maps.MapControl.Common.dll and Microsoft.Maps.MapControl. dll. After you add resources, your References folder should look something like this:
210
Chapter 5
2. If you now go to the Assets library and look for Map, you will find the control. Select it and draw it on top of your design surface. It should look like this:
211
Maps, Pop-up Windows, and Escaping the Browser 3. If you now press F5, your application will start but you will be asked for credentials.
4. This is the point where you will need your developer key, which you obtained earlier by following the instructions in this recipe. 5. Return to the XAML view in your Expression Blend and locate the Map control within your XAML code. You need to enter your key as a value for CredentialsProvider. This is how the specific code will look: <Microsoft_Maps_MapControl:Map CredentialsProvider= "Enter Your Key Here"/>
6. After you enter your key and start your application, you won't see the notification warning that you need to enter your key. Now you are ready to start using the Bing Maps control completely in your solutions.
How to do it – changing map modes with XAML Taking off from the last step in the previous recipe, this recipe will show you how to change the map mode directly in XAML. 1. Locate your map definition in the XAML code and add the Mode attribute. You will notice that IntelliSense will offer you all of the available choices. We will set the map mode to Aerial like this: <Microsoft_Maps_MapControl:Map Mode="Aerial " CredentialsProvider="Enter Your Key Here" />
2. You will notice that your map looks different right away in your Blend. You can play with other available modes (Aerial, AerialWithLabels, Road) within you map.
How to do it – changing map modes with C# The previous recipe showed you how to change the map modes using the XAML code. This recipe will show you how to do exactly the same but this time, you will use C# in the code-behind to achieve the same result.
212
Chapter 5
1. Add the following line of code to your C# code-behind file right after the other using statements: using Microsoft.Maps.MapControl;
2. Taking off from the previous recipe, draw a single Button control on top of your design surface. You can easily draw it on top of your Map control. 3. Call the Button btnAerialWithLabels and set its Content property to Aerial With Labels. Be sure to call your Map control mapWorld so that you can reference it easily later in the code. 4. Select the Events button and double-click on the Click field. We want to generate an event-handler and add some code that will be executed when the user clicks on the Button. 5. Add the following lines of the code: AerialMode mm = new AerialMode(); mm.Labels = true; mapWorld.Mode = mm;
6. If you now press F5 and click on the Aerial With Labels button, your map will be shown in that mode. 7. You can try experimenting by clicking on other map modes using the UI controls provided with the map, but every time you click on your button, the map will be shown in AerialWithLabels mode.
213
Maps, Pop-up Windows, and Escaping the Browser
How to do it – navigating to a specific location (Dubrovnik, Croatia) Often, you will want to provide your users with the starting screen where the map is focused on a specific location. This recipe will show you how to do exactly that: 1. The same as you did in the previous recipe: draw another Button on the map. Call that Button btnDubrovnik and set its Content property to Go to Dubrovnik. Click on the Events button on your Properties pane and double-click on the field near it, so that it will generate place for new code. 2. Add the following code: Location center = new Location(42.64078,18.10913); double zoomLevel = 16; mapWorld.SetView(center, zoomLevel);
3. Press F5 and start your application. Click on the Go to Dubrovnik button and you will be able to see Dubrovnik in all its glory. Now all you need to do is to visit it in real life, in Croatia.
214
Chapter 5
How to do it—changing labels to, let's say, German By default, Bing Maps labels are shown in English. However, often, you want to cater to the specific needs of your international audience. This recipe will show you how to display labels in German: 1. We will just continue from the previous recipes and this time, we will change and modify only our XAML code. 2. Locate the line where you have defined your Map control and just add the Culture attribute with the value: de-de, so that it looks like this: <Microsoft_Maps_MapControl:Map Culture="de-de" Mode="Aerial" CredentialsProvider="Enter Your Key Here" />
3. If you now press F5 and start your application, you will be able to see all of the labels written in the German language: You will see Kroatien instead of Croatia or Deutschland instead of Germany.
215
Maps, Pop-up Windows, and Escaping the Browser
How it (all) works... The Bing Maps control is an extremely rich and powerful control that supports a number of different functionalities and exposes a large number of properties, methods, and events for developers and designers. There are far too many possibilities to describe them all in this book, but under the There's more... sections, you will be able to find more useful resources. Anyhow, back to the explanations. Once you installed the Bing Maps Silverlight controls, the next step is to add references to your Silverlight project so that you can use the Maps control later on. There are two files that need to be added to project. After that, the Maps control is available and easily accessible from the Assets library. We've drawn it on top of the design surface and when we started it for the first time, we've encountered an error— in order to use the Bing Maps Silverlight control, you need to enter Key as a value for the CredentialsProvider within XAML. Once we did that, our simple application was up and running. As you already know, we can use either XAML or C# to change and modify the properties and settings for almost all controls. The first recipe explained how to set the different map modes using XAML, while in the second one, we did the same but this time using the C# code. As you can see in that code, it is fairly simple, but in order to achieve AerialWithLabels mode (that is how it is called in XAML), we actually needed to combine regular AerialMode and then set the Boolean value for Labels to True in order to show labels. The third recipe showed us how to position our map at a specific location. It is a commonly used scenario—sometimes, you want to show your users the exact location and not the default "World map" setting. In this recipe, we've decided to position the center of our map to Dubrovnik, Croatia. The procedure is fairly simple—you need to obtain the longitude and latitude in decimal format (meaning that the values such as 45°32´12˝ need to be converted). Apart from that, you need to set the zoom level, which basically says how close you want to be to the position you are interested in. After you set all those values and hit F5, you will be taken to the specified location. You can easily change all those values during the runtime and therefore, cater the overall experience even more for specific usage. The last recipe deals with internationalization or localization (depends on how you look at it) of your map. By default, a map uses the English language and settings, that is, the names of countries, geographical locations, oceans, and so on are presented in English. However, different languages are also supported. In this recipe, we've added support for German by setting the Culture property to de-de. Want to try in French? Just add the fr-fr and voila. It is that simple! 216
Chapter 5
There's more... Numerous different resources regarding the Bing Maps Silverlight control are available online; the most prominent one is the Interactive Software Development Kit (SDK).
Use the Interactive SDK for free These recipes have shown you how to use and implement the Bing Maps Silverlight control in Expression Blend. However, they are covering only the basics and are intended to provide you with an overview and share the possibilities with you. A more exhaustive resource exists in the form of online Interactive SDK for the Bing Maps Silverlight control. You can access it at: http://www.microsoft.com/maps/isdk/silverlight/. In Microsoft's own words, the Bing Maps Silverlight control Interactive SDK is a Silverlight application that demonstrates features of the Map control and provides the corresponding code to implement those features in your application. It is a real great resource for all the designers and developers looking for how to use and implement the mapping experience in their applications providing you with both the code and the final look—testing demo ground.
See also ff
Building full-screen Silverlight experiences
ff
Implementing out-of-browser experiences
Building full-screen Silverlight experiences Silverlight supports the full-screen mode, it effectively allows you to expand your application to take over the entire computer screen, and it will hide all parts of the browser chrome. Why would you want to use this? There are many different scenarios supporting this UX pattern; for example, when you are building full, immersive experiences, like the ones for games, mapping solutions (Atlases), media players, and so on. In this recipe, we will take the code and logic from the previous recipe that was dealing with the Bing Maps Silverlight control and show you how to extend it into a full-screen, immersive Atlas experience for your users.
217
Maps, Pop-up Windows, and Escaping the Browser
Getting ready We will take off from the last recipe that was dealing with the Bing Maps Silverlight control. However, the code sample for this chapter is separated and it is located in a separate folder. Please note that as was the case with the previous recipe, you will need the Bing Maps key in order to use all of the functionalities. However, even without the key, you will be able to see and demonstrate full-screen capabilities in this recipe.
How to do it... 1. Open the project and click on the mapWorld control. Under the Properties pane, set its HorizontalAlignment and VerticalAlignment properties to Stretch, and set all Margin values to zero. You want to make your map to fill all of the available space. 2. Under the Objects and Timeline pane, select the top-level element, usually called [UserControl], and set its Height and Width properties to Auto.
3. If your map now looks too small, you can set its design-time dimensions by clicking and dragging the handlers located around the control.
4. If you now press F5, your map will be as big as your browser window. Try resizing it, and it will resize accordingly. However, it will not occupy the whole screen; it will leave the browser chrome visible at all times.
218
Chapter 5
5. Add the Button control on top of your Map control. Call it btnFullScreen and set its Content property to Toggle Full Screen. Under the Properties pane, click on the Events icon and double-click the field near the Click event. It will create a placeholder for the code logic for a full-screen implementation. 6. Add the following lines of code: if (!Application.Current.Host.Content.IsFullScreen) { Application.Current.Host.Content.IsFullScreen = true; } else { Application.Current.Host.Content.IsFullScreen = false; }
7. Press F5 now. After your application starts, click on the Toggle Full Screen button. Your map will now occupy the whole screen. If you click on the button again (or hit the Escape key), you will be returned to your "usual" view.
How it works... The only part of this recipe that needs some explanation is the one that is related to code. So, the first thing that we are going to do is check if our application is already in full screen mode. If not, we set it by using: Application.Current.Host.Content.IsFullScreen = true;
If we are already in full screen mode, we will return to our regular, non-full screen mode with the help of the following line of code: Application.Current.Host.Content.IsFullScreen = false;
Note that you can return from full screen mode to the regular, default mode by pressing the Escape key.
There's more... Full screen is a great mode for immersive applications such as games, mapping experiences, and media players. However, there are some limitations that you should be aware of before you decide to implement and design this kind of experience.
219
Maps, Pop-up Windows, and Escaping the Browser
Some limitations with the full-screen Silverlight experiences Due to security reasons, you cannot trigger and set the full screen mode without a user's action. This means that you are not able, for example, to start your application in full screen mode by default. As you have seen, you can use a user input event such as a button click. Apart from a button click, you can also trigger the full screen mode by utilizing one of the following events: ff
MouseLeftButtonDown
ff
MouseLeftButtonUp
ff
KeyDown
ff
KeyUp
More restrictions exist. Imagine the case where you have a TextBox control where you can enter some text using your keyboard and right-click to show the context-menu to copy and paste parts of the text. While all that is possible in Silverlight, once you go to the full screen mode, you'll have to say goodbye to those capabilities. In order to prevent password stealing and other spoofs, Microsoft has limited the available keyboard inputs, which means that while in the full screen mode, you can use only the following: ff
Space
ff
Arrow keys (Left, Right, Up, Down)
ff
Home
ff
End
ff
Enter
ff
Tab
ff
Page Up
ff
Page Down
See also ff
220
Implementing out-of-browser experiences
Chapter 5
Implementing out-of-browser experiences Silverlight 3 has introduced the concept of an application running out of the browser. What it means is the fact that now you can use your Silverlight-based applications and install them locally on your computer and run them like that—without the need to open the browser. Of course, there are certain limitations and things that you should be aware of and this recipe will show you some of those. Once again, we will build upon the previous recipe (Full screen Bing maps Silverlight recipe), as it provides a solid foundation for this recipe as well.
Getting ready We will take off from the last recipe that was dealing with the Bing Maps Silverlight control. The code sample for this chapter is, separated however, and it is located in a separate folder. Please note that as was the case with the previous recipe, you will need the Bing Maps key in order to use all of the functionalities. However, even without the key, you will be able to see and demonstrate the out-of-browser capabilities in this recipe.
How to do it... 1. Open the project that you have previously saved. Navigate to Project | Silverlight Project Options | Enable Application Outside Browser. 2. Believe it or not, this is pretty much it. Press F5 to start your application. Blend will ask you if you want to run the application inside the browser first; you just click on Yes and agree with it. 3. Once your application starts, you can right-click on the surface and select the option to install the application locally. 4. Click on that option and a new dialog will appear asking you where to install the application. You can select both Start menu and Desktop and click on OK. After that, a new window will appear with your application running. If you now click on the Toggle Full Screen button, you will notice that it will still continue to work just like it was the case while it was running within a browser—all the functions are just the same. 5. Close your application now. Go to Start and start typing its name in the Search field; it will appear there and you can run it just like any other application. 6. If you want to uninstall it, just right-click on it, select the option to remove the application, and click on OK to confirm that. Don't do that at the moment, as there is more in this recipe.
221
Maps, Pop-up Windows, and Escaping the Browser
How to do it—detecting network availability Let's just keep working on the previous sample. Detecting network availability is really important in cases where an out-of-browser application needs access to a network in order to function properly. Our mapping application is a typical example of such an application because it requires network connectivity in order to serve us maps. Sometimes, however, your users won't have network access and you need to design and implement a good user experience and inform them of that. We will now make our application "network aware". Disconnect from any network and try running your application right now. You will be greeted with a message saying that the application is unable to contact the server:
This is a partially good experience, thanks to the solid implementation of the Bing Maps Silverlight control. But a better approach would be to make your application more responsive and aware of network changes. For example, if you now connect to the network, you won't see any changes in your application. Let's fix that and make our application network aware. 1. Add a new button, call it btnNetwork, and set its Content property to Network. 2. Go to the code-behind file and add the following using statement at the end of other using statements: 222
Chapter 5 using System.Net.NetworkInformation;
3. Return to the "design" view. Select the Layout Root control under the Objects and Timeline pane. Under the Properties pane, locate the Events icon and click on it. Then, double-click on the Loaded file in order to define an event handler for the Loaded event; the code editor will appear. 4. Add the following lines of code there: if (NetworkInterface.GetIsNetworkAvailable()) { btnNetwork.Content = "Connected"; btnNetwork.Foreground = new SolidColorBrush(Colors.Green); } else { btnNetwork.Content = "Not Connected"; btnNetwork.Foreground = new SolidColorBrush(Colors.Red); }
5. Be sure that you are connected to the network and run your application. You will see something like this:
6. If you now disconnect from the network, the button will still show Connected—it is not aware of the fact that your connection state has been changed. We will solve this in the next step. 7. Go back to the code and immediately after the IntializeComponent(); add the following lines: Loaded +=new System.Windows.RoutedEventHandler(MainPage_Loaded); NetworkChange.NetworkAddressChanged +=new System.Net. NetworkInformation.NetworkAddressChangedEventHandler(NetworkChan ge_NetworkAddressChanged);
223
Maps, Pop-up Windows, and Escaping the Browser 8. My suggestion is to start typing them, when you reach the += part, Blend will suggest you press the Tab key and it will automatically generate event handlers for you. After that, locate the NetworkChange_NetworkAddressChanged event handler and add the same code as you have added under the fourth step of this recipe. It should look like this at the end: private void NetworkChange_NetworkAddressChanged(object sender, System.EventArgs e) { if (NetworkInterface.GetIsNetworkAvailable()) { btnNetwork.Content = "Connected"; btnNetwork.Foreground = new SolidColorBrush(Colors.Green); } else { btnNetwork.Content = "Not Connected"; btnNetwork.Foreground = new SolidColorBrush(Colors.Red); } }
9. Be sure that you are connected to the Internet and press F5 now to test your application. Try disconnecting and you should be able to see a new state in your application looking like this:
10. This provides you with a great starting point where you can handle the behavior and design of your application in cases when it is connected to the network or when it is working offline. Of course, if you connect back to the network, the button will change its state to Connected.
224
Chapter 5
How it (all) works... An out-of-browser experience is one of the most exciting features in Silverlight 3 (and later in newer Silverlight versions) for the author of this book. While you probably are not that thrilled with this scenario (like myself), you can agree that it provides us with some really interesting and rich UX and interaction scenarios enabling end users to literally grab their Silverlight, web-based experience and install it locally on their machine—PC or Mac? No difference at all! The first step was to enable the out-of-browser experience by selecting that option in Expression Blend. But enabling the out-of-browser experience (and install or uninstall scenarios that have followed directly from it) is only the first part of the story. Making our application network aware was the next important step. We've added a simple Button control in order to use it as an indicator for our network connectivity—by changing the Content property and the Foreground color we wanted, for the demo purposes, to show if our application is connected to or disconnected from the network. The first step was simply playing with the NetworkInterface.GetIsNetworkAvailable() method and looking for its result. This method always returns a Boolean value: it is true if the network connection is present and false otherwise. Once you started the application (while connected), you were able to see the Connected state, but once you had disconnected, the state stayed the same; our application was not able to recognize the fact that the connection had been lost. We needed to define one more event handler, NetworkChange.NetworkAddressChanged, which occurs when the IP address or the network interface changes. We've added the same code that was utilizing the previously mentioned NetworkInterface.GetIsNetworkAvailable() method under this event handler. By doing this, we've been able to make our application fully aware, in real time, of all network status changes. Now, the only challenge that remains is to handle those two states properly and to ensure a smooth and terrific experience for the end users.
See also ff
Building full-screen Silverlight experiences
225
6
New Controls and Avant-Garde Features In this chapter, we will cover: ff
Webcam support and printing
ff
Effects with pixel shaders
ff
Animating ListBox items
ff
PathListBox—abandoning the rectangular ListBoxes
Introduction This is the last chapter of the book, and I thought it would be interesting to make it a bit different. All recipes in this chapter require you to have Silverlight 4 (and Expression Blend 4) installed so you can enjoy new features and somewhat avant-garde recipes, which I'm about to show you here. Please note that most recipes described in this chapter are here for demonstrational purposes, and their inclusion to your actual, real-life projects is not something you should do right after you read those recipes. Some of them are fairly bad from a usability perspective; they are used and described here just to give you a feeling of what can be done. However, my true intention here is, hopefully, to encourage you to think and explore possible, good, and usable scenarios for these recipes in your real life applications, and build simple to use interfaces and great and valuable user experiences.
New Controls and Avant-Garde Features Webcam support is a new feature introduced in Silverlight 4. In this recipe I will guide you through a simple application and show you how to grab stills from your webcam and print them. The next recipe will introduce you to a magic world of pixel shader effects. Ripple, blinds, and many others are available, and I will demonstrate how you can utilize those and even build some fairly interesting effects and animations in your application. The two recipes that will follow after that are closely related, and they both deal with the popular ListBox control. In previous versions, ListBox control existed but was rectangular and somewhat limited with respect to the item layout. However, now you can add some interesting stuff to this control. In the first recipe I will show you how to manipulate with LayoutStates and how to change the appearance of different items hosted in your List Box control, and then, in the second recipe, I will show you that your List Box control does not have to be a "box" at all. We will break loose from the older, rectangular look and explore different shapes and layouts using the PathListBox control. So, let's get started!
Webcam support and printing Silverlight 4 brings us support for microphone and webcam. Some really interesting usage scenarios are now possible with this. In this recipe, I will show you how to add and get video feed from your webcam, and after that I will guide you through how you can capture single still images and send them to your printer using the standard Print dialog. A simple yet useful and effective scenario. So, let's get started…
Getting ready Start your Expression Blend 4 and create a new project. Make it a Silverlight 4 project and from the Language drop-down list choose C#.
How to do it – getting started with webcam 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. The first thing we will do here is to add a simple Rectangle control to your design surface. Set its Height to 240 and Width to 320, and set its Fill to any color you want. Be sure to set its name to rctVideo at the top of the Properties pane while your Rectangle control is selected. 3. Now add a Button control just below your rectangle control. Name it btnStart and set its Content property to Start.
228
Chapter 6
4. With the Button control selected, go to Events and double-click near the Click field so that an event-handler is generated. Add the following code in the code-behind file for the btnStart_Click event: WebCamera.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); VideoBrush videoBrush = new VideoBrush(); videoBrush.Stretch = Stretch.Uniform; videoBrush.SetSource(WebCamera); this.rctVideo.Fill = videoBrush; if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess()) { WebCamera.Start(); }
5. While in code view, add the following line just after the InitializeComponent(); line: WebCamera = new CaptureSource();
And add the following line just before public MainPage(): private CaptureSource WebCamera;
6. Be sure that your webcam is attached to your computer. Hit F5 to start your application. After it starts, click on the Start button. A dialog box asking you for permission appears; click Yes to allow access to camera and microphone (though we will not use the microphone in this recipe).
229
New Controls and Avant-Garde Features 7. After you grant access to your camera and click Yes, you should be able to see that which your webcam is capturing directly in your application.
How to do it – taking stills from your webcam 1. Continuing from the last point in the previous recipe, I will show you how to add one more feature—the ability to take still shots from your webcam. 2. Add an Image control close to your previously added Rectangle control. Use the same dimension (320 x 240) and set its Stretch property to Uniform. Be sure to name it imgCapture. 3. Add a Button, call it btnCapture, and set its Content to Capture. Go to Events and create a Click event-handler for btnCapture. 4. Add the following lines of code: if (null != WebCamera) { if (WebCamera.State == CaptureState.Started) { WebCamera.CaptureImageCompleted +=new System.EventHandler<System.Windows.Media.CaptureImageCompletedEven tArgs>(WebCamera_CaptureImageCompleted); WebCamera.CaptureImageAsync(); } else { MessageBox.Show("Make sure your webcam is running!"); 230
Chapter 6 } } else MessageBox.Show("Make sure your webcam is running!");
5. Note that while you are writing the WebCamera.CaptureImageCompleted line, right after you enter += you will be asked to hit the Tab key twice, and that will automatically generate a new event-handler called WebCamera_ CaptureImageComplete for you. 6. Go to that event handler and add the following line of code: this.imgCapture.Source = e.Result;
7. If you now hit F5, allow access, and click on the Capture button you will be able to see the captured image on the righthand-side. The following screenshot shows a still capture of my iPhone with the WallofTweets.net webpage loaded, while the left part shows the actual, live, webcam feed:
How to do it – printing stills from your webcam 1. Continuing from the last point in the previous recipe, I will show you how to send a still image to the printer. 2. Add a new button control and call it btnPrint. Set its Content to Print. For a better user experience, position the btnPrint close to the imgCapture button. Go to Events and add the Click event-handler for btnPrint. Add the following code: PrintDocument pd = new PrintDocument(); pd.PrintPage += (s, args) => { args.PageVisual = this.imgCapture;
231
New Controls and Avant-Garde Features args.HasMorePages = false; }; pd.Print("WebCamPrintJob");
3. Be sure to add a using statement at the beginning of the C# code file. You need to add the following line: using System.Windows.Printing();
4. If you now hit F5, click on Capture, and then hit Print in order to print out the captured still, you will see the usual Print dialog, where you can set some further options and print your document.
5. After you hit the Print button your document will be sent to the printer (the one you select from the Print dialog) and you will even see the name of the print job:
232
Chapter 6
How it works... In the previous several recipes you've learnt how to access, capture, and print content from your webcam. Now it is time to go over those specific scenarios from a more technical perspective. Our first step was to add a simple rectangle control, which would later serve as the place where our video from the webcam would be displayed. Thanks to its pretty smart architecture, VideoBrush, one of the Silverlight's features, enables us to use video pretty much in the same way as we would use Brushes for colors, and paint it on top of different UI controls. In our case, we used it for Rectangle. In order to get a video from our webcam device, we needed to attach the device and instantiate the CaptureSource object. I did that by setting the following line of code: WebCamera = new CaptureSource();
From this point on, I was able to use WebCamera as a more intuitive name so that our C# code was more readable. I hope that this effect was actually achieved. We've added significant code in the btnStart's Click event handler, defined a new VisualBrush and called it videoBrush and then set its Source property to our WebCamera. After that it was simple and logical to set Rectangle's Fill property to videoBrush and we were ready to start. One more thing needed to be done right after that, related to fact that the user, must allow and grant access to your webcam and microphone. After that last line of code, WebCamera. Start started our video feed directly from our webcam device. The next step was to enable a scenario where we could use the webcam as a digital camera to take a single, still shot, and later to send it to print. The first step was to add an Image control and call it imgCapture, which holds all the still images captured during the process. Also, we've added a Capture button, the one which actually triggered the photo itself. We added our code logic under the Capture's button Click event. Let's look at what we have done there. First, we checked whether our webcam was actually running and, if that is not the case, then a message box appears asking you to make sure it is properly connected and running. If, however, all that was correct, we then check to see if the current State is Started so we can go and grab our still. We've then defined an event handler for a CaptureImageCompleted event which, obviously, triggers after the image capturing has been completed. There we added some additional logic by setting the imgCapture's Source property to e.Result. Basically we've just said that we want to set the resulting image of the capture process as a source for our imgCapture control, so when you click on the Capture button you can always get the actual and current still from your webcam device.
233
New Controls and Avant-Garde Features The last step was to enable printing for the end-users through the standard Print dialog. That functionality is provided through the System.Windows.Printing namespace and through the PrintDocument class. At the end, it comes down to the fact that using the args. PageVisual = this.imgCapture; sets the control (imgCapture) to be used as a "source" for printing the document. After that, more properties and adjustments can be made through Print dialog as in virtually anywhere within Windows.
See also ff
Exploring and using pixel shaders and effects
Exploring and using pixel shaders and effects One of the new things introduced in Silverlight 3, and even better supported in Silverlight 4, through Expression Blend 4 is usage of different effects based on pixel shaders. In this recipe I will show you how you can use pre-built, existing pixel-shader effects, and even how to change and animate these effects in order to achieve some really interesting visuals.
Getting ready Start your Expression Blend 4 and create a new project. Make it a Silverlight 4 project and from the Language drop-down list choose C#.
How to do it – getting started with effects 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. The first thing we will do here is simply add an Image control to your design surface. Name it imgPicture. 3. The next step is to load an image from your disk to this control. You can do this by setting the Image control's Source property to an image on your disk. 4. Now add three Button controls on top of your design surface. Call them btnMonochrome, btnRipple, and btnSwirl. Also set their Content property to Monochrome, Ripple, and Swirl respectively.
234
Chapter 6
5. Create an event handler for btnMonochrome by double-clicking on the Click event. You will be transferred to the code-behind view. Before you do anything else, add the following using statement at the top of your file: using Microsoft.Expression.Media.Effects;
7. Now add the following line of code under the btnMonochrome_Click event handler: this.imgPicture.Effect = new MonochromeEffect();
8. Repeat the same procedure for the other buttons, adding the following lines for btnRipple and btnSwirl into their Click event handlers. For btnRipple add: this.imgPicture.Effect = new RippleEffect();
For btnSwirl add: this.imgPicture.Effect = new SwirlEffect();
9. Hit F5 and click on the buttons-note the different changes that are happening with the image.
235
New Controls and Avant-Garde Features
How to do it – modifying effect properties (creating a water ripple effect) Now, let's go one step further and investigate the possibilities for changing different effects' properties, and even modifying them during runtime. 1. Let's start with the previous recipe and just take it from there. With your imgPicture selected, locate the Effects section under the Assets pane (if the Assets pane is not visible on your workspace surface, go to the Window menu and turn it on there). 2. Under the Effects part, locate the RippleEffect. Drag it and drop it on top of your imgPicture control. Right after you do that your image will look "rippled", as expected. Now, under the Objects and Timeline pane, click on the RippleEffect (since it is applied to imgPicture, it is located as its child object), and go to the Properties pane. 3. Under the Properties pane, change its phase to several different values, for example, set it to 0, 10, or 100. You will notice that ripples are being affected. 4. Now, add a Slider control on top of your design surface. Name it sldSlider. Under the Common Properties section, set its Maximum value to 100 and leave the Minimum at 0. 5. Select RippleEffect under the Objects and Timeline pane, under its properties click on Advanced options (looks like small rectangle on the right side) and from the drop-down menu, select the option Element Property Binding…
236
Chapter 6
6. After you select the item, position your mouse cursor over the slider so it looks like the following screenshot, and then click on sldSlider control.
7. The Create Data Binding screen will appear, allowing you to select the desired property that you want to bind to. Make sure that Value is selected and click OK. You will now notice that the Phase property of the RippleEffect has a yellow border, indicating that its value is data-bound. 8. Now hit F5 to test your project and try moving the slider from one side to another. Observe the effects on your image.
237
New Controls and Avant-Garde Features
How it works... Silverlight 3 has offered support for pixel shaders and effects, but major improvements have been introduced with Expression Blend 4 and Silverlight 4. In this recipe, it was explained how to use and apply several different effects, both programmatically and by using the Effects found under the Assets pane. The first step in this recipe was to add support for effects by adding a using statement for Microsoft.Expression.Media.Effects. After that, you were able to utilize the number of different built-in effects. We've added an Image control and set its source to an image file (you can do that with almost any image you have on your hard drive). After that, the idea was to add three buttons and to apply different effects to our picture when the users click on buttons. We added buttons for monochrome, ripple, and swirl effect, for which the code-behind file hosts interaction logic that is quite simple and easy to read and understand. It was all achieved by setting the target of the effect (the object that will be affected by the effect) and the desired effect. Here's the example for ripple effect: this.imgPicture.Effect = new RippleEffect();
If you run your application and click on each button, then the desired effect will be applied. Note, however, that effects are not "cumulative", meaning that if for example, first you set a monochrome effect (and your image now looks monochrome), and then apply ripple, then you will see a colored image being rippled. The reason for this is in the specific nature of how pixel shaders work and affect the "original" image. Also, applying effects is not reserved just for image control. You can set it, for example, on your Button or DataGrid controls as well. Though it might cause more usability issues, it can also add some interesting effects.
What about setting effects using Expression Blend 4 and not through code? The second recipe was about adding a ripple effect, not through the code but rather through the Expression Blend 4 UI. Under the Assets pane you can access the Effects section and a number of different effects will be available for you to select.
238
Chapter 6
You can easily select the desired effect and drag it on top of a control (in our case it was the imgPicture). That effect will then appear under the Objects and Timeline pane where you can select it and change its properties under the Properties pane.
After you've done that you can see the effect being immediately applied to your image. But our next step was to dynamically, during runtime, change the properties of ripple effect. 239
New Controls and Avant-Garde Features For that purpose I've added a simple Slider control and set its minimum and maximum values from 0 to 100. The idea here was to establish a relationship between the Slider's Value property and the Phase property of the RippleEffect. Silverlight supports different types of bindings and one of them, suitable for this purpose, is called element property binding. By clicking on the Advanced Properties square near the Phase property of the RippleEffect, a drop-down menu appears, and from there you've to select Element Property Binding… option. After that, all you need to do is to select the desired object (control) and the Create Data Binding window will appear, allowing you to select the property you want to bind to. In our case that was the Slider's Value property. Simply said, by doing this, we've pulled a Value from the Slider that can be used as a value for the Phase property of the RippleEffect.
There's more... Actually there is so much more! You can build your own pixel shader effects using HLSL (High level shader language) and use those effects in your Silverlight (or WPF) applications. But I will leave you to use the search engine of your choice to get more information. I have one more idea, or suggestion for you. You can try and animate the Phase using the Storyboards with Repeat Behavior set to Forever, which is triggered when the page loads or when you click on the image. It should not be too hard. Also, note the Center properties for RippleEffect. How about wiring those with the mouse cursor location and initiating animation when the user clicks? That way you could create a really interesting look - the effect of users clicking on the surface and causing ripples. Now just add a (multi)touch enabled monitor and you can even engage your users with a tactile experience.
See also ff
Webcam support and printing
Animating ListBox items With Silverlight 4, a new StateGroup called LayoutStates has been added to the ListBoxItem class. Expression Blend 4 exposes LayoutStates, and allows you to manipulate and add different effects and animation when ListBoxItems are added or removed from the ListBox control. This recipe gives you some ideas and a simple approach on how to start using those effects and get you up and running with LayoutStates.
240
Chapter 6
Getting ready Start your Expression Blend 4 and create a new project. Make it a Silverlight 4 project and from the Language drop-down list choose C#.
How to do it – getting started with effects 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Draw a ListBox control on top of your design surface and name it lstListBox, add a TextBox control and name it txtEnter, and a Button control and name it btnAddItem. Arrange them as shown in the following screenshot:
3. Select the btnAddItem control, and under Events double-click the field near the Click event so that the placeholder for an event handler opens. 4. Add the following code there: if (!String.IsNullOrEmpty(txtEnter.Text)) { lstListBox.Items.Add(txtEnter.Text); txtEnter.Text = string.Empty; }
5. Hit F5 now to start your project. Enter the following strings into the text box control and hit the Add item button after you enter each one: First line, Second line, Third line.
241
New Controls and Avant-Garde Features 6. You will notice that those strings will now appear as items in the ListBox control.
7. All right! This was simple, now we are ready for some more fun and cool stuff. 8. Return back to Expression Blend 4 and right-click on the lstListBox control. From the drop-down menu, select Edit Additional Templates and then Edit Generated Item Container… and then click on Edit a Copy… 9. The Create Style Resource dialog box will appear. Leave all options as they are and hit OK. 10. Now you will be able to edit a ListBoxItem template. If you take a look under the Objects and Timeline pane you will see that its scope is now set to ListBoxItemStyle1 (ListBoxItemTemplate). 11. Open the States pane. If it is not currently visible on your Blend workspace, click on the Window menu, and then click on the States pane to turn it on. Once you have, it should look something like this:
242
Chapter 6
12. You will notice different state groups—for this recipe, we will be dealing with LayoutStates—new to Silverlight 4—and the ListBoxItem control template. These LayoutStates define how each ListBoxItem will appear and behave depending on its state (AfterLoaded, BeforeLoaded and BeforeUnloaded). We will keep things simple in this recipe and only play with a limited number of options but you are free (and encouraged) to explore more. 13. Select the Base state and under the Objects and Timeline pane select the Grid control named grid. Set its Opacity value to 0%. Now select the AfterLoaded state (under the beforementioned LayoutStates section), and with the grid selected set its Opacity to 100%. Also, find the Transition duration value (by default it's set to 0) and set it to 2 seconds. 14. Hit F5 and start adding new items into your list box. You will notice that they fade in from 0% opacity to 100% over the course of two seconds. Congratulations! This is your first LayoutStates animation implementation.
243
New Controls and Avant-Garde Features 15. Now let's take it one step further and add some transition effects. Notice the Fx icon. Click on it, and from the drop-down list select Pixelate.
16. If you now hit F5 and start adding items you will notice that they first appear pixelated, and after two seconds they become clear. This effect looks quite cool and you can use it for different scenarios in your user interfaces.
How it works... We started by creating a simple interface consisting of a ListBox control, a TextBox, and a Button control. The idea was to enable you to easily populate the ListBox with any text you added into the TextBox control, and it should appear as a ListBoxItem after you hit the Button. Also, if you hit the button while there is no text at all in TextBox control, nothing should happen. This has all been achieved just by several lines of code that have been added to the Button's Click event handler: if (!String.IsNullOrEmpty(txtEnter.Text)) { lstListBox.Items.Add(txtEnter.Text); txtEnter.Text = string.Empty; } 244
Chapter 6
After you hit F5 and tested your project you were able to type text and add it as items. Also, items have appeared right-away, with no delays, special effects or transitions whatsoever. Well, then we wanted to take it a step further and apply the new LayoutStates extension to the ListBoxItem class. The first step was to create a copy of the ListBoxItem control template and locate the LayoutStates group under the States pane. In short, the different states under the LayoutStates group are there to enable you to define animations and transitions that could occur when adding or removing ListBoxItems. The first step was to set the Grid's Opacity to 0 for the Base (think of it as default) state. After that, we clicked on the AfterLoaded state and set the same Grid's Opacity to 100. Since we didn't want that change to happen instantaneously, we set the Transition time to 2 seconds. After hitting F5 now and adding items, you are able to see that they appear and fade over the course of two seconds. However, in order to make things a bit more interesting, we decided to apply a TransitionEffect. When you click on the fx icon you will get a drop-down box with numerous pre-defined transitions that you can use. In this case we opted for Pixelate effect. Now, after hitting F5, we was able to see every item fading in over the course of two seconds and, being pixelated and rendered at the end. It's the effect that reminds me of a teleporter in the Star Trek series (I guess you can consider me to be a Trekkie!).
There's more… Of course, this recipe just showed you how easy it is to play with LayoutStates. You can easily extend it for situations where you are removing items from the ListBox control (think about the BeforeUnloaded state). You can also play with other visual properties and not just with the Opacity I've used. Especially interesting effects can be achieved by transforming the objects (Skew, Rotate…). If you are up for a challenge, then think about this common UI pattern and scenario, and how you can improve it using the LayoutStates:
245
New Controls and Avant-Garde Features Often you will want to add or remove items from ListBoxes that might appear, like on the following screen from the Microsoft Office Word 2010:
When you select an item in one of the ListBoxes you can use the Add>> or <
See also ff
PathListBox—abandoning the rectangular ListBox
PathListBox—abandoning the rectangular ListBox The PathListBox control is a new control, part of Expression Blend 4 SDK. What's so special about it? It allows you to arrange ListBox items in virtually any shape you can draw using the Pen or similar tool, and any Path can be now used as a list box. Circle? I'll show you that in this recipe. Spiral? You can do that for your own exercise. The cool thing is that you can involve some interactivity by adding animations (either by animating the PathListBox's properties or by animating the Path itself using the AnimationUsingPath class. 246
Chapter 6
Let's start with this…
Getting ready Start your Expression Blend 4 and create a new project. Make it a Silverlight 4 project and from the Language drop-down list choose C#.
How to do it – getting started with effects 1. After you have created your new project, under the Objects and Timeline pane you will see UserControl and LayoutRoot. LayoutRoot is a Grid control hosted in UserControl. 2. Draw an Ellipse on your design surface. You can use the SHIFT key while drawing it in order to make it perfectly circular, but that's not a necessity for this recipe. Make it to about 280 pixels in Width and Height. 3. Right-click on the Ellipse and from the drop-down menu select Path then Convert to Path. 4. Now locate the PathListBox control under the Assets pane and draw it on top of your design surface. It will look like there's no control at all, which is fine, no worries. 5. Next step is to tell the PathListBox control which path to use for its look. With PathListBox selected, locate the Layout Paths section under the Properties pane, click on the bulls eye icon and drag it over on to the Path (that was once the Ellipse control) and then click.
247
New Controls and Avant-Garde Features 6. After that you should be able to see your Path control listed as a Layout Path.
7. The next step is to add some items to our PathListBox. The simplest way to do that is to utilize the always handy Sample Data generator available in Expression Blend. 8. Go to the Data pane and click on the Create sample data icon, and after that on New Sample Data…
9. A New Sample Data dialog will appear. Leave all options as they are by default, make sure that the Enable sample data when application is running option is checked. Hit OK. 10. After that you will notice that Sample Data Source is now visible under the Data pane. Right-click on Property2 and then select the Remove option from the menu. You should only have Property1 listed under the Collection. 11. Click on Property1, then click on Change property type. A drop-down pane will appear. We will leave the Type as String and for the Format, select Phone Number.
248
Chapter 6
12. Now click and drag the Collection on top of your PathListBox control (not the elliptical path but the exact PathListBox control).
13. As soon as you release the mouse button you will see sample phone numbers populating your Path (circle) and arranged automatically. How cool is that? 14. Return to the Properties pane while still having your PathListBox control selected, and look at the numerous properties available under the Layout Path section— Distribution, Capacity, Padding, Orientation, and many more. You can explore those later on and see how they affect the orientation and visual appearance. 15. Set the Distribution to Even and you will notice that all items will be evenly distributed. Then set it back to Padded, since we will do some animation with this setting. 249
New Controls and Avant-Garde Features 16. Before we go on, hit F5 and see that those numbers are indeed items which can be selected in the same way as you'd do with the normal rectangular list box control.
17. Now, let's add some animation magic to make things more interesting. Set the Padding to -90. All your items should now fall onto the same location, looking something like this:
18. Now under the Objects and Timeline pane, click the plus sign (New…) to create a new storyboard. After you click on the + sign, the Create Storyboard Resource dialog will appear. Set the Name (Key) of the storyboard to IntroAnimation and hit OK. 19. You will be transferred to recording mode. Be sure that you are positioned at the PathListBox control and that the timeline playhead (yellow) line is located at 0 seconds. Click on the Record Keyframe icon and the keyframe will be positioned at the 0 seconds mark.
250
Chapter 6
19. Now drag your playhead to the 2 seconds mark and change the Padding to 5. You can do that just by simply entering the number 5 under the Layout Paths properties section. You will then notice that a new keyframe has been added automatically under the Objects and Timeline pane:
20. Click on the X mark to close your storyboard recording. 21. Now add the Button control on top of your design surface, name it btnStart and set its Content to Start. Go to the Events and double-click the Click field so that a new event handler for Click is opened. 22. Add the following code: this.IntroAnimation.Begin();
23. Hit F5 now and click on the Start button. Enjoy the show!
251
New Controls and Avant-Garde Features
How it works... It just does! Joking aside, let's go through the recipe and understand what's going on. As I've said in the introduction to this recipe, PathListBox control is a new control, part of Expression Blend 4 SDK, and it allows you to arrange ListBox items in virtually any shape that you can draw using the Pen or a similar tool. In our case, we have decided to draw a circle and then convert it to a Path, making it appropriate for the ListPathBox to use. The next step was to attach or tell the PathListBox which path object to use as its backbone. Clicking on the bullseye icon and dragging it over our circular path, then clicking on it was all that was required. After this we were ready to start populating our PathListBox. Instead of adding items manually, we decided to use a very cool feature available from Blend 3—Sample Data generation. We added a new sample data Collection, and decided to have just one Property—setting its Type to be String and Format to Telephone number. As you can see for yourself, a number of different other options are available for you to select from. After binding, you are able to immediately see sample data arranged on your circular path. Many properties are available to you to further customize the appearance. However, in this scenario we wanted to animate the Padding property, which affects the padding between neighboring items. The first step was to set the Padding to -90, so that all items fall into the same location. After that, we used some animation capabilities, and over the course of 2 seconds changed the Padding value from -90 (defaulted and set on the first keynote) to 5. The last step was to add a event handler that was in charge of triggering and starting the animation.
See also ff
252
Animating ListBox Items
Index A Action Panels. See task panes AddMonths method 176 AnimationUsingPath class 246 AutoEllipsis property 152 Auto sizing 13
B BlackoutDates property 182 brdBorder background property 112 BorderBrush property 112 BorderThickness property 112 CornerRadius property 112 padding property 112 btnStart_Click event 229
C C# using, for map mode changing 212, 213 calendar interface about 178, 182 getting started 178 guidelines 182, 183 implementing 178-181 users, determining 182, 183 using 178-181 working 182 CaptureImageCompleted event 233 ChildWindow, pop-up window implementation adding 199 background color, changing 200 close button, removing 201
positioning 201 working 201 class AnimationUsingPath 246 PrintDocument 234 classical menus. See also context menus classical menus about 89 accelerator, adding 93 cascading menus, creating 94 checkable menu items, creating 96 commands, executing 92 creating 90, 91 icons, adding 95 Menu control, adding 89 shortcut keys, adding 93 starting with 89 usage guidelines 97 working 91 clear entry points 131 collapsible panels about 144 creating 145, 146 using, need for 148 working 147 Color.FromArgb 208 command area 36 command buttons. See also classical menus command buttons. See also command links command buttons. See also menu buttons command buttons. See also wizards command buttons about 84, 88 adding 84 cancel buttons 87 default button 87
ellipses, using 86, 87 general guidelines 88 starting with 84 using, conditions 85 working 85 command links.See also command buttons command links. See also progress indicators, with known process duration command links. See also progress indicators, with unknown process duration command links. See also wizards command links about 111 guidelines 117-119 using 112-116 working 116, 117 Content property 170 context menus. See also classical menus context menus about 98 activating 98 getting started 98 usage guidelines 100 working 99 control types, responsive UI enabling lblPort 206 lblProxy 205 rdbAutoDetect 205 rdbManual 205 txtPort 206 txtProxy 206 Culture property 185
D date picker interface about 174 designing 174-176 guidelines 177 working 176 DisplayMode property 180 DockPanel about 52, 57 child element docking order, changing 56 docking, controlling 53-55
254
orientation, changing 56 working 55 Duration property 114
E Ease property 114 element property binding 240 event btnStart_Click 229 CaptureImageCompleted 233 EventName property 114 expanders about 143 creating 145, 147 working 147 Expression Blend 4 effects, setting 238, 239
F faceted navigation about 133, 137 classifying 137 creating 135, 136 example, Bing Travel 134 starting with 134 working 136 fixed layout creating 11 using, situations 14, 15 working 12 fluid layout about 8 columns 12, 13 creating 9, 11 grid sizing 12, 13 rows 12, 13 Star sizing 13 using, situations 14, 15 working 11 Format property 186 full-screen mode experiences, Silverlight building 217, 218 limitations 220 working 219
G guidelines for calendar interface 182, 183 for command links 117-119 for data picker interface 177 for split button 123 for star-based ratting 191 for time input interface 183
H High Level Shader Language. See HLSL HLSL 240 HorizontalAlignment property 21
I imgIcon HorizontalAlignment property 113 Margin property 113 Source property 113 VerticalAlignment property 113 Width / Height property 113 IsChecked property 136 IsIndeterminate property 101, 105 ItemCount property 190
J journal navigation about 57 navigation chrome, removing 61 Title 62 using, need for 62, 63 utilizing 57-59 WindowTitle 62 working 60
K key Bing Maps key 221 developer key 212 Escape key 219 shortcut keys, classical menus 93 Tab key 231
key sequence CTRL+C 93 CTRL+V 93
L LargeChange property 101, 105 layout fixed 8 fluid 8 lightbox 202 ListBox control 228 ListBox items about 240 animating 241-244 items, adding 246 items, removing 246 working 244
M maps adding, to Silverlight applications 209 applications, maps adding 210 maps, adding to Silverlight applications 210 Bing Maps Silverlight control, adding 210-212 Dubrovnik, navigating to 214 labels, displaying in German 215 mode changing, C# used 212, 213 mode changing, XAML used 212 working 216 Margin property 20 Maximum property 101, 105 maximum size 15 menu drop-down creating, steps 107-109 working 110 method AddMonths 176 NetworkInterface.GetIsNetworkAvailable() 225 SelectedDate.ToString() 182 Minimum property 101 minimum size 15 modal window. See pop-up window, Silverlight multiple item selection general guidelines 128 255
ListBox-CheckBox combination, using 126, 127 simple ListBox, using 123, 124 working 125 MultipleRangle property 182
N Name property 114 navigation pane components, buttons 15 components, content 15 content, hosting into specific tabs 20-23 creating, from scratch 17-19 tab control, using 16 using, situation 23, 24 working 20 NetworkInterface.GetIsNetworkAvailable() method 225
O out-of-browser experiences 198 about 221 implementing 221 network availability, detecting 222-224 working 225
P paging pattern about 149 characteristics 154, 155 creating 150-153 implementations 149 using 150-154 working 153, 154 PathListBox about 246 rectangular ListBox, abandoning 246-251 working 252 Phase property 240 pixel shaders building, HLSL used 240 effect properties, modifying 236, 237 effects setup, Expression Blend 4 used 238, 239 256
effects, starting with 234 ripple effect, creating 236, 237 working 238 pop-up window, Silverlight about 198 ChildWindow, adding 199 ChildWindow background color, changing 200 ChildWindow close button, removing 201 ChildWindow color, working 201, 202 ChildWindow, positioning 201 context 204 downsides 203 position 204 usage scenario 202 preferred size 15 PrintDocument class 234 ProgressBar 100 progress indicators with known process duration 100, 101 with unknown process duration 105, 106 working 102 progress indicators, with known process duration. See also progress indicators, with unknown process duration progress indicators, with known process duration calculating 101 general guidelines 103, 104 working 102 progress indicators, with unknown process duration. See also progress indicators, with known process duration progress indicators, with unknown process duration calculating 105 general guidelines 106 working 105 progressive disclosure using, conditions 50, 51 working 49 promoted actions about 167, 168 creating 169 implementation, hints 171 implementing 167 Luke Wroblewski saying 171 starting with 169
utilizing 170 working 170 property AutoEllipsis 152 BlackoutDates 182 Content 170 Culture 185 DisplayMode 180 Format 186 IsIndeterminate 101, 105 ItemCount 190 LargeChange 101 Maximum 101 Minimum 101 MultipleRangle 182 SelectionMode 180, 190 ShowInTaskbar 26 SmallChange 101 Value 101 PropertyName property 114
R Record Keyframe icon 250 Rectangle’s Fill property 233 ResizeMode property about 30 styles, setting to 30 responsive UI enabling 198 about 204 benefit 208 Color.FromArgb 208 context 209 control types 205 designing, starting with 204 designing, steps 205-207 working 207, 208 right-click menus. See context menus row colors about 191-195 alternating 192, 193 design guidelines 195 in real-life 195 working 194, 195
S Sample Data Generation 150 SDK about 217 accessing 217 free usage 217 SelectedDate.ToString() method 182 SelectionMode property about 125, 180, 190 multiple value 125 single value 125 ShowInTaskbar property 26 Silverlight Accordion control 145 applications, maps adding 209 DataGrid 194 date picker interface 177 full-screen mode experiences, building 217 pop-up window, implementing 198 split button, creating 123 Silverlight 3 out-of-browser experiences 221 Silverlight 4 webcam support 228 simple ListBox using, for multiple item selection 123, 124 Slider’s Value property 240 SmallChange property 101 Software Development Kit. See SDK specific UI pattern about 130 Bing search engine 132, 133 designing 130, 131 StockTrader label 131 working 131-133 split button creating 120-122 creating, Silverlight used 123 guidelines 123 in Outlook 2007 119 working 122 stack order 56 star-based rating about 173, 188, 190 design, guidelines 191
257
guidelines 191 implementing 188-190 working 190 Star sizing 13 startup object 58 status bar about 73 adding, steps 73-75 implementation guidelines 80, 81 other controls, adding 76-78 SizeGrip, adding 79 using 79, 80 working 76 Stretch property 230
T tabs about 64 adding 64-66 icons, adding 68-70 implementation guidelines 71, 72 orientation, changing 68 using 70 using, queries 70 working 67 task panes about 160 controls, hosting 166, 167 creating 162-164 examples 160 implementation hints 165 implementing, need for 165 starting with 161 using 162-164 working 164 time input interface about 184 designing 184, 185 features 186 guidelines 187 using 186 working 185, 186 titled sections about 158 implementation consideration 159, 160 Internet Options dialog 156 258
starting with 157 using 155 using, reasons 158 using, steps 157 working 158 tree views about 138 container node 138 creating 139, 140 determining, as good UX pattern 141 leaf node 138 main challenges 142 root node 139 using, guidelines 142 working 141 txtDescription Font size property 113 Foreground property 113 HorizontalAlignment property 113 Margin property 113 Text / Font property 113 Text property 113 VerticalAlignment property 113 Width / Height property 113 txtMainInstruction Font size property 113 Foreground property 113 HorizontalAlignment property 113 Margin property 113 Text / Font property 113 Text property 113 VerticalAlignment property 113 Width / Height property 113
U UI pattern implementing, in WPF application 47 UI pattern, implementing in WPF application expander control’s header label 49, 50 steps 47, 48 working 49
V Value property 101, 102, 114 VerticalAlignment property 22
W webcam getting started 228, 229 stills, printing 231, 232 stills, taking 230, 231 working 233 window management about 25 contextual window 25 general window usage, guidelines 34, 35 icon, changing 26 minimum screen resolution target, determining 33 primary window (top-level) 25 program-initiated 25 ResizeMode property 30 ResizeMode, setting 26 secondary window(owned) 25 states 28 system-initiated windows 25 Title bar controls 26 window borders 26 window sizes 27, 32 window states 32 WindowStyle property 30 Windows Presentation Foundation. See WPF WindowStartupLocation property about 30, 33 CenterOwner option 33 CenterScreen option 33 manual option 33 WindowState property 28 maximized state 32 minimized state 32 normal state 32
window positioning, using 33 WindowStartupLocation property 33 WindowStyle property 27 styles, setting to 31 wizards about 35 building 35-38 resizable wizard, designing 45 types, overview 40 using, guidelines 46, 47 using, situations 45 working 39 wizards, types choice page(s) 42 commit page 42 follow-up page 44 Getting started page 41 progress page 43 WPF UI pattern, implementing 47
X XAML using, for map mode changing 212
Z z_order 56 ZeroOr More property 147
259
Thank you for buying
Silverlight 4 User Interface Cookbook About Packt Publishing
Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our solution based books give you the knowledge and power to customize the software and technologies you're using to get the job done. Packt books are more specific and less general than the IT books you have seen in the past. Our unique business model allows us to bring you more focused information, giving you more of what you need to know, and less of what you don't. Packt is a modern, yet unique publishing company, which focuses on producing quality, cutting-edge books for communities of developers, administrators, and newbies alike. For more information, please visit our website: www.packtpub.com.
Writing for Packt
We welcome all inquiries from people who are interested in authoring. Book proposals should be sent to [email protected]. If your book idea is still at an early stage and you would like to discuss it first before writing a formal book proposal, contact us; one of our commissioning editors will get in touch with you. We're not just looking for published authors; if you have strong technical skills but no writing experience, our experienced editors can help you develop a writing career, or simply get some additional reward for your expertise.
Microsoft Silverlight 4 Business Application Development: Beginner’s Guide ISBN: 978-1-847199-76-8
Paperback: 412 pages
Build enterprise-ready business applications with Silverlight 4 1.
An introduction to building enterprise-ready business applications with Silverlight quickly.
2.
Get hold of the basic tools and skills needed to get started in Silverlight application development.
Microsoft Silverlight 4 and SharePoint 2010 Integration ISBN: 978-1-849680-06-6
Paperback: 336 pages
Techniques, practical tips, hints, and tricks for Silverlight interactions with SharePoint 1.
Develop Silverlight RIAs that interact with SharePoint 2010 data and services
2.
Explore the diverse alternatives for hosting a Silverlight RIA in a SharePoint 2010 Page
Please check www.PacktPub.com for information on our titles
JavaFX 1.2 Application Development Cookbook ISBN: 978-1-847198-94-5
Paperback: 360 pages
Over 60 recipes to create rich Internet applications with many exciting features 1.
Easily develop feature-rich internet applications to interact with the user using various built-in components of JavaFX
2.
Make your application visually appealing by using various JavaFX classes—ListView, Slider, ProgressBar—to display your content and enhance its look with the help of CSS styling
JSF 1.2 Components ISBN: 978-1-847197-62-7
Paperback: 408 pages
Develop advanced Ajax-enabled JSF applications 1.
Develop advanced Ajax-enabled JSF applications and solve common web development challenges using UI components from JSF component libraries
2.
Master the basics of building web user interfaces with standard JSF HTML components
Please check www.PacktPub.com for information on our titles