Microsoft Silverlight 5: Building Rich Enterprise Dashboards
Create, customize, and design rich enterprise dashboards with Microsoft Silverlight 5
Todd Snyder, Joel Eden, Ph.D. Jeff Smith, Matthew Duffield
professional expertise distilled
P U B L I S H I N G BIRMINGHAM - MUMBAI
Microsoft Silverlight 5: Building Rich Enterprise Dashboards Copyright © 2012 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 authors, nor Packt Publishing, and its dealers and 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 of 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: January 2012
Production Reference: 1170112
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 978-1-84968-234-3 www.packtpub.com
Cover Image by Sandeep Babu (
[email protected])
Credits Authors
Technical Editor
Todd Snyder
Joyslita D'Souza
Joel Eden, Ph.D.
Sonali Tharwani
Jeff Smith Matthew Duffield Reviewers Curtis Taylor Michael Crump Siddharth Mehta
Indexer Tejal Daruwale Project Coordinator Leena Purkait Proofreader Clyde Jenkins
Peter Meany Acquisition Editor Kerry George
Graphics Manu Joseph Production Coordinator
Lead Technical Editor
Nilesh Mohite
Alina Lewis Cover Work Nilesh Mohite
About the Authors Todd Snyder has been a Software Developer/Architect for over 17 years. During
that time, he has spent several years as a Consultant, providing technical guidance and leadership for the development of Enterprise Class Systems on the Microsoft Platform. At Infragistics, he is a principal consultant who focuses on the design and construction of RIA and N-tier based applications. Todd is the co-leader for the New Jersey .NET user group (http://www.njdotnet.net/) and is a frequent speaker at trade shows, code camps, and Firestarters.
Joel Eden, Ph.D. has been working in the area of user experience and design methods for over 10 years. Currently a Senior Interaction Designer working on UX Tools at Infragistics, he previously spent 3 years in the Infragistics UX Services group, consulting for external clients. Prior to Infragistics, he worked at multiple design agencies in the Philadelphia area, as well as working at Lockheed Martin's Advanced Technology Labs. He holds a B.S. in Computer Science, and a PhD in Information Science, both from Drexel University. I would like to thank my wife Kathleen and my daughters Abigail and Genevieve, for giving me reasons to design a better future.
Jeff Smith has been a Visual Designer for 6 years. During that time he has been an Art Director at various agencies and studied Special Effects and Animation at NYU. A convert from Flash and Flex, he has been working with .NET technologies for the past 2 years, specializing in WPF and Silverlight. At Infragistics, he is an UX Visual Designer who focuses on the design, implementation, and User Experience. You can view some of his work at http://www.thinksinkstudio.com. I would like to thank my friends, family, girlfriend, and colleagues for providing support and inspiration.
Matt Duffield is the Architect at emGovPower, a leading software provider for
managing city and county governments. With over 15 years of working in IT, he enjoys building rich user-centric applications. Matt is very active in the community, speaking at user groups and code camps. He is an INETA speaker member and has been a Microsoft MVP in Client Application Development. He started working in .NET as soon as it was available to the development community and was also an early adopter of both WPF and Silverlight. He believes good business intelligence (BI) architecture is the formula for a successful software package that looks beyond just data and provides insightful information. His blog can be found at http:// mattduffield.wordpress.com. You can follow him on Twitter at @mattduffield. Matt currently lives in Charlotte, North Carolina with his wife and two sons. First of all, I would like to thank my family and colleagues who have been instrumental in helping me work on this book. It is their encouragement and enthusiasm that has in turn been my drive for writing. I have always loved working in Silverlight, and I look forward to many more years doing the same. I would also like to thank the team at Packt Publishing for allowing me to become a part of this book and having the patience and wisdom to help me during the writing process. It has been a wonderful experience, and I look forward to doing it again in the future.
About the Reviewers Curtis Taylor is a Principal Consultant at Infragistics, Inc. When he first started
studying human interaction with products, objects and particularly software interfaces, he noticed people often believed they were dumb when they did not understand an interface. However, rather than fixing the problem, the industry standardized interfaces which lacked the ability to engage most users. The industry attempted to fix the user, rather than the interfaces. Designing interface is an interaction between user and developer. Two things drew him to Software Development—the abstraction of writing code and the challenge of presenting that abstraction to human beings in a way they can understand. People are organic. Computers are not. So the work of making software interfaces more understandable, practical, and enjoyable became something he wanted to do. Software development is his connection to serving people. People are more important than things. Perhaps his message will be communicated in the interfaces he creates, the code he writes, and the feedback, training, and team-work he offers to other developers. He loves WPF and Silverlight! So much so, Infragistics found and hired him to be a consultant and trainer. At Infragistics he works directly with customers helping them solve technical and UI-related issues with WPF and Silverlight, he provides training as a fellow software engineer, and he develops custom solutions for customers who wish to utilize their services a step beyond the capabilities of their products.
Michael Crump is an MCPD who has been involved with computers in one way
or another for as long as he can remember, but started professionally in 2002. After spending years working as a System Administrator/Tech Support Analyst, Michael branched out and started developing internal utilities that automated repetitive tasks and freed up full-time employees. From there, he was offered a job working at McKesson corporation and has been working with some form of .NET and VB/C# since 2003.
Michael is currently serving as a Subject Matter Expert (SME) and Content Editor on several other Silverlight publications. He resides in Birmingham, AL with his wife Amanda and children Ridley and Adrienne. He shares his findings in his personal blog: http://michaelcrump.net, and he also tweets at @mbcrump.
Siddharth Mehta is a Business Intelligence professional with more than nine years of experience, and presently works in the role of a Technology Architect for Accenture Services Pvt. Ltd (Mumbai, India), in the capacity of an Associate Manager. Prior to Accenture, he has worked at Capgemini with clients including Walt Disney Pictures and Television, CitiBank, Transport for London, and ABN AMRO. He started his career in 2002 with Visual Basic and SQL Server, and since then he has been majorly working with SQL Server, Business Intelligence, Data Warehousing, Dimensional Modeling, Information visualization design, and related technologies. He is known for his writing in the field of Microsoft Business Intelligence. He has authored a whitepaper for MSDN Library, titled Bulk Report generation using SSIS and SSRS 2008 R2. He continues authoring content on MS BI for community sites such as MSSQLTips.com, SQLServerCentral.com, SQL-Server-Performance.com, and others. He has been the Technical Reviewer of the book Microsoft SQL Azure Enterprise Application Development. He has won awards such as Microsoft Most Valuable Professional CY'11, Capgemini India Envoy FY'10, and others through the course of his career. He shares his insights on business intelligence through his blog: http://siddhumehta.blogspot.com. He can be reached at
[email protected]. Through thick and thin, all I am today is the result of my parent's (Divya Mehta and Kaushik Mehta) vision and my brother's (Rahul Mehta) support to solve troubles before it reaches me. I am grateful to them for taking care of my responsibilities while I remained busy reviewing this book.
www.PacktPub.com Support files, eBooks, discount offers and more
You might want to visit www.PacktPub.com for support files and downloads related to your book. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub. com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at
[email protected] for more details. At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
http://PacktLib.PacktPub.com
Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library. Here, you can access, read and search across Packt's entire library of books.
Why Subscribe? • • •
Fully searchable across every book published by Packt Copy and paste, print and bookmark content On demand and accessible via web browser
Free Access for Packt account holders If you have an account with Packt at www.PacktPub.com, you can use this to access PacktLib today and view nine entirely free books. Simply use your login credentials for immediate access. Instant Updates on New Packt Books Get notified! Find out when new books are published by following @PacktEnterprise on Twitter, or the Packt Enterprise Facebook page.
Table of Contents Preface Chapter 1: The Silverlight Technology What benefit does Silverlight bring to the table? XAML as a declarative programming model Model-View-ViewModel (MVVM) View First versus ViewModel First
Dependency Injection (DI) Silverlight as a Web technology Asynchronous programming in Silverlight Silverlight features Client-side application development Reduced server load Client-side state Cross-browser development simplified Putting the pieces together Summary
Chapter 2: Overview of Dashboards and Silverlight What are dashboards Purpose of dashboards Problems dashboards solve Current state of building dashboards When good just isn't good enough Why should we use Silverlight? Summary
Chapter 3: Silverlight Design and Development Tools Blend strengths and weaknesses Visual Studio strengths and weaknesses Visual States
1 5 5 6 6 9
11 14 16 16 21 21 22 23 23 24
25 26 32 35 36 37 38 41
43 44 46 48
Table of Contents
Storyboards Sample Data Templates Visual Studio Debugging Developing for Silverlight Project Management Summary
51 52 55 59 60 63 64 66
Chapter 4: Building a Basic Dashboard
67
Chapter 5: Dashboard Types and User Needs
87
Creating a Silverlight Dashboard Application What is the MVVM pattern Building the Dashboard Setting up the Data Source Defining the View-Model and Model classes Laying out XAML and Data Binding Customizing the UI Summary
67 70 73 74 75 78 83 85
Different dashboards for different needs 88 Strategic 88 Analytical 89 Operational 89 The Good, the Bad, and the Ugly—typical dashboard charts and graphs 89 Bar chart 90 Pros Cons
90 91
Stacked bar chart
91
Pros Cons
91 91
Line graph
91
Pros Cons
92 92
Scatterplot
92
Pros Cons
92 92
Bullet graph
93
Pros Cons
93 93
Sparkline
94
Pros Cons
94 94
Small multiples
94 [ ii ]
Table of Contents Pros Cons
95 95
Pie chart
95
Pros Cons
95 96
Focusing on needs, not technology Representing and communicating user experience User-centered design User research Personas Scenarios Requirements Storyboards Sketches Wireframes Prototypes High-fidelity mockups
Scenario-based requirements and design Example scenarios for dashboard design Summary
Chapter 6: Designing for Insight
Interaction aesthetics versus visual aesthetics Pre-attentive processing Applying pre-attentive processing to dashboard design Warnings about using pre-attentive attributes
Scenario-based design of our dashboard Our initial overall dashboard wireframe Requirement 1 Requirement 2 Requirement 3 Requirement 4 Requirement 5 Requirement 6
96 97 99 99 100 100 100 101 101 101 101 102
102 105 107
109
109 111 111 113
114 115 116 117 119 120 121 122
Summary
125
Chapter 7: Designing your Dashboard Knowing your tools Blend basics
Assets Data Design View (Artboard) Objects and Timeline Parts Projects Properties Resources
127 128 128
129 130 130 131 132 132 132 134 [ iii ]
Table of Contents Results States
134 135
Styling in Silverlight Referencing resources Implementing resources
135 136 136
Creating a Button Exploring a Button's Control Template Adding Visual States (Visual State Manager) Converting Brushes to Resources Creating Resource Dictionaries
Getting started with styling our Dashboard Creating a custom User Control in Blend Styling the Grid and Chart Summary
Chapter 8: Building an End-to-End Solution Dashboard prerequisites Dashboard requirements Designing the solution Describing an N-Tier application design Sample project structure Setting up the Data Source Reviewing the database schema Stored procedures spTopUsInternetProducts spTopUsInternetCustomers spSalesByRegion spFinanceData
136 137 144 152 155
157 157 160 162
163 164 164 166 166 168 172 173 174 175 176 177 178
Building the server components Domain Model (Shared Between Client and Server) Data Access Layer Building the WCF service Defining the presentation layer View and controls View Model Service Layer Summary
Chapter 9: Data Access Strategies Data access overview Core networking classes Working with WebClient Using Fiddler
180 180 187 194 197 197 205 209 212
213 214 214 214 218
[ iv ]
Table of Contents
Understanding network security Building services with Windows Communication Foundation Working with WCF The data access layer
219 221 223 224
Building a SOAP service Building a REST service Exploring OData data services Building an OData service Consuming an external service Summary
Chapter 10: Building Dashboards in SharePoint and Silverlight Overview of SharePoint Setting up SharePoint Building a Silverlight web part Using the Client Object Model Building a SharePoint Silverlight dashboard Setting up our data source Building our dashboard SharePoint Data Access Strategies Summary
Index
227 230 233 235 238 240
241 241 242 244 248 252 252 253 259 259
261
[v]
Preface Welcome, to the exciting world of building Rich Enterprise Dashboards with Silverlight. Throughout this book, you will learn how to harness the power of the Silverlight 5.0 platform to build amazing Dashboards. This book goes beyond just showing the nuts and bolts of learning Silverlight and showcases how to create amazing dashboards that offer the best user experience and visual design that will impress your end users and peers.
What this book covers Chapter 1, The Silverlight Technology, is an overview of the Silverlight 5.0 Platform and teaches you how to build Silverlight applications. Chapter 2, Overview of Dashboards and Silverlight, answers why you should use Silverlight 5.0 to build dashboards and compares the use of Silverlight and HTML for building dashboards. Chapter 3, Silverlight Design and Development Tools, is an overview of the different tools you will need to build a dashboard applications. Chapter 4, Building a Basic Dashboard, is a walkthrough of how to build a simple Silverlight dashboard application. Chapter 5, Dashboard Types and User Needs, outlines the three main types of dashboards: Strategic, Operational, and Analytical. By the end of this chapter, you will understand how to choose the right dashboard for your project depending upon your needs. Chapter 6, Designing for Insight, throws light on designing concepts of bringing the end-user's attention to certain information. Using these concepts, we will design a dashboard that supports the scenario we have already created.
Preface
Chapter 7, Designing your Dashboard, covers the basics of styling a Silverlight dashboard with Microsoft Expression Blend. Through this chapter you will understand the key styling terminology, learn how to reference resources, and edit basic control templates. Chapter 8, Building an End-to-End Solution, is an overview of building a real-world Silverlight dashboard application that uses the Microsoft SQL Server Adventure Works sample database. Through this chapter you will explore how to use the N-Tier application model to build out the AdventureWorks dashboard application. Chapter 9, Data Access Strategies, outlines the different data access strategies and technologies you can use when building your Silverlight dashboard application. Chapter 10, Building Dashboards in SharePoint and Silverlight, covers how to build a SharePoint web part for hosting a Silverlight dashboard, and how to use the SharePoint Client Object Model to access data hosted in SharePoint.
What you need for this book To build the samples in this book, you will need to have the following available: • • • • • •
Visual Studio 2010 Express or Professional Edition SQL Server 2008 R2 Express or Developer Edition Silverlight 5.0 SDK Silverlight 5.0 Toolkit Microsoft Expression Blend 4.0 (with Updates for Silverlight 5.0) Share Point 2010 Foundations (Optional only required for Chapter 10, Building Dashboards in SharePoint and Silverlight)
Who this book is for If you are a .NET developer who wants to create, customize, and design rich enterprise dashboards with Silverlight, then this book is for you. You should have an intermediate understanding of .NET development, with a working knowledge of Microsoft Silverlight.
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. [2]
Preface
Code words in text are shown as follows: "We can include other contexts through the use of the include directive." 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:
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: "When the dialog is displayed, click on the Discover button, and select the IDashboardService service contract." 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.
[3]
Preface
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 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.
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. [4]
The Silverlight Technology Silverlight as a technology has come a long way. We now have Silverlight 5 close to being released or already released with the publication of this book. We see Silverlight as the technology choice for Windows Phone 7. We see it as being a core part of Windows 8. Silverlight has become the standard technology for corporate Line of Business (LOB) applications. Because it is a plug-in technology, you don't have to worry about how it will render on disparate browsers or if it will look the same in Mac and Windows. In this chapter, we will take a look at what it means to develop Silverlight applications and ultimately dashboards. We will identify the advantages to using Silverlight as the platform of choice. We will cover the following topics: •
What benefits does Silverlight bring to the table
•
Client-side application development
•
Reduced server load
•
Client-side state
•
Cross-browser development simplified
•
Putting all the pieces together
What benefit does Silverlight bring to the table? Whether or not you are building enterprise applications, Silverlight can really make your applications look sharp with very little effort. Let's dig in and see what Silverlight as a technology brings to the table. We will also go over some of the new advancements that Silverlight 5 gives us.
The Silverlight Technology
First, let's discuss what it means to build a Silverlight application. The following are some of the areas of Silverlight that we will discuss: • • • • • •
XAML as a declarative programming model Model-View-ViewModel (MVVM) Dependency Injection (DI) Silverlight as a web technology Asynchronous programming in Silverlight Silverlight features
XAML as a declarative programming model Silverlight shares the same power of Windows Presentation Foundation (WPF) and gives us a rich declarative user interface programming model. This helps facilitate better separation of the user interface and the code that reacts to the user interface. Because of this declarative programming model and the rich data-binding that is inherent in XAML, we can easily put our code in a ViewModel class instead of the code-behind for the user control. Perhaps the biggest benefit for using this model is testing. It is a lot easier to write mock tests when we don't have to re-create the user interface, and all we are concerned with are the business rules. Another advantage to this model is the ability to reuse our ViewModels across Views. This means that we could have two views implemented and use the same ViewModel class. For example, one view would be a read-only screen, and the other would be an edit screen. When using a dependency injection (DI) container in your application, MVVM can also be very beneficial to you. You can inject all of the dependent services in your ViewModel, and use them as if you had created them in your own class. The beauty of DI is that you are making your code less coupled to other classes. You are coding to a contract instead of to an implementation. All the tedious ceremony of creating these objects is now the responsibility of the DI container. This makes your code easier to test and helps you follow the DRY principle: "Don't Repeat Yourself." By removing all the calls to create new instances of the dependencies we need, we are in effect reducing redundancy in our code. Using a DI container is a little more difficult if you are developing your applications using the View First approach. Most major frameworks that currently exist support or allow you to use View First or ViewModel First. Let's back up and discuss some of these concepts so, that we are all speaking the same semantic.
Model-View-ViewModel (MVVM) Before we go further, we need to be sure that we are all on the same page with the concept of MVVM. Model-View-ViewModel is a design pattern that is basically a hybrid from earlier proven patterns that have been used in both the Web and Windows development. Please refer to the following diagram: [6]
Chapter 1 View
ta
Da
g
in
nd
bi
Model
ViewModel
As we can see, we have your user interface defined in the View object. This is our XAML markup. In Silverlight, these are typically UserControl or Page objects. Because XAML has a rich data-binding model, it is easy for us to do our entire markup in XAML and have all the properties that are bound to reside in the ViewModel. The ViewModel acts like a controller. This is very similar to the popular ASP. NET MVC programming model that is currently available for web development. The ViewModel takes advantage of the rich data-binding model in XAML. The ViewModel typically becomes the DataContext of the View. It is this magic that allows us to redirect all of your logic from the code-behind of the View to the ViewModel itself. This is very powerful, and data-binding in XAML is flexible enough to allow for multiple levels of ViewModels to be bound on a given page. A typical ViewModel will control the references to any of the backend models and either expose the Model as a single property, or if it needs higher granularity of control around the model, it can expose the Model properties in the ViewModel itself by using wrapper properties. The Model typically is your data transfer object (DTO). In some models, you may choose to have your models implement the INotifyPropertyChanged (INPC) interface. If you are using the Entity Framework or Linq2SQL , then your models will already have this interface implemented. The View has no direct reference to the Model. It is only through data-binding that the View is aware of the ViewModel; in this case, the ViewModel is the DataContext of the View. Data Transfer Object (DTO) – A DTO is typically a simple representation of an item from your database storage. The most common correlation is a DTO representing a table from your database. The DTO will have properties that either map directly to the columns exposed on a table or a subset of columns. The DTO is meant to be kept very light without any business logic. You can use DTO to pass data across your layers in your n-tier architecture. For example, you would pass a DTO from your data access layer to the business layer. In Silverlight, we can either expose the DTO properties in our ViewModel, or simply have a property on the ViewModel that represents the DTO.
[7]
The Silverlight Technology
The following is a sample DTO that also implements INPC: namespace Dashboard.Models { public class ModelBase : INotifyPropertyChanged { #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged = delegate { }; public void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs (propertyName)); } } public void OnPropertyChanged (Expression property) { var lambda = (LambdaExpression)property; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = (UnaryExpression)lambda.Body; memberExpression = (MemberExpression)unaryExpression.Operand; } else memberExpression = (MemberExpression)lambda.Body; OnPropertyChanged(memberExpression.Member.Name); } #endregion }; public class Person : ModelBase { private string _firstName; public string FirstName { get { return _firstName;} set { _firstName = value; OnPropertyChanged("FirstName"); } }
[8]
Chapter 1 private string _lastname; public string LastName { get { return _lastname; } set { _lastname = value; OnPropertyChanged(() => LastName); } } }; }
We have two classes here in this code sample. The first class is simply a base class that allows us to inherit from and not need to re-implement the functionality of the INotifyPropertyChanged interface. This example shows you the traditional way to implement the interface, as well as one that uses some extra trickery to allow us to get an implementation that gives us compile time validation that we have the correct property name. One of the issues with the traditional way of implementing this interface is that it uses magic strings, which can really be a problem if you accidentally type in the wrong name for the property. We have provided both implementations, but we think you will agree with us once you start using the compile-friendly version. Magic strings – are a hard item to debug, as they require you to perform testing at runtime. What we would like to do is avoid these string representations as much as possible. If we could come up with a way to represent the name of a property without using a string, we could potentially avoid running into issues of misspellings and typing errors. Luckily, there are some clever examples that allow us to use lambda expressions to represent the property name. The previous code sample provides such an example. This is nice, as it gives us compile-time checking as well as supports refactoring of our code; otherwise, we would have to do some sort of search and replace step if we wanted to rename a property.
View First versus ViewModel First Whenever you start discussing MVVM, you will hear opinions on whether developing your applications View First or ViewModel First. We are not going to settle the debate, but rather introduce you to some of the arguments of each side and let you choose which you like for yourself.
[9]
The Silverlight Technology
View First goes on the premise that your Views are created first and then, usually through a locater, the corresponding ViewModel is created. If you don't use a locater to find the corresponding ViewModel, and you use XAML to instantiate your ViewModel, you are limited to the limitations of XAML. In order for XAML to work, you must have a default constructor. This implies that XAML will only call the empty constructor, and that is probably not what we want to happen if we choose to use any type of dependency injection container. To get around this, most developers, using View First, will create a ViewModelLocater class. This is typically a class that exposes all of the available ViewModels for the module you are developing as static properties. The implementation of the static properties allows you to use your dependency injection container to resolve any dependencies like a logging service. Another aspect that makes View First favorable is that it is considered "Blendable", meaning that it is Microsoft Expression Blend friendly. ViewModel First goes on the premise that your ViewModels are created first. If you are using Prism, you can inject the View in through your constructor and set the DataContext of the View to the ViewModel itself. In Caliburn.Micro, you simply use a naming convention, and the View for the corresponding ViewModel is resolved automatically. Views can become "Blendable" in ViewModel First, but it takes a little extra work to get everything set up correctly. When we use the term "Blendable", we are saying that Microsoft Expression Blend supports the ability to see real data from our ViewModel in our XAML while we are designing the UI without ever needing to run the application. This is a great time saver and productivity enhancer. Prism – The Patterns and Practices team from Microsoft has done a great job creating guidance when building componentized enterprise applications in Silverlight, WPF, and Windows Phone 7. This guidance provides sample examples and answers a lot of common questions when building enterprise applications. Some patterns that Prism solves are MVVM, event aggregation, dependency injection, and screen navigation. Their latest version is Prism 4.0.
[ 10 ]
Chapter 1
Caliburn.Micro is a small, yet powerful framework designed for WPF, Silverlight, and WP7. It implements a variety of UI patterns for solving real-world problems. Patterns that are highlighted include MVVM, event aggregation, dependency injection, and convention over configuration. One of the things that makes Caliburn.Micro stand out from other frameworks is convention over configuration. This powerful concept allows us to create certain conventions to remove the ceremony involved in setting the right configuration. By using conventions, this framework allows to create our XAML with very little markup. If we wanted to expose a TextBox in our XAML, and we named the control "FirstName", the framework would then look for a String property in the ViewModel with the same name. If you had a button that you named "Save", then the framework would again look for a method with the same name and bind the click event to this method so that it would be called at runtime. These are very powerful features, and this is just the tip of the iceberg when dealing with convention over configuration in Caliburn. Micro. The latest version of Caliburn.Micro is 1.2.
Dependency Injection (DI) If we look at most of the popular frameworks or guidelines available for Silverlight, a very powerful concept becomes evident. Silverlight is not the first technology to use dependency injection, and it will not be the last. When we talk about DI, we are trying to ensure that we reduce the amount of coupling that happens as we develop our applications. When our code is tightly coupled, it becomes very brittle and cannot be changed or refactored. Typically, the reason that our code becomes coupled is when we start introducing dependencies, and we code to the concrete implementation of these dependencies. We can remove such coupling by coding to the contract instead of the concrete implementation. This implies that we code to an interface. Say, for example, you are writing an enterprise application that you want to provide a logging service for logging messages. You have several projects that make up your application and several developers working on each model independently. This could cause some problems if each developer decided to define their own application programming interface (API) for the logging service. It would be better to create an interface that defines the contract with which you use the logging service. Next, instead of using a concrete implementation of the service, you create a reference to the interface you just defined. Then, you either inject this interface in via a constructor or a property depending on how you want to do this.
[ 11 ]
The Silverlight Technology
There are many frameworks that already support this. The Microsoft Patterns and Practices team has a guidance named Prism. Prism 4.0 is the current version. It allows you to use any DI container that you want, but provides out of the box support for Unity and the Managed Extensible Framework (MEF). Another great framework is Caliburn.Micro by Rob Eisenberg. It allows you to wire up whatever container you want or use MEF as well. It is nice, in that it also promotes a concept of convention over configuration. This can really make your XAML markup be very minimal and can speed up your development process. Another great framework is MVVM Light by Laurent Bugnion. It is a light framework that allows you to get your applications up and running using MVVM and also provides means for using DI as well. Using the previous example, the following is the Person class with the constructor setup to receive an object of type ILoggingService: public class Person : ModelBase { public Person(ILoggingService loggingService) { this._loggingService = loggingService; } private ILoggingService _loggingService; public ILoggingService LoggingService { get { return _loggingService; } set { _loggingService = value; } } private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; OnPropertyChanged("FirstName"); } } private string _lastname; public string LastName { get { return _lastname;} set { _lastname = value; [ 12 ]
Chapter 1 OnPropertyChanged(() => LastName); } } };
Again, the principle behind DI is that you do not construct or build your own objects. Basically, you never call the "new" keyword; instead, you use a container that "resolves" your objects for you, and during the process, the container provides all the necessary dependencies the class needs. This means that the container instantiates or get a reference to an existing instance of the object you are requesting and also provides all of the dependency objects by supplying them to the constructor of the object during instantiation. Another example uses MEF to inject a property: [Export(typeof(Person))] public class Person : ModelBase { public Person() { } private ILoggingService _loggingService; [Import] public ILoggingService LoggingService { get { return _loggingService;} set { _loggingService = value;} } private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; OnPropertyChanged("FirstName"); } } private string _lastname; public string LastName { get { return _lastname; } set { _lastname = value; [ 13 ]
The Silverlight Technology OnPropertyChanged(() => LastName); } } };
Through MEF, we can accomplish the same thing as with Unity or any other container. Both of these containers can provide the same effect, but they differ in what is required to get everything working. MEF requires you to use special attributes for your object composition. This means that you must have the ability to mark up any library that you want to use as part of your dependency injection scenario. If you don't have control of a third-party library, you may need to use another approach, such as Unity. In Unity, you are not required to add any attributes. If you want to code to contracts, you will need to register your interfaces with the Unity container. Unlike MEF, Unity only supports a single implementation of any interface to be registered. If you have multiple implementations with which you wish to work, you can use a special property on the attribute in MEF to expose named solutions. If you are interested in knowing if dependency injection framework is best for you, you should evaluate your core requirements, and then try and pick the one best-suited to your needs. If extensibility is key goal to your application, you may consider MEF being the better solution, as it was created to provide an easy way for extending applications where you have full control. Unity, on the other hand, is designed more just to support dependency injection. There are many more ways that you can use these features, but becoming aware of them and getting familiar is our main task for now.
Silverlight as a Web technology If you recall developing Visual Basic 6 applications or Windows applications in C++, you probably remember a common term, "DLL Hell." When you installed any application on your Windows computer, the installation process would need to register any DLLs that it needed. The problem with this type of registration is that you could have already installed a previous application that used an earlier version of the same DLL, and now you have just overwritten the registry entry with a new version. Next, when you try to access your earlier application, it would give you an error, not being able to find your DLL. If you ever wanted to remove an application from your system, you had to be careful that the uninstall process did not remove any DLLs on which other applications depended.
[ 14 ]
Chapter 1
Another side effect of deploying Windows applications was that it required installations on every client machine. This could become an administrative nightmare, especially if the product goes through several versions; each version requiring you to perform an installation on the client machine. With .NET, we were introduced the concept of "XCopy", and how you could deploy your applications without ever needing to register your DLLs. This made life a lot better but still required installations of the .NET Framework, and then your application assemblies. You still needed to create an installation package, and then require your clients to download or use an installation device to get the application installed on their machine. Silverlight really simplified this paradigm, in that you only had to install your application on a web server, and then all clients could browse to your Silverlight and run your application. Silverlight is a plug-in technology and it runs in and out of the browser. When you first try to run a Silverlight application, it performs a check to make sure that the targeted version of Silverlight is installed in the browser. If the browser contains the latest version, then your application is loaded. If you need the plug-in, you can click on the link provided and get redirected to Microsoft's Silverlight page for installing the plug-in. A nice thing about Silverlight is that when you need a new version, it will prompt the user and allow the user to install the latest, and then run the application. Also, the deployment model for Silverlight is pretty much just like what it would be for deploying a website. Silverlight also provides you a rich API that allows you to manage updates to your application. You can either automatically check for updates or provide the user with an on-demand check. This really improves the deployment model and gets us very close to the web deployment model. Silverlight is a "stateful" technology. Unlike typical web applications where they are "stateless", you don't have to write a lot of extra logic to maintain the "state" of your application. Just like programming in Windows Forms or WPF, we can keep the "state" of our application in memory. In our data-binding scenarios, we can use our "state" management to provide undo/redo scenarios. We can save the "state" of individual user settings and ensure that the settings are applied the next time the user accesses the application.
[ 15 ]
The Silverlight Technology
Asynchronous programming in Silverlight Silverlight is designed to keep the UI thread from blocking. This means that it doesn't allow us to make server-side calls that could potentially take a long time. Even showing dialog boxes in Silverlight happens asynchronously. This is actually good from our perspective, in that we never want to write code that would make the user interface appear not to be working properly. When we have code that either calls a web service or opens a dialog box, we need to either provide a callback method that will get fired when the process is complete or wire up an event. If we want to open up a dialog box that asks the user to confirm closing a screen, we would need to first fire off code that would show the dialog box and then, either in our callback or event, we would check what the user responded and program accordingly. This programming model can make your code more complex, in that you can no longer write your logic in a synchronous manner. Your logic will be spread across several methods and that can sometimes be hard to follow, especially if you need to enforce a specific set of workflow actions. Microsoft is currently working on making this programming model easier. The next version of the .NET Framework will more than likely contain the full version of the Visual Studio Async CTP (SP1 Refresh). This programming model allows us to pretty much write asynchronous code as if it were synchronous using a couple of new keywords Async and Await. This will help streamline asynchronous programming regardless of whether we are doing this in Silverlight or any other technology. Once you get used to using callbacks or event handlers, you will pretty much have a good handle on writing asynchronous code that communicates with any backend server or service. The next trick is keeping your code clean and readable.
Silverlight features Let's now take a look at what we get out of the box when building rich enterprise application using Silverlight. By the time this book is published, Silverlight 5 would have been released or pretty close to being released. We will cover the major pieces of Silverlight 5.
[ 16 ]
Chapter 1
Silverlight is a subset of Windows Presentation Foundation (WPF). Unlike WPF, you can't run Silverlight as a fully trusted Windows application. It has the concept of elevated permissions to allow us to access local assets on a computer, but it is still sandboxed and will not allow you to run malicious code, just like any other web application running in the browser. The same is true for any Silverlight application that is running out of the browser. The difference between in and out of the browser becomes even harder to distinguish with Silverlight 5. Previously, if you were running your Silverlight application out of the browser, you could request your application to become a "trusted application.". This provided you with several enhancements. Here is a short list of some of the features of a "trusted application": •
Ability to host a browser control in your application
•
Direct access to the My Documents folder directly without any prompting of the user
•
Full keyboard support in full-screen mode
•
COM Automation is fully supported allowing you to launch other applications on the computer
•
Access to USB components, e.g., a bar-code reader
•
Calling unmanaged code directly using PInvoke
All of the features are now available to you in the browser with Silverlight 5. The following is a sample application that Microsoft introduced to demonstrate a "trusted application" using COM to access a Blood Glucose monitor:
[ 17 ]
The Silverlight Technology
Here is another example demonstrating an out of browser "trusted application":
If you are looking to writing a rich media application, then Silverlight 5 definitely delivers great capabilities. •
You now have the ability to use the GPU to render high-definition video and improve the overall performance of your application. This is especially important with the rise of tablets and Netbooks being used.
•
TrickPlay allows you to play your video at different speeds, including performing fast-forward and rewind. You can even use audio pitch correction for up to twice the speed of normal allowing users to still watch their video without losing the audio quality.
•
User can now control media playback using remote-control support.
•
Digital rights management enhancements now allow you to switch seamlessly between media sources.
If you are trying to build rich enterprise line of business applications, the following improvements will definitely be a factor in wanting to use Silverlight 5: •
Multi-column text and linked text container allow you to control the flow of text across multiple columns.
•
Character spacing in the form of tracking/leading for precise text layout.
•
Use of Pixel Snapping for better text clarity.
•
Enhanced support of OpenType formats. [ 18 ]
Chapter 1
•
Support for Postscript vector printing for creating reports and documents, even creating virtual previews.
•
Support for double-clicking.
•
Type-ahead support in the ComboBox (Type-ahead means that you can now type a letter in the ComboBox, and it will find the first match that starts with that character).
The following screenshot shows some of the improvements of text in Silverlight 5:
Probably one of the biggest areas of improvement with Silverlight 5 is its rich data binding and MVVM support. Here is a list of some of the improvements: •
Ability to now add breakpoints in your XAML on your data bindings. Hopefully, this feature will also be added to WPF in the next release of .NET.
•
Implicit DataTemplates is a welcome addition that now allows the runtime to choose the correct DataTemplate based on type.
•
Ancestor RelativeSource allows us to walk the VisualTree and bind to parent or child controls based on their hierarchical relationship.
•
Styles now have the ability to have bindings in their setters for referencing other properties.
•
DataContext will now notify us when it is being changed through a new event, "DataContextChanged."
•
Markup extensions used in XAML allow us to have code run during the parsing of both properties and event handlers.
Some of the performance and graphics enhancements with Silverlight 5 include the following: •
Support for 64-bit operating systems.
•
Network latency is reduced by utilizing a background thread for networking. [ 19 ]
The Silverlight Technology
•
XAML parser improvements that have increased runtime performance and startup.
•
Graphics Processing Unit (GPU) accelerated 3-D application programming interface (API) allows for building rich visualizations.
•
Ability to render directly to the GPU using an immediate mode graphics API.
•
Internet Explorer 9-provided hardware acceleration is enabled in windowless mode.
The following is a screenshot of a sample application from Microsoft demonstrating the 3D capabilities of Silverlight 5:
Another cool feature in Silverlight 5 is the enhanced Window. Previously, Silverlight didn't support multiple top-level windows and if you wanted to have a popup, it always was bound by the physical constraints of the parent window. Now, you can use the Window class and have multiple top-level windows. This only works for Silverlight applications that are running out of the browser, but this gives you a lot of power and control when writing applications that can take advantage of multiple monitors.
[ 20 ]
Chapter 1
Client-side application development When developing Silverlight applications, it is important to remember that Silverlight runs on the client. This means that if you need any information from the server, you need to asynchronously make a call back to the server with your request. An advantage of client-side development is the fact that we can do some powerful things in Silverlight without ever needing to run client-side JavaScript or any other technology. Silverlight allows us to run Storyboards and other Behaviors and Triggers to make our application focus on a great user experience. We have seen some of the new capabilities and features of Silverlight 5 and how we can now tap into the power of the client GPU for some really nice graphics and animations. We also have the ability to interact with other Microsoft Office applications and make it look like Office is just an extension to our application; for example, creating emails, opening Word documents, or even building an Excel WorkSheet with charts and everything. When we build our rich enterprise application, we want to ensure that the user experience is truly engaging and allows the user to work in a quick and efficient manner. Part of that delivery is the ability to design and develop applications that act and respond behaviorally as we would expect anything in the real world. If we start to compare the paradigm of a user doing their job manually using documents and files, we can start to provide the same and hopefully better experience by providing sleek animations when certain behaviors are expected. We want a fluid user interface that reacts and displays information and prompts just as we would do in the real world. We don't mean that we should just take what the user did in real life and recreate it without thought or creativity; rather, we are saying that we believe that by following the natural physics of the real world and applying user intuitive effects, the application will get quicker buy-in and acceptance than just building a legacy battleship-gray forms application.
Reduced server load When we run Silverlight applications, a typical .XAP file gets downloaded on to the client machine. The application is then executed either in or out of the browser. If the application has been developed to support an out of browser experience, you can choose to run it out of the browser. Because Silverlight runs on the client, we don't have the same issues like that of a traditional web application. Typical web applications put all the stress on the web server, unless you are using something like client-side JavaScript. The processing power to run and render our applications now falls to the client machine. This is an advantage in that we can have some really powerful applications running without relying on a super web server that is required to do all the processing.
[ 21 ]
The Silverlight Technology
Silverlight is still a web technology. Even though Silverlight applications run on the client machine, it is deployed to a web application server. This really helps remove the added maintenance when dealing with WPF or Windows Forms applications that require some form of installation. When building Silverlight applications, you will still have a need for a server presence. One good example is that of data access. You can use technologies like Windows Communication Foundation (WCF). There are many flavors of WCF; you can use WCF RIA Services, WCF Data Services, plain old WCF operations, and OData.
Client-side state Probably one central aspect that makes web development complicated is the lack of state. Most websites are designed to be stateless, and it makes sense when you realize that if we tried to maintain state for all concurrent users accessing and using the application, your server would be overloaded. Sure, we need to provide caching and optimizations on the server regardless of what style of architecture that we are using but when we develop Silverlight applications, we get the added benefit of being able to use the client's memory and storage just like any other desktop application. You may be thinking that this is also possible with current technologies as well. Yes, you are right, but with Silverlight you can do all this in the exact same technology and language of choice without ever needing to import or download a library to let you work on the client. What we are saying here is that you have a lot of inherent efficiencies when you develop applications with Silverlight. You can still gain this momentum and inertia with web development as well, but there are a lot more moving parts and pieces that need to be put together as well as testing your code across all the target browsers you wish to support. In Silverlight, we have the ability to access local storage in the My Documents location on Windows and the Documents location on the Mac. This gives us the ability to create occasionally connected applications that can even run when our Internet connection is lost and then sync any changes that were made from our local storage back to a server.
[ 22 ]
Chapter 1
Cross-browser development simplified
Probably one of the most frustrating aspects of web development is the need to be sure that your code renders the same across all browsers. If you use Microsoft Expression Web, you can use the Super Preview feature that allows you to preview your code in various browsers. This helps a lot, but it is unfortunate that each browser potentially renders your hard work in a way that was not intended. We want our applications to be cross platform, because we want our users to be able to run our application from Windows or Mac, or any browser and have the same user experience. This is hard to do when just developing web applications that depend on independent browsers. Each browser can potentially render our application slightly different from the other. With Silverlight, because it is a plug-in technology, you don't need to worry about whether or not your application is going to look right using Internet Explorer or Google Chrome; we can be assured that it will just work. We can pretty much be assured the same experience between Windows and Mac operating systems as well. There are some things that we need to take when we are developing an application that is to run on both Windows and Mac OS. Silverlight has some advanced features that have been tailored to work with the Windows operating system. If you want to your application to run on the Mac as well, you need to take care not to use certain features, like Toast Notifications or COM Automation. Overall, Silverlight makes perfect sense if you are getting ready to build an enterprise line-business application.
Putting the pieces together Now that we've established that Silverlight is a premium platform for creating web applications and dashboards, let's see what it takes to get your environment set up for using Silverlight. The following list should get you started with building rich Silverlight applications: •
Visual Studio Requirement °° °° °° °° °° °°
Microsoft Visual Studio 2010 Microsoft Visual Studio 2010 Service Pack 1 Microsoft Silverlight 5 Tools for Visual Studio 2010 Service Pack 1 (optional) Microsoft Visual Web Developer 2010 Express Microsoft Visual Web Developer 2010 Express Service Pack 1 Microsoft Silverlight 5 Tools for Visual Studio 2010 Service Pack 1 (optional) [ 23 ]
The Silverlight Technology
•
Microsoft WCF RIA Services V1.0 SP2 Preview (optional)
•
Microsoft Expression Blend Preview for Silverlight 5 (optional)
•
Microsoft Expression Blend 4 (optional)
•
NuGet (optional)
•
Microsoft Silverlight Toolkit
We will be using Microsoft Visual Studio 2010 with Service Pack 1 for our development. If you want to use Microsoft WCF RIA Services, you can install the latest service pack that is compatible with Silverlight 5. Sometimes, it is easier to do our design work with Microsoft Expression Blend. You ought to either use the latest version that is compatible with Silverlight 5, or use their current released version that works with Silverlight 4. A tool that will really help you as you develop your solutions is the new tool NuGet. NuGet is a Visual Studio extension that allows you to install and update open source libraries and tools. If you have NuGet installed, you can then install the Microsoft Silverlight Toolkit or other packages, like Prism, Caliburn.Micro, Entity Framework 4, and so on.
Summary In this chapter, we took a look at the benefits of what Silverlight brings to the table. We reviewed the latest features on what Silverlight 5 will contain. We discussed the advantages of doing client-side development, and where it makes your development much easier by allowing to you to develop the whole application lifecycle without depending or using another technology. We discussed the reduced server load, even though Silverlight is a web-based technology. State management is simpler due to the fact that you are basically developing your application just like you would a Windows Forms or WPF application. When using elevated permissions, you can have direct access to the user's documents folder and transparently manage documents without needing to prompt the user. We then finished by examining how developing Silverlight applications really simplified the whole issue with crossbrowser support. Because Silverlight is a plug-in technology, you don't have to worry about whether your application will behave or look correctly across browsers. In the next chapter, our focus will be looking at how building dashboards fit in with Silverlight.
[ 24 ]
Overview of Dashboards and Silverlight We see dashboards everywhere in our daily lives. Whether we are driving in our car, crossing the street, or shopping in a grocery store, we are inundated with dashboards. In the car, the dash informs us of our speed, gas level, oil pressure, etc. Crossing the street, we see street signs indicating street names and hear crosswalk indicators. In the grocery store, signs indicate where food groups are located and what is contained in certain aisles. All of these signs and indicators are great examples of providing information to the user at the right time. Dashboards are part of a larger unit within technology named, Business Intelligence (BI). Business intelligence tries to sift through the wealth of data that resides in an organization and render it to the end user in the most appropriate medium possible. Reporting, spreadsheets, and OLAP cubes are some of the ways BI is accomplished within an organization. Dashboards typically are the first thing executives and managers see when they start work in the morning, and most likely the last thing they look at before leaving for the day. Providing good business intelligence is a very hard target to hit. It requires a coordinated effort across multiple departments and domains and can cause a lot of confusion. Good business intelligence can put an organization in a position where it can dominate in its demographic. What dashboards try to do is present pertinent information to the business user at the right moment and level as to where the business user can make actionable decisions based on that information. We stress the word information, because it is not just raw data that is being presented to the business. Many hours of investigation and discovery goes into identifying what is the correct level of information to be composed into the right dashboard element. Dashboards have come a long way since they were first introduced.
Overview of Dashboards and Silverlight
In this chapter, we will take a look at the evolution of dashboards. We will examine what makes a good dashboard and also what makes Silverlight the perfect choice for building your dashboard solution. We will cover the following topics: •
What are dashboards
•
Purpose of dashboards
•
Problems dashboards solve
•
Current state of building dashboards
•
When good just isn't good enough
•
Why should we use Silverlight
What are dashboards A dashboard is a meaningful representation of some aspect of your organization that enables you to take action. The action could be as simple as picking up the phone and calling a department to ask why production is low, or gathering your sales representatives together and encouraging them to make quota. A dashboard displays raw data from your organization in a manner that provides meaning. Hopefully, this raw data transforms into information for the user. A dashboard is concise and clear. It avoids cluttering and noises that may draw attention away from the important data points. A dashboard tends to have a theme as to what it is displaying, and most of the elements in the dashboard adhere to a common granularity. A typical dashboard is composed of many different pieces placed together to provide the whole picture. The following are a listing of the most common elements found in a dashboard: •
Score cards
•
Graphs
•
Gauges
•
Reports
•
Strategy maps
•
Tables
•
Charts
•
KPI
We will discuss each of these, but we will go into detail with the last three.
[ 26 ]
Chapter 2
Score cards are typically used for dealing with performance measurement of an organization. The score card is usually comprised of the actual metric data and also a target value for which a visualization is rendered to display whether or not you are on target. Graphs are very similar to charts, in that they are typical visual representations of your data within your organization. Gauges most closely resemble an automobile dash, as they are typical simple gauges indicating a single aspect of your company and where it stands in comparison with upper and lower thresholds. Reports are a category that can stand alone outside of dashboards, but they also can play an important role in authoring dashboard elements. Strategy maps are typically diagrams that visualize the primary strategic goals of an organization or department. A table is a simple representation of data in a tabular format. The data points are represented in raw form, and you may also encounter threshold indicators showing which direction the data point is trending. The following is a sample table:
A chart provides a rich representation of your data. Charts are typically in the following formats: •
Line
•
Area
•
Bar [ 27 ]
Overview of Dashboards and Silverlight
There are many other formats for charts but these can pretty much cover quite a bit of that which you are seeking. We will look at three different chart types over the same data to demonstrate how they look and are able to convey the information visually. An Area chart would look similar to the following:
Next, a Bar chart will contain rectangular bars representing certain values:
[ 28 ]
Chapter 2
Finally, the Line chart will look like this, connecting a series of data points:
An important thing to note about these different representations of the same data is that one of the chart types may speak to you or your users more than another. This becomes important as you evolve and mature your dashboard solution. Let's take a look at how a chart would look like with multiple series:
It is pretty easy to see which year had better sales during the first quarter. The use of colors and selecting the correct chart type can really help make this analysis easy.
[ 29 ]
Overview of Dashboards and Silverlight
Let's take a look at one last chart that includes thresholds:
Here, we see the average call duration for a help desk operator. We have an upper and lower threshold of 300 and 120 seconds correspondingly. With this chart, it is very easy to see who is above the upper threshold, who is on target, and who is below the threshold. A Key Performance Indicator (KPI) is typically one single data point with usually some indicator showing the current trend and whether or not we are in a good state, "green", in a questionable state, "yellow", or in a bad state, "red." The following is an example of a sample table with KPIs:
Based on this KPI, the threshold for each value was the following: •
Lower threshold – $100,000.00
•
Upper threshold – $200,000.00
[ 30 ]
Chapter 2
Now that we know and understand what the threshold value is, it is easy for us to understand what each icon means. We see that February was a very good month, and we had sales beyond our goal. We also notice that March was a weak month, and that we were even below our lower threshold. January was within range and is satisfactory. Armed with this information, we can now take action and act accordingly. When showing indicators, it is important to use color plus shape to help further convey the meaning of the data. It is also noteworthy that we don't see a lot of extraneous data in these examples. This is important, as we only want to provide meaningful data to the end user and nothing more. Enough theory, let's take a look at what you will be building throughout this book:
[ 31 ]
Overview of Dashboards and Silverlight
We will be building a dashboard based of the AdventureWorks database that is one of Microsoft SQL Server's most popular samples. As you look at the dashboard, you can see that we have a header section that has been reserved for filtering of our dashboard elements. We have date ranges for filtering both the start and ending dates. We have regions for defining which regions we wish to evaluate in our dashboard. Finally, we have product classes that come straight from our products table so that we can further filter based on a product. If we look at the first element on the top left, we see a simple table with the name of our financial indicators, a sparkline that basically shows a summary of the trend for the indicator, the actual value of the indicator, where it stands in comparison with its target value, and finally, a bullet-graph that shows the performance of the indicator. This simple table tells us quite a lot of information in a single viewing. The chart below the table maps out each region's sales from July 2001 to July 2003. At the right side of the dashboard, we have two similar tables that show product and customer information respectively. The product table shows the product name, sales amount, and a comparison as to how it corresponded to other products as a gradient bar graph. The customer table below is basically the same representation, but analyzing customers instead of products. As we can see, we can pack a lot of information by using dashboards and different visualizations on each piece of data.
Purpose of dashboards When we look at the automobile industry and how manufacturing has evolved, we still see a common theme that has stood the test of time. If we compared the dash of an antique vehicle and then looked at a modern dash, we would still see the same common pieces of information. It is these pieces of information that make the dashboard so important that we would not know what to do without one in our car. The purpose of dashboards in your organization is exactly the same; to make the use of them so important that you would not know what to do without them.
[ 32 ]
Chapter 2
The following is the dash of a 1980 Fiat Spider:
Now, we jump 27 years forward and look at the dash of a 2007 Chrysler Town & Country:
As we can see from the two different car dashes, not a lot has changed in what the driver needs to know while driving a vehicle. Sure, there may be new innovations, like GPS systems, but the bare necessities are still the same. In the previous examples, we were presented with four main pieces of information: •
Fuel level
•
Speedometer
•
Engine temperature
•
Tachometer
We also see our total mileage embedded in the speedometer. It is important to note that size is a key factor in notifying the driver what is more important. [ 33 ]
Overview of Dashboards and Silverlight
A dashboard delivers information to a user. Over time, this information can be turned into knowledge by the user, and with even further experience and more dashboards, wisdom. In a nutshell, this evolution can be displayed with the following diagram:
Wisdom Knowledge Information Data
At the base of the pyramid, a dashboard is nothing more than raw data. At this level, the data has very little relevance to the business and provides almost no intelligence. It takes the careful planning and understanding of the business domain to be able to be able to transform this data and make it meaningful information. Typically, this can be achieved by aggregating and grouping the data together so that analysis of the information provided can be accomplished at a glance. Sometimes it can be as easy as changing what type of rendering you wish to display. Over time, the dashboard data and then information will mature and become meaningful to users. Once a user becomes comfortable with the information they are analyzing, then knowledge can be extrapolated from the dashboard. This typically happens as patterns form, and the user can visualize these patterns and even predict when they will happen again. This makes the user very powerful and provides insight over the data. The user immediately sees when there are anomalies in the data and reacts correspondingly. Dashboards reach the final level when each dashboard item provides quick insightful information to the user. When a dashboard answers and identifies problem/opportunity areas in the business at a glance, you know that the dashboard has matured as the result of the business working over multiple revisions of the dashboard to ensure that it truly provides the information and knowledge necessary to see the health of the business. Finally, armed with the understanding and knowledge of the dashboard, a user can truly gain wisdom and make smart decisions. This typically is in the form of making inventory adjustments and forecast planning to be ready for future developments.
[ 34 ]
Chapter 2
Problems dashboards solve Dashboards solve many different problems. In healthcare, a dashboard could be as simple as an electrocardiograph (ECG) monitoring the heart rate of a patient. If we step back and look at this example, we can see that the monitor is tracking raw bits of data and mapping it out on paper in the form of a plot. If the data were stored in a spreadsheet, for example, and a physician was presented with just the raw data points, it would be much more difficult for the physician to identify any problems. Another potential problem with just looking at the raw data points is that they could be misinterpreted and cause the physician to make an erroneous decision. A simple plotting of the heart rate over time really seems to make much more sense. We can easily identify what is high and what is low based on the line being plotted. With training and knowledge, we can even see potential problems and make good decisions by just observing the plot. The following is an example of a digital dashboard of an ECG:
If we were to try and present this information in raw data form, it would be an extremely dense spreadsheet with multiple columns for each category, but our capacity for deriving information from such a volume of raw data would not provide much meaning.
[ 35 ]
Overview of Dashboards and Silverlight
Current state of building dashboards So, where are we now in the process of building dashboards? Dashboards typically tend to be an enterprise solution. It is either through some corporate strategy or IT strategy that dictates what business intelligence tool will be used for dashboards. Because dashboards fall under the umbrella of business intelligence, there are many ways to provide a viable solution for your business. The traditional solution was to have the dashboard solution embedded as part of your data warehouse strategy. While there is nothing wrong with this approach, it can be quite a bit of time before any business user sees any dashboards, because they are typically at the end of the data workflow. This is true for any dashboard strategy and it calls for taking a different approach to providing good dashboards in a reasonable amount of time. One such strategy is to build your dashboard solution not at the enterprise level, rather at the department level. Once your ETL and warehouse solution is ready as your central repository, you can move your current departmental dashboards but, until that happens, you can at least have dashboards delivered and proven at the departmental level. This makes sense due to the fact that validation and confirmation of the dashboard will need to happen at the warehouse level regardless. When we look at the environment for building dashboards, we only see a few contenders: •
Desktop—Windows Forms, WPF
•
Web
•
Silverlight
A desktop solution will provide the richest user experience, in that you can develop really good applications that will run natively on the user's operating system. The limitation with providing a desktop solution is that it only targets a single operating system. The organization that uses this approach must already have governance that dictates that the dashboard solution will only run on the predefined operating system. Another potential problem with this approach is deployment. In .NET we have ClickOnce to help in the deployment process of desktop applications. This helps in easing the overhead of application maintenance but still can be an issue in certain environments. A web solution will provide the most ubiquitous solution, being browser based. However, it also has the problem of being browser based. The complexity of developing a truly rich application will require AJAX or jQuery to make the application responsive without post-backs. Also, the application will have to be tested on multiple browsers and versions of browsers to ensure consistency and accuracy of the application. The deployment model is nicer in that nothing has to be deployed to the client and only deployed to the server. [ 36 ]
Chapter 2
A Silverlight solution will provide a rich user experience like that of a desktop solution. Being a plug-in solution, you are pretty much guaranteed that the application will look the same on Windows or on the Macintosh and on any modern browser. The deployment model follows the web deployment model in that you only deploy to the server. The Silverlight application is then downloaded to the client.
When good just isn't good enough Probably one of the biggest arguments you will hear is that you can deliver a good dashboard experience building a web-based solution. Let's take a look at this. Building a web-based solution has several factors; let's take a look at what is involved at each layer: •
Presentation layer °° °° °°
•
Business layer °°
•
HTML JavaScript, jQuery, AJAX Cascading Style Sheets (CSS) C#, VB.NET, JavaScript
Data layer °°
C#, VB.NET, JavaScript
Let's look at these data points graphically as well: Users Presentation Layer (HTML, JavaScript, jQuery, AJAX, CSS)
Business Layer (C#, VB.NET, JavaScript)
Data Access Layer (C#, VB.NET, JavaScript)
DB 1
DB 2
Cloud Service
[ 37 ]
Overview of Dashboards and Silverlight
In .NET, at the presentation layer, we have two main camps: ASP.NET Web Forms and ASP.NET MVC. Depending on which one we choose further dictates what third-party control suite libraries to which we have access. With ASP.NET MVC being a newer technology, there are not as many libraries from which to choose. After we have decided which technology to use, we still have to create the user interface with HTML and controls. If we want a modern web application that is user friendly, we are also going to need to use AJAX or jQuery to reduce the page-level post-backs that occur. The JavaScript may either be mixed in with the HTML mark-up or stored in a separate file. Finally, we have CSS to provide styling of the elements on the page. When we look at the business layer, we also have to option to develop this in C#, VB.NET, or completely in JavaScript as well. We may need to have both server-side and client-side validation and processes. Finally, we have our data layer and model. This could be simple Plain Old CLR Objects (POCO) in the form of data transfer objects (DTO), or it could be in the form of JSON. We could also have a combination of DTOs and other POCOs with business logic embedded in the classes. Finally, we could have JSON as our transport mechanism, which is very light compared to an XML payload. Another thing to note about web development is that you are constrained within the bounds of a browser.
Why should we use Silverlight? So, now we have come to the argument as to why we should use Silverlight. For those of you who have had some experience with Silverlight, this should be an easy exercise. Let's get started, Silverlight allows us to do some pretty powerful things that are just near impossible or require a lot more time and effort to get accomplished. Because it is a XAML technology, you can declaratively define what you want the user interface to look like all using an XML-like syntax. Silverlight lets you build rich user interfaces without the need to have multiple languages involved in getting it setup. Writing your application in a single language like C# makes building applications really simple. Another factor to know is that Silverlight is a vector-based technology. Like Flash, Air, or Flex, you can build really nice applications, but it is the rich tooling and time to market that makes Silverlight really shine in this area. Let's take a look at what it takes to build a Silverlight application: •
Presentation layer °°
XAML [ 38 ]
Chapter 2
•
°°
Behaviors/Triggers
°°
DataTemplates
°°
Styles
Business layer °°
•
Data layer °°
•
C#, VB.NET C#, VB.NET
Web host
In the presentation layer, we have a lot of parity with web development, but with much less complexity. In Silverlight, we have a single mark-up language and semantic from which to develop our user interfaces. JavaScript is not required to develop rich visualizations. We have the opportunity to use Behaviors and Triggers to help us follow recognized design patterns, such as Model-View-ViewModel (MVVM). We also have the ability to call static resources, like styles and data templates, that really gives us a lot of flexibility when we architect our screens. Styles provide a rich environment where we can inherit from base styles or override them, depending on our user requirements. In the business layer, we typically use POCOs combined with ViewModels to perform our data binding to the Views. The ViewModel encapsulates all of the behavior and interaction required for a given view. Client-side validation would reside here or be accessed via a service. This leads us to having the consistency of a single language for our development, unlike that of the Web. Finally, our data layer is quite similar to that of the Web. In fact, it is possible to have the same data layer servicing both Web and Silverlight applications. The objects are typically POCOs, DTOs, or JSON. You will also encounter object relational mapping (ORM), such as the Entity Framework, Linq-to-SQL, or even NHibernate. In Silverlight, you also have a rich data binding experience that not only makes building applications easy, but also facilitates testing. Data binding alone really makes the development life-cycle much easier and nicer when comparing it with standard Windows Forms or Web development. Silverlight is asynchronous in nature, and this greatly improves the user experience when performing operations that are client/server such as data access or long-running processes.
[ 39 ]
Overview of Dashboards and Silverlight
Silverlight controls are considered "lookless", in that you are able to change the control template for a control. Some examples of this are restyling the button control to have a completely different appearance. Another example is restyling the appearance of radio buttons like a TabControl. These are all very simple and would require a lot of coding and effort using any other technology. This gives us a very powerful platform to build very nice dashboard solutions. Because of its declarative nature, Silverlight provides an excellent means for generating user interfaces dynamically. We have the XamlReader.Load(...) method that allows us to pass in a string argument that represents the XAML, and the runtime will create an object based on the mark-up XML. This provides some very powerful scenarios when we need to swap out behaviour or dashboard types on the fly. When using this approach, it is important that you refrain from wiring up events in the traditional manner. If you were to wire up a button click event, the event handler would be exposed in the code-behind for the XAML file. Because there is no code-behind when you use XamlReader.Load(...), you cannot wire up events this way. The following is an example of what would NOT work using XamlReader.Load(...):
However, it is possible to use Behaviors and Triggers to accomplish the same thing in XAML. See the following code snippet: Using these namespaces at the root of the file: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System. Windows.Interactivity" xmlns:mei="clr-namespace:Microsoft.Expression.Interactivity. Core;assembly=Microsoft.Expression.Interactions"
Using DataTemplates and a DataTemplateSelector is another route that you can use to switch between dashboard types. Silverlight does not have this feature natively, but it is fairly easy to define your own selector class and use it. Most of the third-party control vendors already have their own version of a DataTemplateSelector, and thus it pretty much alleviates the need for you to roll your own. [ 40 ]
Chapter 2
Animations are another area where Silverlight is simple to use. You can create VisualStates and have animations using Storyboards, and then use the VisualStateManager to trigger which state to which you wish to go. The level of effort to build really nice animations in Blend is extremely easy. In fact, Blend does an excellent job as far as providing you some very advanced animation functions that is simply a matter of setting properties. The ability to reuse stock effects makes it very convenient and easy to build very nice, polished applications. It should be noted that Microsoft Expression Blend is a designer-friendly tool that can work in conjunction with Microsoft Visual Studio. It is an excellent tool that allows you to design a very engaging user interfaces. If you are a designer or new to Blend, you can compare it with Adobe Fireworks. The biggest advantage with Blend is that it generates the XAML for you, where Firework's assets would need to be imported. You will see quite a bit of similarity between mnemonics and the overall behavior with both Blend and Fireworks. Blend also offers some rich components that make it a unique offering when designing your applications. If you are building standard business applications and have data-bound screens, you can use a sample data from Blend to provide you a rich look and feel of your screen without ever needing to run the application. All this can be achieved while you are designing your screens. Another key factor with Blend is the ability to build applications rapidly that follow a certain workflow. This can easily be achieved by using SketchFlow. SketchFlow is a wire frame or paper prototyping tool inside of Blend that allows you to not only mock up your application, but also collaborate with your clients as you iterate through your development process. These and many more features of Blend really make it powerful compliment to Visual Studio when you are building your Silverlight applications. If you are familiar with Fireworks, you will see a lot of similarities and find the transition fairly easy.
Summary In this chapter, we discussed the definition of dashboards. We went into detail analyzing different views for the same data. We also looked at the purpose of dashboards and how they are meant to provide information and convey knowledge to the end user. We evaluated some sample scenarios where dashboards provided a much better venue than solely examining raw data. Next, we shifted gears and looked at where Silverlight was clearly the best solution for building rich, dynamic dashboard solutions. We saw the limitations and complexity of using traditional web-based solutions. In the next chapter, we will look further at Silverlight design and development tools. We will examine the two best development tools on the market: Microsoft Expression Blend and Microsoft Visual Studio 2010. [ 41 ]
Silverlight Design and Development Tools Now that we know what Dashboards are and have a good understanding of how to use them, it is time to look at the tools necessary to create them. In this chapter, we will examine Expression Blend and Visual Studio 2010. We will focus on what it takes to build Silverlight applications with Blend and Visual Studio. Here are the topics we are going to cover: •
Blend strengths and weaknesses
•
Visual Studio strengths and weaknesses
•
Visual States
•
Storyboards
•
Sample Data
•
Templates
•
Visual Studio
•
Debugging
•
Developing for Silverlight
•
Project management
Silverlight Design and Development Tools
Blend strengths and weaknesses
Microsoft Expression Blend is an user interface designer that focuses mainly on the designer aspect of software development. It allows you to quickly prototype good looking user interfaces in a manner that requires almost no coding. If you need to code you can do this in Blend, but Microsoft Visual Studio is the better tool when it comes to writing custom code. What makes Blend a great compliment to Visual Studio is that it really does try to focus on the design aspect of software development. Visual Studio has its strength in the development community, and typically you can use both tools to get your job done. If you have the pleasure of working with designers, you can achieve great synergies by developing the application in parallel with your designers. Let's focus on the strengths and weaknesses of using Microsoft Expression Blend. At the heart of it, Blend was created to appeal to designers more than developers. If you look at Blend, you see an application that is very good looking. You see a nice interface that makes designing applications very easy. When we are designing a screen and we want to change the template of a given control, nothing beats Blend as far as gaining access to a control's template. If we want to create some visual states, again Blend makes it very easy for us to record what we want to happen for every state. Blend provides us with the ability to add sample data to our project so that we can preview our screens without ever needing to go through the whole build and run F5 lifecycle. On the flip side, Blend does allow us to look at XAML, but we have limited editing support. We even have a bad experience if we want to write code in Blend. Another possible issue with Blend is that it runs the applications that you are authoring in the same application domain where it runs itself. This could be a problem, as there is no way for it to unload any of your assemblies, and if you are building a very large application, you could potentially run out of memory. The following is the splash screen you are presented with when you start Microsoft Expression Blend:
[ 44 ]
Chapter 3
You are then presented with a dialog to allow you to open existing projects or create a new one. If we decide to create a new Silverlight project, here is what Blend presents to us:
As you can see above, the MainPage.xaml file is loaded and waiting for you to start designing this screen. The Assets tab is selected so that you can select what controls to use on the screen. If you want to test the screen, you could easily drag a TextBlock onto the designer surface, and update the Text property with something like, "Hello World", and then press F5. The following is what you would get:
[ 45 ]
Silverlight Design and Development Tools
Pat yourself on the back; you have just created your first Silverlight project in Expression Blend.
Visual Studio strengths and weaknesses When it comes to writing programs and a development experience, Visual Studio is probably the most popular editor on the market. When we further constrain our view to editors for the Microsoft stack, it even becomes more compelling, Visual Studio provides one of the best experiences when writing code. The editor provides you intellisense, and it also gives you syntax highlighting. You can start your own web project that hosts your Silverlight application and debug a service call from the client to the server and then back to the client again. While it is a great editor, it still has a long way to go as a designer. Visual Studio wanes compared to the rich design time of Blend. The designer in Visual Studio, "Cider," still has quite a few stop gaps that you can only do in Blend. Viewing the default template for a given control is one such workflow that forces you to switch over to Blend. Microsoft is working hard to further reduce the gap between Blend and Visual Studio. Hopefully, the next version of Visual Studio will be even more powerful and incorporate more of what makes Blend a strong editor without losing the appeal to regular coders. The following is the splash screen in Visual Studio:
[ 46 ]
Chapter 3
Once Visual Studio has loaded, you are presented with a Start Page that allows you to create new projects or open existing ones. Let's load the same project as we did in Blend:
It is possible to open a Visual Studio project from Blend. You only need to select the Projects tab, and then right click the solution or any XAML file. You will be presented with a context menu that will allow you to edit the project in Visual Studio, as seen in the following screenshot:
[ 47 ]
Silverlight Design and Development Tools
From Visual Studio, you can also switch back to Blend. In the Solution Explorer, simply right-click any XAML file, and you will be presented with a context menu that will allow you to open the file in Expression Blend, as seen in the following screenshot:
Visual States As you begin authoring your controls in Visual Studio and Blend, you will want to have your control as user-friendly as possible. This would imply that you will need standard behaviors or cues to happen to your control as state changes. This feature is called, "Visual States.". Let's examine the Button control and take a look at what it has in the form of Visual States. To access the States of a control, we need to edit its template. To do so, we need to right-click the Button control, select Edit Template | Edit a Copy, as shown in the following screenshot:
[ 48 ]
Chapter 3
Selecting the States tab, we can see what has been defined for the Button control:
Looking at the image above, we see that the Button has two Visual State Groups: CommonStates and FocusStates. Within each group, we see a set of states. Each of these states can have behavior attached so that something happens when the state is triggered. Let's change the coloring of the MouseOver and Pressed states:
[ 49 ]
Silverlight Design and Development Tools
The Normal state is the default look and feel for the Button. Typically, we will define what we want the control to look like in its normal state outside of the State manager, and then just create a Normal state so that we can programmatically go back to the Normal state. Now, let's see what happens when we modify the MouseOver state:
All that we changed in this state is the background. We basically want the button to have a yellow tint when our mouse hovers over the Button control. Next, let's modify the Pressed state:
[ 50 ]
Chapter 3
If you look again, you can see that we just made the background property of the Button control bright yellow. When you have finished modifying the states of a control, just click on the up arrow under the Objects and Timeline section, as shown below, and it will take you back to the normal editor:
Press F5 to test the new changes you made to the button at runtime. You can now test the changes by hovering over the button with your mouse, then clicking on the button, and finally releasing and moving the mouse away from the button.
Storyboards In the previous example, we took a look at the Button control and modified the MouseOver and Pressed states. We let Blend do all of the work for us by recording our mouse clicks. Now, let's take a look at the template in XAML and see what is really happening. We will discover that each state simply triggers a Storyboard. Let's take a look at the XAML snippet for the MouseOver state:
As you can see from the previous code, the VisualState does nothing more than create a Storyboard. The first thing that we see here is that we are changing the Opacity of the BackgroundAnimation target from 0 to 1 by using a DoubleAnimation. Next, we see that we are changing the Background property of the BackgroundAnimation target and setting it to the value of #FFCABF47.
[ 51 ]
Silverlight Design and Development Tools
Storyboards are very powerful, and we can either use them like we see here with VisualStates, or we can call them programmatically. It is through Storyboards that we provide all the nice user friendly animations in our controls and applications. This is one of the key features that really helps us deliver rich dashboard solutions. We can use Storyboards to define elegant animations. For example, we can define a rich loading animation to show that our dashboard is pulling its data from a server, or we can have some simple scale and rotate transforms to further give the user the feeling of an interactive dashboard. Remember that we use Storyboards to engage the user and draw attention towards our dashboards. Our goal is not just to create "noise" and distract the user. As you play with Storyboards and tune how they work in your applications, you will start to appreciate a balance between your screen and the animation.
Sample Data A great feature in Expression Blend is the ability to create sample data. This provides us with the ability to have design time data so that we can minimize the workflow for testing to see how our screen and controls are going to look at runtime. If you are developing your applications using the Model-View-ViewModel (MVVM) pattern, you need to use the View first approach, or make sure that your implementation is what we would call "Blendable" to be able to see your data. Let's take a look at how we can create some sample data. 1. To add sample data, select the Data tab, and then click on the icon that looks like a database with a plus symbol on the bottom right. 2. Once we click on the button, we are presented with the following context menu:
[ 52 ]
Chapter 3
3. After we choose New Sample Data, we are then presented with the following dialog:
4. We will just leave the default values here for our example. Clicking the OK button finally gives us some sample data. 5. We will modify the collection provided with the following look:
6. Each property has ability to be one of the following types of data: °°
String
°°
Number
°°
Boolean
°°
Image
[ 53 ]
Silverlight Design and Development Tools
7. If we select String as our type, we can then choose more formatting, as shown in the following screenshot:
This makes using the sample data feature from Expression Blend very powerful in that it gives us not only sample data, but it allows us to format it in a way that makes sense from our user interface's perspective. That's all you need to do to get your sample data ready. We can even look at what the sample data will look like by clicking the edit button to the right of the Collection in our sample data:
We are then presented with a dialog that shows us sample values. We are able to edit and modify the data to exactly how we want it to show up in our controls.
[ 54 ]
Chapter 3
Templates Now that we have created some sample data, let's take it a step further and display that sample data in a ListBox. The following is a screenshot of our sample data definition and a single ListBox on our design surface:
[ 55 ]
Silverlight Design and Development Tools
In order to get the ListBox to be bound to the sample data, we simply drag the collection over to the ListBox, as shown in the following screenshot:
Once we drop the collection on the ListBox, we instantly see data in the ListBox:
Now, let's lift the hood and take a look and see just what exactly Blend did to help us out:
[ 56 ]
Chapter 3
A lot is going on here that we got from a simple drag-and-drop operation. If we break it down into smaller pieces, we see that the DataContext of the Grid control is being set to a static resource of SampleDataSource. We recognize this object as our sample data object that we defined in the previous section. Next, looking at the ListBox, we see two key properties: •
ItemTemplate
•
ItemsSource
The ItemTemplate gives us the ability to define the look and feel of each individual item in the ListBox. The ItemsSource allows us to tell the ListBox what collection to use as the source of its items. We are now at the resources section of the XAML. Here, we see a DataTemplate defined with a Key of "ItemTemplate". As we look at this DataTemplate, we see that it is composed of a StackPanel. The StackPanel hosts a TextBlock for each property that is exposed in our sample data. Let's modify this template just slightly to make it a little nicer: [ 57 ]
Silverlight Design and Development Tools
If you refer to the previous image, you see how the default template looks. We are using some basic features in graphic design to help us format this data to become easier to read and understand. When we present the Name property, we also modify the size of its font so that it is slightly larger than the rest. Next, we do a little formatting trick to put the Age property on the same line as the Name property. We set the font size of the these elements to FontSize of 10. This is just enough to give the user an intuitive understanding of what the information means. Next, we put the Email property on the next line and also set the style of font to "Italic". Finally, we add the Phone property, but we use the default formatting. Now, we can compare the subtle differences between the two DataTemplates. If you are like us, you will agree that the second one looks better than the original, and it didn't take that much effort to modify it. As we are already bound to data, if we switch our view back to the designer, we will be able to visualize what we did to the DataTemplate:
As you can see, we can do a lot with DataTemplates. We can also change the whole look and feel of a control like we did previously with the Button control by modifying its ControlTemplate. As you play around with these template features, you will start to realize the potential of creating some really nice user interfaces.
[ 58 ]
Chapter 3
Visual Studio We have spent quite a bit of time in Expression Blend; let's shift gears and get familiar with Visual Studio. The following is a screenshot of the sample project that we have been using throughout this chapter:
Within Visual Studio, we can basically manage the whole lifecycle of our application development. We manage our project typically through the Solution Explorer. There we can and add and remove project items. It is here where we would add new screens and controls for our application. We can run our application by pressing F5. If we press Ctrl+F5, we run the application without debugging.
[ 59 ]
Silverlight Design and Development Tools
Debugging Writing code doesn't always go perfectly, and sometimes we need a little more help than just pressing F5 and trying to figure out what is happening at runtime. With Visual Studio, we are provided a very mature debugging environment. Also, if we have written any diagnostics code, we are able to see it in the Output window. Let's first take a look at outputting information to the Output window at runtime. The following code snippet demonstrates sending text to the Output window when creating the MainPage object as well as when the MainPage has been loaded: using using using using using using using using using using
System; System.Windows; System.Windows.Controls; System.Windows.Documents; System.Windows.Ink; System.Windows.Input; System.Windows.Media; System.Windows.Media.Animation; System.Windows.Shapes; System.Diagnostics;
namespace SilverlightApplication1 { public partial class MainPage : UserControl { public MainPage() { // Required to initialize variables InitializeComponent(); Debug.WriteLine("Creating MainPage..."); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { Debug.WriteLine("MainPage loaded..."); } } }
[ 60 ]
Chapter 3
When we run the application, we see the following in the Output window:
If we want to debug the UserControl_Loaded method, we only need to press F9 or click on the far left side of the editor as shown in the following screenshot:
When we run the application, we will break at our breakpoint and be able to view property values at that point in time:
The Locals window gives us a view of all available variables in the scope in which we are currently located.
[ 61 ]
Silverlight Design and Development Tools
You can go as far as writing conditional breakpoints so that they will only fire when the given condition is met. This can be achieved by right-clicking your breakpoint, as shown in the following screenshot:
Once you click on the Condition menu item, you are presented with a dialog. You can then type in your expression you want the debugger to track and fire only when it is true. Alternatively, you can have the debugger fire the breakpoint when the value in your expression has changed.
Finally, once you have defined your condition, you breakpoint will look slightly different from a standard breakpoint, as shown in the following screenshot:
[ 62 ]
Chapter 3
Developing for Silverlight There are a couple of things to keep in mind when developing for Silverlight. The first thing to remember about Silverlight is that it is an asynchronous technology. Silverlight was designed with the user as a first-class citizen. If you haven't done asynchronous programming before, it can seem a little complex developing applications in Silverlight. If you have a lot of business rules that are dependent on processes or data being returned from the server, you will need to have a good handle of asynchronous programming. To give you a good reference, let's walk through a simple example. Perhaps we have a screen that is a simple master-detail. We have to display a DataGrid that shows Orders. If we click on an Order, we display the OrderDetail information for that given record. We also have a simple Web Service that exposes us to methods that allow us to get Order records and another that takes in an OrderId and returns an OrderDetail record. When programming with Silverlight, there is no way for us to make a synchronous call to the Web Service and get our data. We have to use the asynchronous paradigm which is typically is represented with a "BeginXXX/EndXXX" pair of methods. Note that the "XXX" refer to the method name, for example, BeginGetOrders(). If we use Visual Studio to create the web proxy to the Web Service, all the methods for doing this are provided for us. As you can see, our code logic can get messy very quickly when we need to have a workflow that requires things to happen in a certain order. We no longer can write synchronous code and visually step through it. Now, we need to begin our request, and then jump to a callback method that will be fired once the operation is complete. If we have further process that needs to happen, then we repeat the previous steps of invoking our web request and then jumping to the other callback method to continue. We do this so that we can ensure that we provide the end user with a good experience. We believe that this is a good decision by the Silverlight team, but it does add to our code complexity. Currently, there really is no production-friendly help for asynchronous programming from Microsoft. There are several frameworks that try to help you make asynchronous programming synchronous like Caliburn.Micro, but that is beyond the scope of this book. There is also a new technology that is currently available as a Community Technical Preview (CTP) named the Async CTP. You can download and play with it today, but it probably won't be ready until the next version of Visual Studio and .NET are released. Apart from Silverlight favoring asynchronous programming, you must also be aware that a Silverlight application is deployed as a .XAP extension. This is really nothing more than a ZIP file with the contents of the application embedded in it. A great guidance for WPF and Silverlight composite applications is provided by the Patterns and Practices team at Microsoft named "Prism", which allows you to download a XAP file on demand. [ 63 ]
Silverlight Design and Development Tools
Here are links to all the references mentioned: Caliburn.Micro – http://caliburnmicro.codeplex.com/ Async CTP – http://msdn.microsoft.com/en-us/ vstudio/gg316360 Prism – http://compositewpf.codeplex.com/
Project Management Visual Studio alone has some great project management tools. If you have Team Foundation Server (TFS) set up, you can use agile templates or customize them to what makes sense for your own environment. Before we go further, let's breakdown what TFS does out-of-the-box and take a look at other alternatives available to you from the community: •
Source Control
•
Unit Testing
•
Automated builds/Continuous Integration
•
Project Management
•
Collaboration
For source control, you may want to use a distributed source-control solution. Take a look at Git or Mercurial, and then cloud-based hosting solutions like github or bitbucket. If you still want to know which files have changed or not in Windows Explorer, you can use TortoiseGit or TortoiseHg. Probably the most popular unit testing framework right now is xUnit.net (xUnit. net—http://xunit.codeplex.com/). More than anything else, it is important to pick one that suits your team's needs and works with your environment. In the area of automated builds and continuous integration, we see TeamCity and NAnt. TeamCity – http://www.jetbrains.com/teamcity/ NAnt – http://nant.sourceforge.net/
Project management can be controlled using the project management components of Bitbucket. You could also look at JIRA, TeamCity, or Unfuddle. [ 64 ]
Chapter 3
As far as collaboration goes, Bitbucket, TeamCity, and Confluence all provide great Wikis and collaboration tools to help you better communicate with the rest of your team. Again, your team's environment will dictate which tools you want to use. There are so many good products and free ones for small teams on the market that it doesn't make sense not to use one of them. TFS (Team Foundation Server—http: //msdn.microsoft.com/en-us/vstudio/ff637362) is a great tool, but sometimes can bog down your development box when all you really want to do is write code. It is best to take a look at several offerings and then choose the one that best fits your team's requirements. Here are links to all the references mentioned: Git: http://git-scm.com/ TortoiseGit: http://code.google.com/p/tortoisegit/ github: https://github.com/ Mercurial: http://mercurial.selenic.com/TortoiseHg http://tortoisehg.bitbucket.org/ bitbucket: https://bitbucket.org/ Jira: http://www.atlassian.com/software/jira/ Unfuddle: http://unfuddle.com/ Confluence: http://www.atlassian.com/software/confluence/
[ 65 ]
Silverlight Design and Development Tools
Summary In this chapter, we discussed the strengths and weaknesses of both Visual Studio and Expression Blend. We looked at VisualStates and what it took to make modifications to a Button control. We saw that a VisualState was simply a wrapper for calling a Storyboard. We looked at what we could do with Storyboards and how we could make really nice, fluid applications by using Storyboards before examining the templating capabilities of Silverlight. We reviewed what we could do with ControlTemplates from previous examples, and then looked at writing a custom DataTemplate for ListBox items. We discussed the power and flexibility of Visual Studio as a development platform, and then moved on to examine how we could perform debugging inside Visual Studio. Armed with this knowledge, we looked at some basic assumptions when it comes to writing Silverlight applications. Finally, we wrapped up with discussing the administrative side of application development by talking about tools and products available to manage your whole development lifecycle. In the next chapter, we finally dust off the cobwebs from our keyboards and get started building our first dashboard.
[ 66 ]
Building a Basic Dashboard In the previous chapters, you were introduced to the technology and tools that are required to build a Silverlight dashboard application. We will now build upon that knowledge as we walk through the process of creating a dashboard application, how to use the Model View View-Model (MVVM) pattern, and how to customize the user interface to better showcase the Key Performance Indicators (KPI) you want to display in your dashboard. In this chapter, we will cover the following topics: •
Creating a new Silverlight project
•
What is the MVVM pattern
•
Building a dashboard application
•
Customizing the UI to better showcase Key Performance Indicators (KPI)
Creating a Silverlight Dashboard Application Now that you understand the technology and tools that make Silverlight tick, it's time to build your first Silverlight dashboard. We will walk through how to create a new Silverlight project and set up the dashboard user interface.
Building a Basic Dashboard
To create a new Silverlight dashboard: 1. Open Visual Studio 2010. 2. Select File | New Project. 3. Expand the C# node. 4. Under the Silverlight project list, select Silverlight Navigation Application. If you do not see the Silverlight project types listed, most likely you are missing the Silverlight 5.0 Tools for Visual Studio 2010. You can download the tools from the main Silverlight site: http://www.silverlight.net/getstarted/.
[ 68 ]
Chapter 4
After you enter the project/solution name and select a location to store your project, the New Silverlight Application dialog will appear. This dialog allows you to define the host application and version you want to use to build your Silverlight Dashboard application.
After you click Ok, you should compile and run the newly created Silverlight project. This will ensure that the project was properly set up before we move onto the next step. For our first Silverlight Dashboard, we will be using a Grid and Chart to display data stored in an XML file that we will download from the host web project. In order to use these controls, we need to make sure the necessary references are added to our Silverlight project. Open the solution explorer in Visual Studio, and expand the references node under the Silverlight project. Right-click on the reference node, and select Add Reference. When the Add Reference dialog appears, add the following references: •
System.Windows.Controls.Data
•
System.Windows.Controls.DataVisualization.Toolkit
[ 69 ]
Building a Basic Dashboard
If you do not see the reference for Data Visualization, then you need to download the Silverlight 4.0 toolkit from codeplex: http://silverlight.codeplex.com/
What is the MVVM pattern In order to display data in our dashboard application, we need to take a moment and explore how data binding works in XAML and how it relates to the Model View View-Model (MVVM) pattern. One of the key aspects of Silverlight and XAML is its rich data binding support. In XAML, you use the binding keyword to set up one or two-way data binding to the datacontext of the view. To define the datacontext for a view, you can databind it in XAML to a static reference or in the view's code behind, and set it to an instance of object, e.g., a View-Model. In addition to data binding the data displayed in a textbox and listbox, you can set up buttons to bind to commands and use behaviors to extend the data binding capabilities of XAML. Here is the XAML for data binding a TextBox and ListBox. You set the Mode=TwoWay so that any changes the user makes are automatically propagated to the View-Model. To data bind a ListBox, you set its ItemSource to a collection type.
[ 70 ]
Chapter 4
To set up command binding, set the Commandproperty for a Button to an ICommand exposed by your View-Model. You set the CommandParameter property to pass a parameter value to a command:
MVVM pattern is based on the separation of concern principles of the Model View Controller (MVC) pattern. To use the MVVM pattern, you need to define three separate loosely coupled components to handle the use cases of your application. The View (XAML and Code Behind) should focus on displaying data to users; the Model represents the business behaviour and attributes of the application, and the View-Model takes on several responsibilities, including exposing the properties (Data and Command) you will bind to in XAML, responding to user actions, tracking UI state (e.g., Selected Item), and abstracting the interworkings of the Model from the view.
When building an application using the MVVM pattern, it's always a good idea to start out with a base view model class. This class will contain the common functionality all View-Models need for notifying their views when one of their attributes changes. This is done by implementing the INotifyPropertyChanged interface. When data changes in your View-Model, the PropertyChanged event notifies bound dependencies of the change so that they might update accordingly. usingSystem.ComponentModel; namespace Chapter4.ViewModels { publicclassBaseViewModel : INotifyPropertyChanged { publiceventPropertyChangedEventHandlerPropertyChanged; protectedvoidSendChangedNotification(stringpropertyName) { if (this.PropertyChanged != null) {
[ 71 ]
Building a Basic Dashboard this.PropertyChanged (this, newPropertyChangedEventArgs(propertyName)); } } privatestring _viewName = string.Empty; publicstringViewName { get { returnthis._viewName; } set { if (this._viewName != value) { this._viewName = value; this.SendChangedNotification("ViewName"); } } } } }
Another handy class to create is the delegate command. This makes it easy to build commands that are bindable from XAML. The delegate command implements the ICommand interface and uses .NET delegates to notify a view model when a command has been invoked. To use a command, you need to expose it as a property off over your view model and set up the binding for a button or hyperlink to the command. Microsoft and other third-party developers offer frameworks that include helper classes similar to the delegate command that make it easier to build MVVM-based applications. Microsoft Prism: http://compositewpf.codeplex.com/ MVVM Light: http://mvvmlight.codeplex.com/ Caliburn: http://caliburn.codeplex.com/ using System; usingSystem.Windows.Input; namespace Chapter4.ViewModels { publicclassDelegateCommand : ICommand { [ 72 ]
Chapter 4 publiceventEventHandlerCanExecuteChanged; privateFunccanExecute; privateActionexecuteAction; privateboolcanExecuteStatusCached; publicDelegateCommand(ActionexecuteAction, FunccanExecute) { this.executeAction = executeAction; this.canExecute = canExecute; } publicboolCanExecute(object parameter) { boolcanExecuteStatus = this.canExecute(parameter); if (canExecuteStatusCached != canExecuteStatus) { this.canExecuteStatusCached = canExecuteStatus; if (CanExecuteChanged != null) { CanExecuteChanged(this, newEventArgs()); } } returnthis.canExecuteStatusCached; } publicvoid Execute(object parameter) { this.executeAction(parameter); } } }
Building the Dashboard
We will now be using the MVVM pattern to build out our Dashboard application. The main use case of the dashboard will be to display a list of products and allow you to filter the monthly sales data for the selected product. We will be creating the following items: •
XML for storing the product sales data
•
Product and Sales KPI model classes used to store the instance data displayed by the Dashboard [ 73 ]
Building a Basic Dashboard
•
Product Sales View Model that will expose the list of products and sales data for the selected product
•
XAML View contains a Grid for displaying the list of products and Chart for display the selected product sales data
Setting up the Data Source To keep things simple, we will be loading the data source for the dashboard from an XML file (Products.xml), which is stored in the ClientBin folder, along with the application's XAP file. Each product listed in the XML file contains the attributes that will be displayed by the grid and sub elements for storing the last six months of sales data for each product. 414324-423 Tunnbröd PB Knäckebröd AB Grains/Cereals 12 - 250 g pkgs. 9.00 61 10
To retrieve and load the data from the ClientBin folder, we will be using the WebClientDownloadStringAsync method to retrieve the XML file. Once the XML file is retrieved, we will be using XLINQ to load the data stored in XML into the product and sales model classes for our application. WebClient client = newWebClient(); client.DownloadStringCompleted += newDownloadStringCompletedEventHandler (client_DownloadStringCompleted); client.DownloadStringAsync(newUri("products.xml", UriKind.Relative)); [ 74 ]
Chapter 4
Defining the View-Model and Model classes
The main components of our application will be our View Model and Model classes. We will be creating two model classes: Product and SaleKPI, and a single View Model ProductSalesViewModel. The product class is fairly simple and contains the properties that will be displayed by the grid, and a child collection for monthly sales data. usingSystem.Collections.Generic; namespace Chapter4.Model { publicclassProduct { publicstringProductId { get; set; } publicstringProductName { get; set; } publicstring Category { get; set; } publicstringQuantityPerUnit { get; set; } publicdecimalUnitPrice { get; set; } publicIListSalesData { get; set; } } }
The SaleKPI class will contain the two properties: Month and Amount that will be displayed by the Chart Control. namespace Chapter4.Model { publicclassSaleKPI { publicstring Month { get; set; } publicdecimal Amount { get; set; } } }
The ProductSalesViewModel will be responsible for exposing the properties. The dashboard's XAML view will be bind too, tracking the selected product so it can filter the sales data displayed, and loading the model with the XML data retrieved from the products.xml file. When a user selects a product (row in the grid) the view model updates the
SalesData property to display the sales data for the selected product. using System; usingSystem.Collections.Generic; using System.IO; [ 75 ]
Building a Basic Dashboard usingSystem.Linq; using System.Net; usingSystem.Xml.Linq; using Chapter4.Model; namespace Chapter4.ViewModels { publicclassProductSalesViewModel : BaseViewModel { publicProductSalesViewModel() { LoadData(); } privateIList _products; publicIList Products { get { returnthis._products; } set { if (this._products != value) { this._products = value; this.SendChangedNotification("Products"); } } } privateProduct _selectedProduct; publicProductSelectedProduct { get { returnthis._selectedProduct; } set { if (this._selectedProduct != value) { this._selectedProduct = value; this.SendChangedNotification("SelectedProduct"); if (this._selectedProduct != null) { this.SalesData = this._selectedProduct.SalesData; } } } } privateIList _salesData; [ 76 ]
Chapter 4 publicIListSalesData { get { returnthis._salesData; } set { if (this._salesData != value) { this._salesData = value; this.SendChangedNotification("SalesData"); } } } } }
When the View-Model is created, it sends an asynchronous request to retrieve the products.xml file from the ClientBin folder. When the asynchronous request returns, the View-Model uses XLINQ to load the data into the Product and SaleKPI model classes. We are using XLINQ to query the returned XML that contains product data easily. XLINQ allows us to extract the elements and attributes for each product and its related sales data. We use the extract data to create a Product class and SalesKPI collection for each product element defined in the XML. To execute the defined XLINQ query, we call the ToList()command to load the product data for the dashboard. privatevoidclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { XDocument document = XDocument.Load(newStringReader(e.Result)); var result = from d indocument.Root.Descendants("Product") selectnewProduct { ProductId = d.Element("ProductID").Value, ProductName = d.Element("ProductName").Value, QuantityPerUnit = d.Element("QuantityPerUnit").Value, Category = d.Element("Category").Value, UnitPrice = decimal.Parse(d.Element("UnitPrice").Value), SalesData = this.GetSalesData(d.Element("SalesData")) }; this.Products = result.ToList(); } privateIListGetSalesData(XElement element) [ 77 ]
Building a Basic Dashboard { var result = from d inelement.Descendants("Sales") selectnewSaleKPI() { Month = d.Attribute("Month").Value, Amount = decimal.Parse(d.Attribute("Amount").Value), }; returnresult.ToList(); }
Laying out XAML and Data Binding
We are now ready to lay out the XAML and set up the data binding for the dashboard application. Our UI will contain two components: a grid that displays a list of products, and a chart that displays the sales data for the selected product. When creating the view for our dashboard, we need to add the XML namespaces for the controls we are going to use, and set up the View-Model we are going to bind to the view's data context. Because we will be using the Silverlight DataGrid and Silverlight Toolkit Chart control, we need to make sure we have the following two namespaces defined in XAML. •
xmlns:Controls="clr-namespace:System.Windows. Controls;assembly=System.Windows.Controls.Data"
•
xmlns:dv="clr-namespace:System.Windows.Controls. DataVisualization.Charting;assembly=System.Windows.Controls. DataVisualization.Toolkitt"
To organize the layout of the dashboard, we will be using a ScrollViewer and StackPanel control. The ScrollViewer will automatically display horizontal and vertical scroll bars when the necessary space for the view is larger than its window. The stack panel will vertically align the Grid and Chart controls so that they can be easily viewed at the same time.
[ 78 ]
Chapter 4 [ 79 ]
Building a Basic Dashboard
To set up the data binding between the dashboard's view and its view model, we can define a static reference to the view model and bind the data context of the view to the static reference, or set the data context for the view in the code behind. Either method will work for simple applications; but for more advanced applications, it is better to set up the data context in code, so you can manage the life cycle of the view model and handle sharing state between multiple view models. usingSystem.Windows.Controls; using Chapter4.ViewModels; namespace Chapter4 { publicpartialclassHome : Page { public Home() { InitializeComponent(); this.Loaded += newSystem.Windows.RoutedEventHandler (Home_Loaded); } voidHome_Loaded(object sender, System.Windows.RoutedEventArgs e) { this.DataContext = newProductSalesViewModel(); } } }
To set up the product grid, we need to follow the given steps: 1. Set the grid ItemSource (property exposed by the view model). 2. Define the columns (properties in the product class). 3. Set up a two-way data binding between the grid's SelectedItem and the view. [ 80 ]
Chapter 4
4. Model's SelectedProduct property. 5. Turn off AutoGeneratedColumns. 6. Set the Height of the Grid to 300 and IsReadyOnly to True.
To use the Chart control, you need to define its axes and series types you want to display. Because we want the dashboard to display financial data across a time period; we will be setting up a DateTimeAxis (X axis) and a Linear Y axis. Make sure to set the IntervalType for the X Axis to Months, and its location to Bottom. For the Y Axis, set its interval type to 1000, and its Minimum and Maximum values. To bind data to the chart, we need to define a series type and set its ItemSource to a property exposed by the view model. For the dashboard, set up a line series type, set its item source to SalesData, bind the independent value to the Month property, and the dependent value to the Amount property of the SaleKPI class.
[ 81 ]
Building a Basic Dashboard
At this point, you should have a fully working dashboard. Compile and run the application. When it displayed, you should see the data displayed by the chart control change to reflect the sales data for the selected product.
[ 82 ]
Chapter 4
Customizing the UI When building a dashboard style application, one of the important things you need to keep in mind is defining a great user experience. There are several ways to accomplish this: make sure the information, especially the Key Performance Indicators (KPIs) displayed, matches the needs of the user. The visual design should be clean and simple, focusing on highlights KPI and other important data. It's important too to make sure the data displayed is organized correctly, and the necessary formatting is done. Throughout the rest of the book, we will focus on how to build a Silverlight Dashboard application that offers the best user experiences, uses a professional clean looking visual design, and displays data from multiple different data sources. Before moving on, let's look at a couple simple ways we can improve the user experience of the Dashboard by customizing the look and feel and applying formatting to the grid and chart controls. To customize the look and feel of the grid, we are going to use a template column to combine two columns into one and apply formatting to the unit price column. In the following XAML, we have added a new template column named product. Inside of the data template for the column, we have added a set of Text Block controls that allows us to format the new column ProductName (ProductId). If you want your template column to support sorting, make sure to set the SortMemberPath to a validated property of the Product class. [ 83 ]
Building a Basic Dashboard
To apply a currency format to the unit price column, add the StringFormat property to the binding string, and set the format to 'c'. This will make sure the column's data is displayed as currency.
To format the chart control, we can apply formatting to the DateTime axis to display the name of the month and reformat the Y Axis to display the numeric value using the defined format.
[ 84 ]
Chapter 4
Summary In this chapter, we walked through how to create a Silverlight dashboard application. We walked through how XAML data binding works and how to use the Model View View-Model (MVVM) pattern, and how to customize the Silverlight grid and chart controls to better showcase the Key Performance Indicators (KPI) of a Dashboard. In the next chapter, we will give a broad sweep across the major types of dashboards: strategic, operational, and analytical. We will cover how to choose between the different types to the meet the needs of the dashboard application users.
[ 85 ]
Dashboard Types and User Needs First, we will look at an overview of the three main types of uses of dashboards, seeing that different types of dashboards are needed to support different general classes of needs of users. Next, we will review the different types of charts and graphs that typically show up on dashboards, looking at pros and cons for each chart and graph type. Then, we'll move on to understanding how to discover and represent actual user needs. To do this, we'll discuss the typical methods used in what is named user-centered design, which is a design philosophy focused on designing good user experiences. Finally, we'll apply one of these user-centered design methods in detail, showing how we can move from scenarios (narrative stories of use) to requirements. This will prepare us for the following chapter, in which we will take this understanding of user needs and move on to designing an actual dashboard to support those needs. In this chapter, we will specifically cover the following topics: •
Different dashboards for different needs
•
The Good, the Bad, and the Ugly—Typical dashboard charts and graphs
•
Focusing on needs, not technology
•
Scenario-based requirements and design
Dashboard Types and User Needs
Different dashboards for different needs The three main types of dashboards are Strategic, Analytical, and Operational. Each of these serve a differing set of overall goals and interaction needs. In this section, we'll look at a brief description of each type, before moving on to later sections that will focus even more on understanding how to discover and represent the needs of our users.
Strategic Strategic dashboards are the type that you likely think of when you think of dashboards. Strategic dashboards are intended to show long term perspectives of data, including looking back at least a year or so, as well as looking ahead for projections of the future. The goal of strategic dashboards are to give the user a quick, high-level sense of what is going on, usually with only minimal tools for digging deeper. For example, a strategic sales dashboard may show target vs. actual revenue, costs, and profits, likely shown only at the level of year-to-date (that is, not going down to even the monthly level). While the high-level view of a strategic sales dashboard probably won't show all products, regions, or a monthly view, you may see "top 10" listings for products, or regions.
[ 88 ]
Chapter 5
Analytical Analytical dashboards go beyond the high-level view of strategic dashboards, and are meant to allow users to conduct analysis at a much deeper level in order to get a full understanding of the causes, not just the results. For example, sales managers may want to go beyond just looking at year-to-date revenue, and top 10 products. They usually want to be able to compare specific products across specific geographic regions, looking for patterns. A marketing manager may want to conduct similar analysis, but instead looking for impact of marketing initiatives in differing regions on actual revenue.
Operational Operational dashboards are meant to support real-time decision-making. For example, retail chains may want to track the numbers of items in each store in order to make sure stock levels never fall below, or get above certain levels. Operational dashboards not only show information, but usually provide the ability to take action. In the example of low stock levels for a retail chain, the user might actually be able to not only look at current stock levels and buying projections based on the last few years, but may also be able to place orders for multiple stores in the dashboard itself. We only have room here for the basics, because our goal is to get on to understanding how to represent user needs, and ultimately design for them. For further description and examples of these and different ways to categorize dashboards, take a look at Stepthen Few's book,"Information Dashboard Design".
The Good, the Bad, and the Ugly—typical dashboard charts and graphs This section provides an overview of chart types typically found in dashboards. Each chart type is described along with some of the pros and cons for each. In addition, details about what makes some of these charts good or bad for certain uses based on more detailed design principles will be discussed further in next chapter. When choosing ways to represent data for dashboards, the focus should be on using compact information representations that guide users towards answers to their questions. In addition to looking at typical, better known charts, we'll see how many newer representations (for example, sparklines and bullet graphs) provide a lot of info in a small space. We'll also see why this means that we want to avoid unnecessary graphics as much as possible. As we'll see later, these unnecessary elements go by the name chartjunk. [ 89 ]
Dashboard Types and User Needs
Bar chart
A bar chart is used to compare multiple items, using one bar for each item, with the length of the bar corresponding to a specific attribute value for the items. While whole-to-part ratios can be represented using bar charts, there is no need for the bars to add up to 100%, making them a good candidate for most comparison situations. Sorting the bars can enable users to see largest and smallest values easily. A second attribute of each item being compared can be represented by shading each of the bars, with stronger shades representing larger values, and lighter shades representing smaller values. Bar charts can be laid out both horizontally or vertically, but for dashboards, horizontal is usually best because of space issues, and in order to align labels and other attribute values with each bar. The following image shows a typical use of a bar chart in a dashboard on the right (Comparison column):
Pros Bar charts are easy to analyze because bars of differing lengths are easy for people to compare at a quick glance. In addition, when laid out horizontally, it is easy to place labels and attribute values with each bar in a manner that is easy to scan visually.
[ 90 ]
Chapter 5
Cons As the number of items to represent gets large, it can be difficult to fit all of the items in the small amount of space typically available on a dashboard.
Stacked bar chart A stacked bar chart builds on the standard bar chart by allowing multiple related bars to be stacked on top of each other, allowing the user to see the aggregate values (the complete stacked bar) as well as the constituent values (each smaller bar in a given stack). For example, one stacked bar may show the total sales for a product line, while each constituent bar represents a single product in that product line.
Pros The main reason to use stacked bar charts are that they are horizontally space efficient, allowing more information to be squeezed into a smaller area.
Cons It is difficult to compare bars that are stacked above others because each bar will have a different starting height, as compared to the standard bar chart where every bar starts at the bottom of the chart.
Line graph A line graph shows one or more lines plotted on a two-dimensional chart.
[ 91 ]
Dashboard Types and User Needs
Pros Although a line graph may take up a good amount of space, it can be an efficient way to compare many items, because it's easy to see when a small number of lines differ from all of the others.
Cons Line graphs can take up a lot of space if the data is very spread out (for example, if you're trying to represent many different points in time). In addition, if the values are too similar, it will just look like a chaotic mess of lines; this can be mitigated if your dashboard has the ability to dynamically single out one line at a time to be visually contrasted with the others.
Scatterplot A scatterplot is a set of points laid out on a two-dimensional chart, typically used to visually show correlation between two sets of values. Scatterplots tend to be used as secondary ways to view data, for example when carrying out multivariate analysis, and therefore would likely show up on dashboards meant to support what-if analysis.
Pros It is easy for people to notice whether or not data values are clumped together into noticeable patterns, making a scatterplot a useful way for users to notice trends at a glance quickly.
Cons Scatterplots can take up a lot of space, depending on how spread out the data is, and may take up more space than is available on many dashboards.
[ 92 ]
Chapter 5
Bullet graph
Developed by Stephen Few, the bullet graph is useful in showing data where there are varying thresholds of quality (for example, minimum, target, or maximum values). The visual representation of the bullet graph enables quick scanning by the user to see which items are above or below various predefined thresholds.
Pros Bullet graphs pack of lot of information into a small space, and allow for quick scanning of key information. Their usefulness is resulting in quick acceptance in the information visualization field as a go-to choice for dashboards. The simple representation allows for numerous variations, in terms of how many ranges and thresholds can be represented.
Cons While very useful and simple, because bullet graphs are somewhat newer chart types, users may need an initial explanation of their representation; because of this, a simple legend on the dashboard above or below a set of bullet graphs suffices.
[ 93 ]
Dashboard Types and User Needs
Sparkline Sparklines are basically line graphs to show time-based data that are meant to only take up a very small amount of space, allowing them to be used in tight spaces. Created by Edward Tufte, sparklines were meant to be "word sized," so that they could be placed inline with text.
Pros The small amount of space required for a sparkline means that they can be used in the same amount of space as text and numbers.
Cons Compared to larger line graphs, it is more difficult to show multiple lines in a sparkline. If too many lines are shown in a single sparkline, it becomes difficult to make out the each line.
Small multiples In many cases, multiple variables need to be compared for the same data, formally called multivariate analysis. The design pattern called small multiples is used to mean cases where you want to show users many different views of the same data, varying in some attribute such as time, geographic region, product line, and so on. Many people are familiar with the concept of pivot tables, also named crosstabs, and the small multiples visualization is a way to show the result of pivot tables visually, rather than just as data in a spreadsheet. [ 94 ]
Chapter 5
Pros Multivariate analysis is difficult; real-world problems are made up of information entities that each have many variables. Therefore, most real-world problems involve trying to understand complicated, multivariate information spaces. There is tremendous value in providing our users with the ability to carry out multivariate analyses using a visual representation in a small multiples layout. This is because they will actually be able to think about information spaces more complicated than if left to their own internal cognitive abilities. Good representations for multivariate analyses very literally extend the capabilities of the human mind (and that is the main goal of information dashboards!).
Cons Small multiples inherently take up a good amount of space, because we're usually trying to show representations across multiple variables, and this is usually done using a matrix layout where each cell in the matrix itself contains a line chart, or other visual representation. Therefore, they are rarely used as part of a default view of a dashboard, and are instead typically used in interactive dashboards in a separate area that can dynamically be shown and hidden for detailed analysis.
Pie chart Pie charts show whole-to-part ratios by showing a circle broken into colored segments (pieces of the pie), with the size of each segment corresponding to an attribute of the values being compared, and the color of each segment mapped to a particular item.
Pros Pie charts don't take up much space, and they seem to have a good visual aesthetic quality, meaning that people tend to think they look nice (even if their interaction aesthetic qualities are lacking). In addition, people can tell at a glance that what is being represented is a part-to-whole ratio.
[ 95 ]
Dashboard Types and User Needs
Cons Although they are very popular, there are many drawbacks to using pie charts, and in most cases, there will be a better alternative, especially for time-critical tasks. People are not good at comparing angles or non-rectangular areas, which makes it difficult to actually compare pieces of the pie with real world cases where you have many values to compare. In addition, because of the circular nature of the pie chart, it is difficult to label each segment, requiring the use of a separate legend to show segment labels; this forces users to visually scan back and forth between the pie chart and the legend, using working memory to remember which color represents which items. The worst kind of pie chart is the 3D pie chart, which a 3rd dimension just for the "cool factor." The problem with adding this 3rd dimension is that the extra dimension does not actually represent data; this 3rd dimension adds inaccuracies by making certain pieces of the pie look larger than they should, making it more difficult to carry out visual comparison of the pieces.
Focusing on needs, not technology This section will introduce how we can apply user-centered design best practices for the design of good dashboards. User-centered design is a now a well known set of practices that if used properly, can lead to products and services that will have what we call a good user experience (UX). A brief definition of good user experience is that the product or service is: •
Useful
•
Usable
•
Desirable
The rest of this chapter will focus on how to make sure your dashboard ends up being useful, which involves using methods that help you capture and represent the most important needs of your users; needs even users or stakeholders won't be able to tell you! The next chapter will cover the second aspect of good UX: usability. For example, in this chapter, we took a brief look at typical types of charts used in dashboards. In the next chapter, we will take a deeper dive into why some of these charts are better than others, based on how human perception works. By first discussing usefulness, we make sure that we understand What users need, before trying to tackle the How; good user-centered design is all about understanding the needs of users, before starting to design or code anything. The last piece of the UX triad, desirability, has a lot to do with visual aesthetics, and will be addressed in the following chapter along with a more general discussion of aesthetics.
[ 96 ]
Chapter 5
Useful dashboards help people answer specific questions, rather than just providing a dump of data. Users shouldn't have to perform mental calculations to get the information they need. They should be able to scan a dashboard visually, pick off answers to their questions, and see where there may be exceptional situations that need analysis. Put another way, users should be able to think with their eyes, getting insights they need at a glance. Ok, so how do we do this? Well, we already know the answer; we'll just apply user-centered design to understand first what these specific questions are that users need to answer (their needs). Only then will we move on to figuring out how best to support these needs (the design).
Representing and communicating user experience We've already stated that user-centered design is about user needs, not necessarily what users think they need. A key aspect of user-centered design is representing interactions between people and the products and services over time. All experiences happen over time, so we need to be able to understand and represent this. If we can't understand needs from the user's perspective, how could we possibly support those needs? So how do we represent and communicate user experiences? Such a seemingly simple question hides a lot of complexity. Bill Buxton, a well known designer currently working at Microsoft, has a great exercise that he has people go through when he gives a talk about design. As you read through this exercise, try it out yourself. He tells each audience member to pull out a piece of paper and a pen or pencil. So, go ahead, it doesn't matter if "you can't draw," just get a piece of paper and something with which to write. First, he asks everyone to draw their phone - just a quick sketch of the physical form of the phone in about 15 seconds. Pretty simple, right? Even if you can't draw well at all, it's not too hard to sketch out the rough form of your phone.
[ 97 ]
Dashboard Types and User Needs
Here's a rough sketch of an iPhone:
Next, he asks each everyone to draw the user interface of their phone, again just taking 15 seconds or so. That's pretty easy, too, right? Go ahead and try it for your phone. For the iPhone, this may look like a bunch of boxy little icons that represent apps, showing how you touch and drag to move between pages of apps:
Ok, so here's the third and last thing he asks everyone to do: In just about the same time, just 15 seconds, draw the user experience of your phone. Ok, go ahead and try it…draw the user experience of using your phone. Whoa…not so easy, right?
[ 98 ]
Chapter 5
Why is this so difficult? And why is this such an issue for designing good user experiences? Why is it so easy to sketch the form and interface of the phone, but so difficult to sketch out the experience? Buxton ends with stating how important it is for the future of experience design to have tools that make it as easy to do the third part as it currently is to do the first two. One of the main issues is that the first two (physical form and user interface) can be easily drawn as static images, but with the third, experiences happen over time, space, and even social structures. People have the experience, the technology doesn't. So what are we to do? How do we represent the future experience of our users using a dashboard so that we can design these great experiences?
User-centered design User-centered design doesn't prescribe a specific set of methods to use for understanding and designing for user needs, but we'll take a brief look at the usual set of best practices that we use in their practice. The full user-centered design process we typically use makes use of user research, personas, scenarios, requirements (derived from scenarios), storyboards, sketches, wireframes, prototypes, and high-fidelity mockups. The remainder of this chapter will focus on Scenarios and Requirements, but I'll provide a brief description of each piece of the full process so we see how what we'll cover fits into the full process. A good reference for the complete process covering all of the above methods is Designing for the Digital Age: How to Create Human-centered Products and Services, by Kim Goodwin.
User research User-centered design by its name implies that the focus is on users, but many people confuse this with literally meaning, "ask the users what they want, and build that." In fact, this is one of the worst things to do, because users aren't, and actually can't be aware of many of their needs, or how they actually go about accomplishing even what they currently do. Conducting user research focuses on understanding what people need to accomplish, getting a deep understanding of what we call "the context of use." The context of use is the environment where our users are doing whatever it is they do, including any social, physical, and time-based characteristics of this environment. You want to get past how people are supposed to act in a given situation (for example, what their company manual says the correct way to do something is), and find out what really goes on. To do this, you need to carry out contextual inquiries, which is just a fancy name for interviewing people in the realworld setting where their work, play, and so on, happens. Focus on actual behavior, rather than what people say they do; there is usually a big difference between the two. [ 99 ]
Dashboard Types and User Needs
Personas A persona is a concrete, yet fictional representation of a user of your product or service that helps you stay focused on for whom you are designing. Personas are not made up, but should instead be based on user research, and are mainly based on behavioral variables that differentiate people that were part of your user research. The number of personas created for a given project will depend on what your user research shows, but is usually at least about three. Personas typically include key characteristics that differentiate our users, and in many cases would list key "pain points" with current products, and key tasks or activities that are important to this persona.
Scenarios Scenarios are textual narratives that describe a good user experience for which we want to design. The most important element of scenarios is that they need to be from the user's perspective. Scenarios should represent a vision for the future use of your product or service. Focus on "what" is being accomplished, rather than "how" it is being accomplished. Initially, stay away from mentioning any specific technology; in fact, what we want to do is pretend that technology in the future is magic, and that (almost) anything is possible. Of course, later in our design process we'll take into account technological constraints, but when we're creating scenarios, it's a great chance to focus on what people really need without focusing on technology first. We are going to use scenarios quite a bit in the remainder of this chapter, as well as in the next.
Requirements In user-centered design, in addition to requirements given to us by business stakeholders, we are most interested in deriving requirements from approved, credible scenarios (as defined previously). By deriving requirements in a scenariobased manner, we are more likely to end up with requirements that represent the subtle (yet important) ways that people use information together. Because scenarios represent a vision for the future, these requirements will therefore represent for what we need to design, rather than just being based on what stakeholders and users are able to think of grounded in current technology.
[ 100 ]
Chapter 5
Storyboards Storyboards that have been historically used in the film and animation fields are great ways to show main points of interaction during software design, while also describing some of the temporal elements. There are many great books and websites out there on storyboarding. Some of the best examples come from early Disney movies, and Disney just released new books with archives of storyboards from early animation up through the most recent movies. I was amazed when I first learned how integral storyboarding is to the film process. For example, Pixar will typically spend at least two years just creating the story for a new film, just using low fidelity sketched storyboards. And their success has a lot to do with that...their films are all great stories. In a way, experience design is just like creating a great story for a movie, with the user being the main character.
Sketches Many people think of sketches as rough drawings on napkins, whiteboards, paper, etc. While this is true, in user-centered design, we have a broader definition of sketches as any low cost, low fidelity, throwaway representation of an idea. This means a sketch can be realized on paper, and in software. The goal of "sketching" then is to rapidly generate lots of ideas on the path to good ideas. Do be careful though when trying to sketch in digital form to not create high-fidelity creations, because the goal of sketching isn't to get it looking or feeling perfect; the goal is to use just enough fidelity to communicate an idea in order to see where that idea breaks down.
Wireframes Wireframes are low fidelity representations of an interface design, focusing on overall layout of information rather than on higher-fidelity visual aesthetics.
Prototypes Prototypes are used to try out ideas to test different types of feasibility, and to answer different types of questions. If we have designed a novel type of interaction, and we aren't sure how our users will behave when using it, we would create a prototype that focuses possibly just on the interaction design (interaction aesthetics), and not on the visual aesthetics. If instead, we have questions about the technological feasibility of a design idea (for example, can the system respond in the amount of time we expect for a given interaction?), then we would create a prototype that actually implements just those interactions. The goal is to focus prototype development on answering the specific questions we have, not on building them to give developers something to do, or to try out cool technology. [ 101 ]
Dashboard Types and User Needs
High-fidelity mockups
High fidelity mockups go beyond wireframes, and represent what we call "pixel-perfect" designs, where the actual colors, size, and placement of screen elements are shown as intended for final implementation.
Scenario-based requirements and design The remainder of this chapter will be used to show how scenarios can be useful as the basis of requirements derivation, and how important they are at driving the following design process. By using scenarios as a method to get to requirements, you are in a better position to both make sure that you have traceability and rationale for features, and to help avoid features creeping in only because someone thought it would "be cool" to include them. Use Cases (from traditional software development processes), and User Stories (from agile processes) are similar to scenarios, with respect to trying to represent user interactions and needs, but scenarios differ in many ways. While use cases describe interactions between a user and a system, they typically do so in a very system-centric manner, focusing only on the very explicit input/output aspects of the interaction. User stories purposely lose a little of the detail seen in use cases, and add a pinch of context (for example, stating the goal of the user), but still really just focus on one low-level interaction at a time, and therefore don't give a good sense of the context of use. What use cases and user stories don't provide are the richer, qualitative aspects about the surrounding context of use…for example, who is the user, and why is he or she using the system? What we really want is a representation of the user accomplishing things in a way that will lead to empathy for this user…what does he or she need or want to do, and why…think of how when you're reading a good book, it's easy to picture the characters, and you feel that you get to know them, and what they're going through. We want that, at least as much of that empathy as we can get in about a paragraph or a page for each key situation in which we think users will find themselves. In user-centered design, we create narratives like these named scenarios.
[ 102 ]
Chapter 5
How do you collect information that puts you in a position to be able write these scenarios? If you can, you should use contextual inquiry methods, such as observations and interviews that take place in the actual places where users will be doing these activities. In many cases, you're using scenarios to represent situations that don't yet exist, so you have to find creative ways to get as close as possible to these new situations to gain the proper understanding. Look for similar situations in other industries, and so on. If you were designing the first online music store ever, you'd want to hang out in bricks and mortar music stores and see the types of questions customers ask. In the case of dashboards, again what we really care about is understanding what questions people are trying to answer, so that we can represent information in best possible way to answer these questions. We use scenarios to represent what users need and want to be able to accomplish. These are just simple textual narratives that describe a good user experience for which we want to design. The most important element of scenarios is that they need to be from the user's perspective. If you can't capture and represent needs from the user's perspective, what chance do you really have in ending up with a product that supports these needs? Again, the goal is to allow people to gain empathy for a user's situation. Here is an example scenario related to a couple using a system to compare cities with the goal of trying to decide on a new place to move because of a job change. As you read it, consider how the focus is on what is being accomplished, but not how. Alice just got a job offer from a company with which she's been trying to get a job for a while, but unfortunately, the new job is going to require her and her husband Jeff to move. One good aspect of this is that the company will allow Alice to choose between any of the nine cities where this company has this particular position available. Jeff and Alice have two young children that are about to start elementary school in a couple of years, and they don't want to keep moving around once the kids start school. It's really important for them to choose a city that has great schools as well as great job prospects for the future, for both Alice and Jeff. Because Jeff is a teacher, he's not too concerned about being able to find a job, as long as the school districts in the area are typically hiring, which is usually the case if an area's population is increasing. Jeff bought the issue of Money magazine that comes out every year showing the best cities in which to live. Buying the magazine also gave Jeff free access to the online version of the article and accompanying data, but Jeff and Alice were quickly frustrated with how much data there was to keep track of. Both the magazine and the online data just gave table after table of data for each city, and it was really hard to find, re-find, and keep track of the information most important to them. [ 103 ]
Dashboard Types and User Needs
Jeff heard about a new system you can use to compare cities in which to live, and it seems like not only a quicker way, but also a more fun way to figure this all out, at least compared to having to sift through all of that online magazine data. Jeff and Alice go down to the public library to try out this new system. Alice selects the nine cities from which she is allowed to choose and can see what types of data are available to use. Jeff sees that different types of data are available to help compare the cities Alice has selected. Out of all of the available data they decide to use school information, job growth, and housing information, because those seem to be the ones that matter the most. They figure they can look at other things like crime rate and the availability of parks and entertainment later once they've whittled down the list of cities to just a few. Jeff selects the data about schools, housing, and predicted job growth from the overall set of data available, and they see that even each of these sets of data contains further subsets they can use to compare cities. Even though Jeff and Alice already have a few favorites in mind, they decide to start off by comparing all nine cities from which Alice can choose. Based on the type of data that Jeff has chosen, the system recommends a few ways to compare the data visually. Jeff chooses a bar graph, because it looks like something he's seen before, and Alice isn't as comfortable with charts and graphs anyway. The system shows how each city compares across the three sets of data they've selected, schools, jobs, and housing. The comparison is showing the information sorted based on the order that Jeff selected the information in the first place. Because housing was selected first, it is currently used to sort the data, but they care more about schools. Jeff rearranges the order so that schools are most important, then housing, and then finally jobs. The system now shows the information that makes it easier to compare the cities based on Jeff's arrangement. With this information so clear, they can easily see that there are about three cities that stand out as the best options. Alice reduces the number of cities being analyzed to these three and creates a summary of the information in a format that they can use to discuss the options. An important aspect of the scenario is that you can't tell what technology the system uses. You don't see any specific mention of mouse clicks, finger taps on a touchscreen, and so on; the focus is on what the couple is accomplishing, not on a given technical solution. This allows you to make sure you have represented what users really care about before committing to any specific design solutions.
[ 104 ]
Chapter 5
And if we take just the following snippet of this scenario, we can see how initial high-level requirements can be derived from it, focusing on what information is being used, and how it is being used, especially looking for information used together or as part of a related flow: "The system shows how each city compares across the three sets of data they've selected, schools, jobs, and housing. The comparison is showing the information sorted based on the order that Jeff selected the information in the first place. Because housing was selected first it is currently used to sort the data, but they care more about schools. Jeff rearranges the order so that schools are most important, then housing, and then finally jobs… Alice reduces the number of cities being looked to these three and creates a summary of the information in a format that they can use to discuss the options." …could lead to the following requirements: 1. Ability to compare multiple cities at the same time. 2. Default sorting of data based on the order the user selected the data. 3. Ability to rearrange the sort order of the selected data. 4. Ability to change (add, remove) selected cities during city comparisons, without disturbing the comparison parameters selected. The next step would be to use these requirements to drive the design process. By using scenarios to derive requirements, you will have more confidence about why a given feature has been designed, because it supports a requirement that comes from a clear understanding of the user's situation. The next time someone on your team says "Hey, I just saw Microsoft's cool new 'XYZ' feature and I think we should put that in the dashboard," you can respond with "Can you show me which of our agreed upon scenarios this supports?"
Example scenarios for dashboard design Now let's look at a scenario that is typical for dashboards, focusing on the strategic type of dashboards. We'll use a sales dashboard, given that these are one of the most popular kinds, given that the goal of a sales dashboard is to show where sales are doing well, and where they are not; that's pretty important to every type of business. Then, just as we did for the scenario example above, we'll look at some requirements that could be derived from this scenario. In the next chapter, we'll see how we can use this scenario and the derived requirements to choose appropriate chart types, and to lay out an overall dashboard design.
[ 105 ]
Dashboard Types and User Needs
Steve is the new sales manager at Adventureworks, a leading manufacturer of bikes and related parts. While Adventureworks is doing well, they brought Steve in to lead the growing sales team, and the hope is that he can take Adventureworks to the next level, and edge past their main competitors. Luckily for Steve, getting a sense of what's going on with sales should be pretty easy, because in addition to being good at building bikes, Adventureworks has a great foundation in technology, and they track all kinds of sales data, and Steve has access to a dashboard that brings all of this data together nicely. First, Steve wants to get a sense of the overall sales picture, so he opens up the dashboard application. With the way that the dashboard shows the main KPIs, such as overall revenue, profit, and costs, Steve can simply scan down the list and see which ones are meeting their targets. Next, Steve takes a look at sales broken out by the four geographic regions of the U.S., and can quickly see that his best performing region is [X], while his worst performing region is [Y]. In order to focus these two regions, Steve makes selections on the dashboard to hide data related to the other two regions. This way, he can focus on trying to see what's going on with these best and worst regions. Now, similar to looking for any trends in sales by region, Steve decides to see if any obvious patterns exist when looking at sales based on product categories. Steve brings back in all region data, to make sure that he's looking at products across all regions. He now uses the options to look at just one product category at a time. With just one product category selected, the whole dashboard shows the same information, but only for that product category. Now Steve decides to look to see who the top customers are, so he brings back in all of the product categories. The dashboard already shows the top 10 customers by default, so it's easy to see. Finally, since Steve has seen some patterns by region, and just by products, he wants to see whether he can dig even deeper with this dashboard, mixing these two ideas to see if any specific products are doing better or worse in any specific regions. Steve opens up the detailed area where he can visually compare sales data across multiple attributes, such as both region and product category, in a way that goes beyond just what the standard dashboard shows. Steve uses the filter options to look at only what appears to be the two best and worst performing regions. Then, Steve also uses the filter options to focus in on just the best and worst performing product categories. While the overall dashboard allowed Steve to look at region and product data, this specialized graphic allows these two variables to be compared together in a single chart.
[ 106 ]
Chapter 5
From this scenario, we can derive requirements based on what Steve was accomplishing: 1. Ability to see performance data for key KPIs (sales/revenue, profit, costs) together in one location of the dashboard. 2. Ability to see which KPIs are under or over performing just by scanning the list of KPIs. 3. Ability to filter by geographic region. 4. Ability to filter by product category. 5. Ability to see sales data by both geographic region and product category at the same time. 6. Ability to see top 10 customers based on revenue.
Summary This chapter covered an overview of the three main types of dashboards, as well as the different types of charts and graphs that typically show up on dashboards. Typical methods used in user-centered design were discussed with a focus on understanding how to discover and represent user needs, as opposed to just focusing on designing with "cool" technology in mind. Finally, we applied one of these user-centered design methods in detail, showing how we can move from scenarios (narrative stories of use) to requirements. In the next chapter, we'll use this scenario and the derived requirements to lay out a rough design of a dashboard, going through the process of choosing appropriate chart types.
[ 107 ]
Designing for Insight In the previous chapter, we saw how different types of dashboards are needed to support different general classes of needs of users. Then, following the principles of user-centered design, we created a scenario that represents what our fictitious user needs to accomplish. Now, in this chapter, we will use this scenario as the basis of an overall dashboard design. First, we'll discuss design concepts related to focusing our user's attention on certain information, enabling what we call visual thinking. Then, with these concepts under our belt, we'll move on to designing a dashboard that supports the scenario we have already created. We will design for each of the six requirements that were derived from the scenario one at a time, while always keeping an eye on how each of our separate design choices interact to make sure we end up with an overall dashboard design that works. In this chapter, we will specifically cover the following topics: •
Interaction aesthetics versus visual aesthetics
•
Scenario-based design of our dashboard
Interaction aesthetics versus visual aesthetics When people talk about "aesthetics," usually they are talking about how nice something looks visually, for example when a client tells you they want their website to be "aesthetically pleasing". However, there is a lot more to aesthetics than just visual beauty. Aesthetics have to do with human perception from all of the senses, including how it "feels" to interact with something (for example, as a result of physically touching an artifact, or moving your body through a space).
Designing for Insight
Interaction Aesthetics refers to the qualities of a design that lead to the feelings, emotions, and the behaviors that result from these more bodily types of interactions. An important element of these types of interactions is that they happen over time. This is why when we talk about interaction design, and user-experience design, it is important to not forget that interactions and experiences happen over time (even if just for a brief moment while someone moves their mouse from one area to another). Visual Aesthetics, is a term that is used to talk about the qualities of a design that lead to feelings, emotions, and behaviors that result from stopping and being more deliberative about the visual aspects individually. When we stop and deliberate about these types of visual qualities of a design, we're noticing things in a much different way than when we actually use the same designed artifact for a real-world activity. This is where the danger occurs of clients asking for "better looking" designs, without realizing the potentially negative implications of focusing only on visual aesthetics. Although we don't stop and deliberate about visual aesthetics when actually using a tool to accomplish an activity, we are more likely to notice the interaction aesthetics during actual use. So, there's a bit of a trap you can fall into when evaluating a design by looking at it; it is easier to notice, and therefore focus on attributes of the design that are completely different than the attributes of the same design in use. More generally, humans don't stop and deliberate about most actions as much as many designers think. This is why if you ask people what they do and how they do it, you are likely to get a very convincing story that in most cases will be far from what actually happens. The goal of good user experience design is to end up with artifacts that are useful, usable, and desirable. The most important word here is "and;" we want to end up with designs that have good interaction aesthetic qualities and good visual design qualities. When people use the things you design, they aren't having separate experiences, for example, one interaction with the visual design, and a different parallel interaction with the interaction design. They have one single, unified experience. It is only the designer who separates out these aspects and discusses them. What we want to design for is beautiful designs that also have great interaction aesthetics. A good example of something that has good interaction aesthetic and visual aesthetics is the pricing page for Basecamp from 37signals (http://basecamphq. com/signup). This website adopts effective visual aesthetics and interaction aesthetics together, in a way that creates a single, unified experience. The visual design is not over the top; it uses colors that are pleasing, and most importantly, the visual design hierarchy guides your attention to key information (the most popular pricing plan, information useful to compare plans are given stronger treatment, and the sign up buttons are easy to notice). [ 110 ]
Chapter 6
The concept of Pre-attentive Attributes (which will be covered later in this section) is one example where the two can blend together, for better or worse. Essentially, because of how our visual perception systems work, certain aspects of a design get your attention whether you want them to or not, before you actually spend cognitive effort or think about what you want to notice. You can use visual design to take advantage of these types of attributes, or your designs may suffer without you even knowing (you want to make sure that the visually appealing aspects that draw visual attention are moving that attention to the right places). That extra bit of color the client demands may interfere with the overall visual hierarchy of your design (for example, using extra color and weight for headers of information may draw too much attention away from the actual information).
Pre-attentive processing Now that we understand the difference between Interaction Aesthetics and Visual Aesthetics, we can move forward towards understanding how to design for visual thinking. What does visual thinking even mean? For this book, we won't dive too deep into cognitive science, but we'll cover just enough to apply it to dashboard design. There are certain characteristics, or attributes of visual representations that our vision will pick out and notice, without us even trying; in fact, we have no real control over this happening. The processing of these attributes by our vision system happens before our cognitive system attends to the representation, and therefore these attributes are called pre-attentive attributes, and the processing of them is known as pre-attentive processing. For example, we may notice that one word in a paragraph is bolded well before we are able to process what the word is, or what the word means. In this section, we will see the pre-attentive attributes that have been shown to be useful for dashboard design.
Applying pre-attentive processing to dashboard design Pre-attentive attributes are useful for dashboard design because of the inherent goal of most dashboards; to draw a user's attention to certain information, based on what is known about the information. For example, if thresholds such as sales goals exist for quarterly sales figures, we want to be able to have a user notice which sales figures are above or below these goals by simply glancing across that section of the dashboard. This is precisely what proper application of pre-attentive attributes allows us to do. If used properly, this idea will allow us to call out the right information to the user, and if ignored, we will end up forcing our users to spend unnecessary time trying to answer questions through extra cognitive effort. [ 111 ]
Designing for Insight
The following image shows the subset of pre-attentive attributes that have been shown to be most useful for dashboard design; these attributes are related to form, color, and spatial position. Our decisions on what chart types to use, as well as information design in general will be guided by this set.
For more in-depth discussion and academic treatment of the complete set of known pre-attentive processing and pre-attentive attributes, check out http://www.infovis-wiki.net/ index.php/Preattentive_processing. Colin Ware's book Visual Thinking for Design covers these vision system and cognitive science concepts applied to design. Additionally, for further information about this concept, applied specifically to dashboards, see Stephen Few's book Information Dashboard Design. The image above is based on Stephen Few's Information Dashboard Design book.
[ 112 ]
Chapter 6
Warnings about using pre-attentive attributes There are many ways to misuse, or incorrectly apply the concept of pre-attentive attributes, and a couple of these happen so frequently that it is warranted to discuss them briefly here.
Mixing too many attributes The first issueto be aware of is mixing too many of the attributes together. Many of the attributes deal with a very subtle use of visual design and typography (that is, font treatment), and therefore trying to use too many at once can actually backfire, defeating the purpose. We need to remember to look at the overall design to make sure that the key information we want popping out to the user is still doing so. Always be careful and check how well multiple attributes of any single item are coming together.
Visual distractors The second warning is in regards to the concept of distracters, which is exactly what it sounds like; we want users to notice certain information and anything that gets in the way is a distracter. Of course, we would never intentionally distract our users, but there are some ways to do it accidentally. The usual offender is unnecessary color, and by unnecessary, we mean strong colors used in section labels and headers, column headers, and other non-informational elements of the dashboard. Color and strong typography should be reserved for the information we want our user to notice, not used for the layout elements on the screen. In addition to unnecessary color, the use of extra lines and boxes to separate sections easily becomes a distracter. Proper use of whitespace, the area between the real information, is a much better way to break up information than using extra boxes or lines. In general, we want to use subtle visual design for non-informational elements in order to leave room in the visual hierarchy for the intended attributes to jump out based on the state of data (for example, stronger visual weight used to show when data is above or below a predefined threshold).
[ 113 ]
Designing for Insight
Scenario-based design of our dashboard In the previous chapter, we went through the process of constructing a scenario that represents the needs of a typical sales dashboard user. The goal and focus of such a scenario is to represent a concrete narrative story of what is being accomplished by the users in the scenario, but not how it is being accomplished. Once you have a credible, agreed upon scenario, it is time to move on to the next step in the user-centered design process, which is to start coming up with alternative design ideas that will support the scenario. We are going to carry out a very streamlined version of this part of the design process in this chapter. In a typical real-world project, we would have many personas and many scenarios, each representing different needs of different users, in the many different contexts of their work; even just for a single sales dashboard. In this chapter, we will focus on a single scenario for a single persona, Steve. In addition, for a typical real-world problem, we would spend days, weeks, even months, coming up with at least 5 alternative design ideas at each level of the design. What we're going to do in the remainder of this chapter is look at each requirement that was derived from our scenario, and consider the different options for what charts may support each requirement. We will also design for the overall interaction framework, by considering how these charts all work together, making sure that all of our design decisions work together for an overall good dashboard design. We will go back and forth between two levels of design, considering what specific charts we need (the lower level), while always thinking about the overall layout of the dashboard (the higher level). We will create a rough, low-fidelity wireframe showing the overall layout of the dashboard, and we will add to this wireframe as we make design decisions about which charts to use for each requirement. At the end of this process, we will not only have a design for our dashboard, but a rationale related to all of our design decisions. It is important to have this rationale to accompany your designs, because in the real world, you need to present and support these decisions to the many stakeholders on a project. From this scenario, we derived six requirements based on what Steve was accomplishing: 1. Ability to see performance data for key KPIs (sales/revenue, profit, costs) together in one location of the dashboard. 2. Ability to see which KPIs are under or over performing just by scanning the list of KPIs. 3. Ability to filter by geographic region. 4. Ability to filter by product category.
[ 114 ]
Chapter 6
5. Ability to see sales data by both geographic region and product category at the same time. 6. Ability to see top 10 customers based on revenue. In the remainder of this section, for each requirement we will look at the portion of the scenario the requirement was derived from, and consider alternative design choices in terms of which chart types might support that need. We will make a choice about which chart type seems to be the best choice, based on the pros and cons of the chart types as well as the overall goals of the dashboard. Lastly, after each choice, we will take a look back at the wireframe for the overall layout, seeing how each choice helps shape the overall dashboard design. When we have finished addressing all six requirements, we'll take a look at an actual full mock-up design (that is, not just a rough wireframe) of what the overall dashboard might look like.
Our initial overall dashboard wireframe The following image is a low-fidelity wireframe giving us a starting point for our dashboard design. As we move through the six requirements, we'll gradually add to this wireframe, as design decisions are made. For now, you will see that all we know is there will be a main area for the dashboard, as well as a likely header area at the top of the screen.
[ 115 ]
Designing for Insight
Requirement 1 The ability to see performance data for key KPIs (sales/revenue, profit, costs) together in one location of the dashboard. Related scenario text: First, Steve wants to get a sense of the overall sales picture, so he opens up the dashboard application. With the way that the dashboard shows the main KPIs, such as overall revenue, profit, and costs, Steve can simply scan down the list and see which ones are meeting their targets. This requirement is not related to comparing values, because each KPI will be considered separately. Therefore, we can rule out chart types that are best for comparisons, such as pie charts and line graphs. What we would want to do is use a simple table listing the KPIs, providing the key numerical values for each, as well as a very small graphical representation of the value. Sparklines are a good choice for this graphical representation, because they are meant to be word-sized and therefore would fit on the same line within this table. Following is an image of what this would look like for our scenario.
Now that we've made the decision to use a table with a line for each KPI, including an embedded sparkline, you can see what the updated rough wireframe looks like with the approximate location of this KPI table:
[ 116 ]
Chapter 6
Requirement 2 The ability to see which KPIs are under or over performing just by scanning the list of KPIs. Related scenario text: First, Steve wants to get a sense of the overall sales picture, so he opens up the dashboard application. With the way that the dashboard shows the main KPIs, such as overall revenue, profit, and costs, Steve can simply scan down the list and see which ones are meeting their targets. Again, because we are still referring to this same list of KPIs, we know we are not really comparing them against each other. Instead, the focus here is on comparing each KPI value against pre-defined thresholds. We could list out the threshold value in numerical form, but then the user would have to carry out a numerical comparison for each KPI (the KPI current value and the threshold), and this takes cognitive effort that we want to avoid. Instead, we can use a bullet graph, whose main purpose matches this exact situation; the bullet graph was designed to show a single current value against multiple threshold levels, and/or specific targets. The shaded areas in a bullet graph are used to show increasing levels of thresholds, and the small vertical bar (which we could use more than one if we wanted to) represents the key target threshold. The horizontal bar across the middle of the bullet graph is the current KPI value. The bullet graph makes use of the pre-attentive attribute called added marks, because it's easy to see when the current value crosses the key target resulting in a t shape, which is an instance of the added marks attribute. [ 117 ]
Designing for Insight
In the following screenshot, you will see the bullet graphs placed within our KPI table, with one bullet graph per KPI based on our scenario:
Just as with the previous design choice, now we can take a look at the rough wireframe updated again, showing that a bit more space will be taken up by the KPI table. We need to make sure we are always looking back at the overall layout to make sure our individual design decisions are coming together properly.
[ 118 ]
Chapter 6
Requirement 3
The ability to filter by geographic region. Related scenario text: Next Steve takes a look at sales broken out by the four geographic regions of the U.S., and can quickly see that his best performing region is [X], while his worst performing region is [Y]. In order to focus on these two regions, Steve makes selections on the dashboard to hide data related to the other two regions. This way, he can focus on trying to see what's going on with these best and worst regions. This requirement has to do with making choices about what data the user sees on the dashboard. This can be accomplished through the use of filters, but the decision we need to make is what scope the filters should be at. Should the filter selection impact the whole dashboard, or just a single chart or subset of the dashboard? In most cases, we want to apply filters to the whole dashboard, so the user won't become confused when looking across multiple areas of the dashboard. For these types of filters, we can use simple checkboxes with each checkbox corresponding to a different geographic region. Following is a screenshot showing what these filters would look like:
This next step should be obvious by now; we know what the filter design looks like, but we need to see where they would be placed on the overall dashboard design. For now, let's put the filters in the upper part of the dashboard, so that the user can easily see what filters are applied.
[ 119 ]
Designing for Insight
Requirement 4 The ability to filter by product category. Related scenario text: Similar to looking for any trends in sales by region, Steve now decides to see if any obvious patterns exist when looking at sales based on product categories. Steve brings back in all region data, to make sure that he's looking at products across all regions. He now uses the options to look at just one product category at a time. With just one product category selected, the whole dashboard shows the same information, but only for that product category. Just as with the geographic regions above, now we need to add the ability to filter based on product category. To be consistent with our previous choice, we will use the same type of design for the product category filters, and provide a single checkbox for each. Following is a screenshot of what the filter area would look like with the new filters added:
With the addition of more filters, we see that the filters area is going to take up a little more space at the top of the dashboard. Now that more space is needed, we can dedicate the whole top area of the wireframe to filters, leaving space for any more filters that may come up beyond just this scenario.
[ 120 ]
Chapter 6
Requirement 5 The ability to see sales data by both geographic region and product category at the same time. Related scenario text: Finally, because Steve has seen some patterns by region, and just by products, he wants to see if he can dig even deeper with this dashboard, mixing these two ideas to see if any specific products are doing better or worse in any specific regions. Steve opens up the detailed area where he can visually compare sales data across multiple attributes, such as both region and product category, in a way that goes beyond just what the standard dashboard shows. Steve uses the filter options to look at what appears to be the two best and worst performing regions. Then Steve also uses the filter options to focus in on just the best and worst performing product categories. While the overall dashboard allowed Steve to look at region and product data, this specialized graphic allows these two variables to be compared together in a single chart. So far, we have dealt with the requirements to look at specific geographic regions and product categories separately, but this requirement is about seeing these two concepts together. This is more of a specific analytical requirement, and goes beyond what we would typically put on a dashboard. We still want to support this requirement, but we just won't be able to easily support it on the default view of the dashboard. In these types of cases, we should use a link on the main dashboard that either leads to a different screen, or that opens up an overlay (dialog window). It's a good idea to use an overlay, which will only cover up a portion of the current screen, thereby keeping the user in the current context, while still allowing deeper analytical exploration. For the actual design of the view of sales data by both geographic region and product category, we can use the design pattern called small multiples, allowing us to show a small line graph for each specific product category, for each different region.
[ 121 ]
Designing for Insight
The following updated wireframe shows how the small multiples overlay covers only a portion of the initial wireframe screen. Notice how this allows the user to stay somewhat in the context of what lead them to the overlay in the first place. This is accomplished by placing the overlay so that the link that leads to its opening is still visible and next to the overlay if possible.
Requirement 6 The ability to see top 10 customers based on revenue. Related scenario text: Now Steve decides to look to see who the top customers are, so he brings back in all of the product categories. The dashboard already shows the top 10 customers by default, so it's easy to see. This last requirement has to do with comparing customers in a sense, but only the top 10 customers based on revenue. When we think of comparison, chart types that come to mind are pie charts and bar graphs.
[ 122 ]
Chapter 6
In the previous chapter, we discussed the many issues that come with pie charts, for example, they are usually just nice looking, and don't actually offer an efficient way to easily make sense of information. In this case, it would be difficult to label the top 10 customer names on the pie chart given the space we have. The second choice, a bar graph would fit nicely in the space we have left. To be consistent with the design of the KPI table, we can use a combination of a table and a bar graph. We will use a table that lists the top 10 customers with a single bar laid our horizontally embedded in the corresponding row of the table representing revenue. If we make the space between each row small enough, then the table will also act as a bar graph itself. Following is a screenshot of what this looks like:
[ 123 ]
Designing for Insight
Following is an image of the rough wireframe updated with this new top customer table.
We have now finished designing solutions for each of the 6 requirements, all the while being careful about how these pieces will fit together into a unified solution. Following is an image of what the final design might look like as a final mockup, going beyond the rough fidelity of the wireframe. To complete the design using available space, two more sections have been added; a top 10 products table (similar to our top 10 customers), and a line graph showing yearly sales by region. In addition, a third filter set has been added in the filter area in the header for date ranges. The implementation of this complete dashboard (except for the overlay) will be covered later in the book.
[ 124 ]
Chapter 6
Summary This chapter continued on from the previous, by leveraging the scenario we previously created. We used this scenario as the basis of an overall dashboard design, designing for each of our six requirements one at a time, while also keeping a holistic view of the overall integration of each of our design choices. We discussed design concepts related to focusing our user's attention on certain information, enabling what we call visual thinking as a basis for this design process. Therefore, all of our design choices were based on well-founded rationale, and support our specific scenario, rather than just being based on a whim of a designer or stakeholders. In the next chapter, we will look at how Blend is used to add visual styling to a design concept.
[ 125 ]
Designing your Dashboard The great thing about being a developer is that a developer can think of an idea and make it a reality. However, sometimes this reality can be difficult to use and appreciate. Designers are quite the opposite. Sure, they can think of great ideas and design a beautiful layout, but in the end, no one will able to use it. If we tie these two worlds together, we are left with the discipline of styling and integration. Styling engages users and makes applications easier to use. A good design is actually one that shouldn't be noticed. The user is there to get important information and get out. A poor design, whether visually pleasing or not, gets in the way of what the user is trying to do. It's important to find a good balance between a visually pleasing and "clean" design. In business applications, such as the dashboard shown in this chapter, a simple clean design that puts the content first is always a good approach. The intention of this chapter is not to turn a developer into a designer. However, there are several books that cover Design for Applications, such as Robert Hoekman's Designing the Obvious: A Common Sense Approach to Web Application Design and Jennifer Tidwell's Designing Interfaces: Patterns for Effective Interaction Design. What we are going to do in this chapter is look at how to take a pre-existing design and integrate it into our project. In this chapter, we will cover the basics of Microsoft Expression Blend's UI by understanding key styling terminology, learning how to reference resources, and edit basic control templates. We will create custom user controls and then use the knowledge we have learned to edit more advanced controls, such as the grid and chart.
Designing Your Dashboard
Our main tools in this chapter will be Visual Studio and Blend. Here, we'll be using Visual Studio 2010 and Blend 4, but earlier versions will work just fine. In this chapter, we will cover the following topics: •
Knowing your Tools
•
Styling in Silverlight
•
Getting started with styling our Dashboard
Knowing your tools Most developers are comfortable using Visual Studio 2010, but because we are wearing our design hats in this chapter, we will be using Microsoft Expression Blend 4. If you don't have a copy of Blend, you can download a free trial here: http://www.microsoft.com/expression/products/blend_overview.aspx
Blend combines XAML, C#, and an interactive design surface that allows the user to easily create visually striking applications. Blend has many powerful features, but for the purpose of this book, we'll stick to the basics. As many of us may have never used Blend before, let's start with an introduction to the UI.
Blend basics
When we first open Blend, we will notice it is very similar to many typical docked-panel applications. We can configure the layout anyway we want, but for the purpose of this chapter, the default is perfectly fine. The Blend UI consists of 11 dockable panels: Assets, Data, Design View, Objects and Timeline, Parts, Projects, Properties, Resources, Results, States, and Tools.
[ 128 ]
Chapter 7
In this chapter, we will only be using the most important of these panels.
Assets The Assets panel lists all of the controls, styles, behaviors, effects, and media that we can draw in the Design View. The most commonly used controls appear in the Tools panel, while the Assets panel will list all of the controls available. Once we get to know Blend, we may find ourselves only using Visual Studio for code, while laying out all of the XAML in Blend. For a project like this Dashboard, the controls have already been laid out in Visual Studio, so we will be using Blend solely for styling.
[ 129 ]
Designing Your Dashboard
We can open the Assets panel by clicking Assets at the bottom of the Tools panel, or by clicking Assets on the Window menu:
Data The Data panel allows for the creation and organization of data sources that will be used in applications. In the case of our application, the data has already been set up, so there won't be a need to work with this panel.
Design View (Artboard) The Design View (Artboard) is our work surface; here, we can draw objects and controls. The Artboard also provides us with a preview of our document. Just like in Visual Studio, we can switch between XAML, Design, and Split Views by clicking the icons in the top right of the panel, as you can see in the following image:
[ 130 ]
Chapter 7
Here we can see what the Split View looks like the following screenshot:
Objects and Timeline The Objects and Timeline panel allows us to view the hierarchical structure of all objects in the Design View. We can also select objects so that we can modify their Properties in the Properties panel, arrange them in the Hierarchical Tree, and so on. It also allows us to create and modify animations using the timeline.
[ 131 ]
Designing Your Dashboard
Parts The Parts panel will show the listed PARTS that are available for that control in its control template. We will not be working with this panel for our project:
Projects The Projects panel allows us to view all the files associated with the current open solution and any files that are open. It also allows us to manage the project's files easily.
Properties The Properties panel is where we can view and modify the properties of an object that is selected in the Design view, or under Objects and Timeline. If we modify an object directly in the Design view, the property changes will be reflected in the Properties panel. The reverse is also true. If you edit the properties in the Properties panel, the changes will be reflected in the Design view. [ 132 ]
Chapter 7
[ 133 ]
Designing Your Dashboard
Resources The Resources panel lists all the resource dictionaries and resources included within them that are used in the currently open project. We can drag resources out to apply them to objects, or we can manually add them in XAML. The Resource panel also allows us to edit the resource by clicking the Edit resource… button to the right of the resource name:
Results The Results panel displays errors and warnings, as well as output information, so we can debug errors in our application. Just as in Visual Studio, we can double-click an error to display the line of code that is causing the error.
[ 134 ]
Chapter 7
States The States panel is used to manage the various visual states of a control. By selecting a state, we start recording the visual changes that we want the users of our application to see, such as when they move the mouse over a Button. We can open all of the panels listed above by clicking Window in the main menu:
Now that we have a general understanding of Blend's UI, let's cover the basics of styling in Silverlight by learning some key definitions and walk through the basics.
Styling in Silverlight For those of you who have not worked much with styles in Silverlight and WPF, XAML follows a similar approach to Cascading Style Sheets (CSS). There are some core terms that will be used throughout this chapter that any Silverlight or WPF developer should become familiar with. •
Brush is an object used to paint a property of an element. There are several types of brushes, such as SolidColorBrush, RadialGradientBrush, LinearGradientBrush, and TileBrush.
•
Resource is a styling property, or collection of properties, that can be applied to elements throughout your application.
•
Resource Dictionary is a collection of resources. Resource dictionaries can be defined inline or externally. Style is a collection of property setters. A style is defined in a resource dictionary and targets a particular control. Styles can consist of all kinds of styling information, such as Font Family, Font Size, and Border Brush. [ 135 ]
Designing Your Dashboard
•
Control Template contains parts that make up the visual appearance of a control. A control template can be easily seen while editing a control in the visual tree of Blend under the Objects and Timeline window.
Referencing resources It is important to know how styles are being referenced in the XAML. In WPF, there are two types of resources one can use in styling, Static and Dynamic. In Silverlight, however, there are only Static resources. A Static resource processes a key by looking for the value of that key in all the referenced resource dictionaries. A Static resource requires the property to be assigned during loading.
Implementing resources Because we are using Blend, our resources will also be automatically assigned for us. However, you should be aware of what is going on in the XAML when a resource is applied. Here, we will go through the following topics: •
Creating a Button
•
Exploring a Button Control Template
•
Creating a Custom Button Control Template
•
Adding Visual States (Visual State Manager)
•
Converting Brushes to Resources
•
Creating Resource Dictionaries
Creating a Button
To create a Button, we first need to create a Silverlight project. We can do this by opening Blend and selecting New Project | Silverlight Application + Website: 1. There are several ways to create a Button: We can use the Button Tool in the Tool Bar by drawing in the Design View, or by double-clicking the tool. We can use the Assets panel by selecting the Controls item and dragging a Button into the Design View, or we can simply double-click the Button control, which will automatically add it into the Design View.
[ 136 ]
Chapter 7
2. Now that our Button is visible in the Design View, it is important to notice our Objects and Timeline panel. The Button control, [Button], will now be a child of our LayoutRoot grid. We should also note that when our Button is selected, the Properties panel reflects the properties of the Button in our Design View. Let's rename our Button to MyButton, either by double-clicking the Button in the Hierarchal tree, or by changing the name property at the top of the Properties panel. We should also take note of our XAML. It was mentioned earlier that you can change the view from Design to XAML. We can achieve this by clicking on the different icons located at the top right of the Design View:
3. The Button property x:name has changed to MyButton in the XAML. The other properties seen here in the XAML, such as Margin and HorizontalAlignment, were automatically applied when we created our Button. Now, we will look into how the Button is constructed by exploring its Control Template.
Exploring a Button's Control Template
Now, we will edit a copy of our Button's Control Template. Just like creating the Button, there are several ways to edit the template of our Button. 1. Notice that when our Button is selected at the top of our Design View, there is a Button under our document name. By clicking this Button, we can choose Edit template | Edit a Copy....
[ 137 ]
Designing Your Dashboard
2. We can also right-click the Button in the Design View or in our Objects and Timeline panel and choose Edit Template | Edit a Copy. 3. We can then go to the main menu and select Object | Edit Template | Edit a Copy... 4. Regardless of how we choose to edit the Button, a dialog will appear, asking us what we want to name our Resource (Key), and where we want to define our Resource. In this case, we will choose This Document. There are no rules on naming conventions in XAML, but the style should appropriately described as to what is being styled. Most people like to name styles by starting with where it is used, followed by the type of control it is, and then end with "Style". In this case, let's name the style MainButtonStyle. 5. Once we have clicked OK, you will notice that our Object and Timeline panel is updated and now shows the hierarchal tree displaying the parts that make up the Button's control template. 6. Let's turn back now to our MainPage so we can take a look at what happened to our XAML when we created MainButtonStyle. We can do this in two ways: °°
By either clicking the Button labelled MyButton on the top left of the Design View.
°°
By clicking the return to scope Button in the Objects and Timeline panel.
[ 138 ]
Chapter 7
7. Notice the style property being applied to the Button:
8. If we scroll to the top of our MainPage.XAML, you will notice that Blend has added the Control Template for a Button. We mentioned earlier that when we define a Resource Dictionary, it can be defined either inline or externally. This is an example of an inline Resource Dictionary. Later, we will create external resource dictionaries. There are a couple of things to notice in the XAML for the Button control template. The x:Key property defines our style name, and the TargetType property defines the type of control to which this template can apply. 9. Now that our template has been created, we can access the template in another way. The Resources panel lists all of the resources that are available. Since we created a control template for our Button, it will now be listed under MainPage.XAML in the Resources panel. Let's open the resource by clicking the Edit resource button next to our Resource name.
10. Now that we are back into the Control Template for the Button style we created earlier, let's take a few minutes and explore the tree and the various parts that make up the Button. The most important part of any control is its ContentPresenter. The ContentPresenter displays the content of the control outside of the template. By default, a Button's content is set to the string "Button". ContentPresenters are powerful because you can change the content of a control but keep the same template. Content Presenters can display anything that's placed as a child of the control in the Hierarchal Tree. Notice each part of the Button's template has different properties that may not be visible in the Base State of the Button. For instance, the rectangle DisabledVisualElement has its opacity property set to 0 and is only visible when the Button is in a disabled state. [ 139 ]
Designing Your Dashboard
Creating a Custom Button Control Template
Now, let's change the Button template to make it our own. The following image is an example of a mock-up of a Button:
Remember, we can add or delete anything in the template, but we want to keep the content presenter. 1. Let's start by deleting the Grid inside of the Background Border, as well as the DisabledVisualElement and FocusVisualElement borders. 2. Because we did not delete the Background Border, we can edit its properties to match the Button mock-up shown earlier. To do this, we need to change the following properties: Background, BorderBrush, and CornerRadius of the Background Border. 3. Let's change the CornerRadius to 5 and set the Background and Borderbrush property values. The easiest way to achieve this is to change the Background and BorderBrush right on the Background Border. However, to make our Button more dynamic, we can template-bind the Background and BorderBrush properties to the Button's Background and BorderBrush.
[ 140 ]
Chapter 7
4. We can do this by clicking the box to the right of the color swatch. We will bind the Background brush to the Background and the BorderBrush to the BorderBrush. Notice that after the property is bound, the box turns yellow.
5. Now that the properties are bound, we will leave the template and select the Button on the main page. We can now apply the color for the Buttons properties. The BorderBrush is a SolidColorBrush with a Hex value of #FF999999.
[ 141 ]
Designing Your Dashboard
6. The following diagram shows the different types of brushes that can be painted on an element:
7. We will use a slightly more complicated RadialGradientBrush for the background. From our Button mock-up, we can see a distinct line running through the center of the Button horizontally. This is achieved by using one gradient. To create this effect, our background gradient will consist of four gradient stops. A gradient stop indicates the location and color of a transition point in a gradient. We can add stops to a gradient brush by clicking below the gradient slider and then manually positioning their offset position by selecting the stop and entering a number between 0 and 100 to the bottom right of the gradient slider.
[ 142 ]
Chapter 7
8. We can see that our third stop is selected, and its color is displayed as well as its position which is at 50.1% of the slider. Let's take a look at the XAML:
The order in which the gradient stops appear in the XAML is unimportant because their position is determined by their offset. 9. At this point, we can see that the Button is starting to look like our mock-up. We need to set the Button's Height and Width properties, as well as Font, Font size, and Foreground color for the Button's text. We will do this on the Button directly. 10. In the mock-up, the Button width is 103 and the height is 35. We used the font trebuchet #333333 for the text colour, and 14 pixels for the font size. One important thing to note about Blend is that in the Properties panel, the font size units are in points (pt). In XAML, however, it produces this value in pixels. To achieve a font size of 14 pixels like we have in our mock-up, we will need to set the points to 10.5. One quick way around this is to set the font size in XAML to 14. Blend will automatically convert the number for you. The following is a quick reference for point to pixel conversion: Point (pt)
Pixel (px)~
7pt
9.333
8pt
10.666
9pt
12
10pt
13.333
11pt
14.666
12pt
16
13pt
17.333
14pt
18.666
15pt
20 [ 143 ]
Designing Your Dashboard
By now, our Button should match the mock-up almost exactly. Let's take a look at the following XAML:
We can see that the Height, Width, FontFamily, FontSize, and Foreground properties are set. If we run our project by clicking Project | Run Project (F5, Ctrl + F5), we will see our Button. However, if we interact with it, we'll notice that there are no indicators that let us know our mouse is over it, or that we are clicking the Button. We can handle this by using the States panel in Blend.
Adding Visual States (Visual State Manager) The States panel manages the states of a control. The states can only be modified inside the control template. Let's go back inside the template of the Button and open the States panel. You will notice that the States panel consists of a Base State and two States groups. Common States consist of: •
Normal: A Default State of a Control. This state is often used to return visuals to their original values when using Storyboards
•
MouseOver: A State that is triggered when the mouse pointer hovers over the control
•
Pressed: A State that is triggered when the user left mouse clicks on the control
•
Disabled: State when the control is Disabled
Focus States consist of: •
Unfocused: A State in which the control is not in focus (Default State) [ 144 ]
Chapter 7
•
Focused: A Focused state occurs when a control is in focus. When a user tabs to that control or the user has selected that control with their mouse.
When we click on one of these States in the States panel, Blend starts recording our actions and places a recording Icon in the top left corner of our Design View panel.
In this case, we don't need to record an action for every one of our states. States such as Normal and Unfocused are simply a state that returns to the Base State. Let's look at our mock-up for the various states of our Button. We can also look at a digital version of the mock-up available under the Images folder in the Chapter 7 folder available with the book.
[ 145 ]
Designing Your Dashboard
You can see that we have five states, but only four to create because the base state is the default state. Those four states are: •
MouseOver
•
Pressed
•
Disabled
•
Focused
MouseOver State 1. Let's start with creating the MouseOver state. There are a couple of ways to do this. Firstly, you can animate the color of the background border. However, there are two important things preventing us from doing this. Firstly, the Background and BorderBrush are template-bound and animating the color will break that bind. Secondly, later on, we will be making those fills into brush resources, which unfortunately cannot be animated. 2. Let's select the base state and add a rectangle to our Button's control template. The easiest way to do this is to select the grid inside of the template and double-click the Rectangle Tool in the Tools panel. 3. Now that our Rectangle is showing in the Objects and Timeline panel, let's rename it to MouseOverRectangle. We will also need to make sure that the rectangle is positioned behind the content presenter:
[ 146 ]
Chapter 7
4. We can now style the rectangle to match the MouseOver state in our mock-up. First, let's match the corner radius of the Background Border. Then, we will need to set the FillColor, StrokeColor, and the Radius X and Y Properties. Let's take a look at our XAML:
We can now see that our MouseOverRectangle matches our MouseOver state in our mock-up.
5. We now need to make our MouseOverRectangle activate during the MouseOver state. With the Base State selected, change the Opacity of the MouseOverRectangle to 0. 6. Now select the MouseOver state, and change the Opacity of the MouseOverRectangle to 100. 7. Finally, run the Project.
[ 147 ]
Designing Your Dashboard
Adding transistions to the MouseOver State We can see that our MouseOver State is now working. However, the MouseOver state just appears, whereas we would want it to fade in. To achieve this, we could use the timeline by either clicking the Show Timeline button or by setting the TransitionDuration property. For this example, we will be using the TransitionDuration property: 1. Let's set the Transistion Duration to 0.2:
2. We can also set the Easing Function property. An Easing Function allows you to apply various transition types to your animations. Instead of an unnatural movement, Easing Functions allow for realistic movements that simulate effects such as gravity. Silverlight has built-in easing functions that we can set for our animation. For this example, let's select Cubic Out.
[ 148 ]
Chapter 7
3. Now, let's run the project again. You will notice that the MouseOver State now fades in.
Pressed State Now, let's work on the Pressed State: 1. Make sure the Base State is selected in the States panel. Like the MouseOver State, we will create a Rectangle and name it PressedRectangle. We also want to make sure that the contentPresenter is in front. The Properties will be the same as our MouseOverRectangle, except the Fill Property. This time we will be using a RadialGradient fill.
[ 149 ]
Designing Your Dashboard
2. Let's use two white gradient stops, but set the first stop to have an Alpha of 100% and the second to have an Alpha of 0%. We can set the Alpha by filling in a value for "A" under the RGB values.
3. We now have a RadialGradient fading from white in the center to a 0% white on the outside. However, this still isn't looking quite how we want for a few reasons: °°
Firstly, the background isn't blue. This is because we are still on our base state (remember that the MouseOver State is set to zero).
°°
Secondly, the RadialGradient isn't originating from the bottom. We can fix this by using the Gradient Tool. Select the Gradient Tool, as shown in the following image:
[ 150 ]
Chapter 7
4. Our Artboard now shows gradient handles. This enables us to postion, stretch, and change the Gradient right on the Artboard. Let's get it to look as follows:
Let's take a look at our XAML for the PressedRectangle: We will notice that the XAML shows position properties for the RadialGradientBrush.
5. Now, we just need to set the PressedRectangle Opacity to 0 for the Base State. 6. Then, select the Pressed State, and set the Opacity to 100. 7. We want the MouseOver state to be 100 for the Pressed state as well. We don't need to set the TransitionDuration and the Easing Function, because those properties apply to the entire Common States Group. 8. Run the project, and try clicking the Button. Using what we have learned, let's see if we can do the Disabled State and Focused State by ourselves. The Disabled State is as simple as setting the Opacity on the Main Grid to 50, while the Disabled State is selected in the States panel. Remember, when doing the Focused state, that it is part of the Focus States Group, so the Transition Duration and Easing Function need to be set for that group. We should now have a Button that looks like our mock-up and functions correctly. Now, let's convert our brushes for the Button into Resources.
[ 151 ]
Designing Your Dashboard
Converting Brushes to Resources
Now that we have created our custom Button control template, we now need to convert our brushes into resources. For now, like the Button template, we will keep our styles inline. 1. Let's select our Button and click the square to the right of our Background swatch in the Properties panel. In the menu, click Convert to NewResource…
2. Let's name our resource ButtonBackgroundBrush and define the Brush resource in This document. Click OK.
[ 152 ]
Chapter 7
3. Notice how the square we clicked to create the resource is green. Green indicates that a resource is being applied. We can also see that the Brush type is set to Brush Resources, and our new resource is listed under Local Brush Resources in the Resources panel:
4. Notice how our Button in the XAML has its Background Property defined as: Background="{StaticResource ButtonBackgroundBrush}"
5. We can also scroll up to where our resources are defined and find the definition for the brush we just created:
6. As you can see, Blend makes creating resources very easy. Let's create resources for the rest of our brushes for our Button. Once we have created brush resources for the Button›s Background, BorderBrush, and Foreground, we should have something like the following code inside of our resource dictionary: [ 153 ]
Designing Your Dashboard
7. Remember that there are also brushes set inside of our Custom Button Control Template. Once we are inside of our template, we will notice that the MouseOverRectangle shares the same border brush as our Button. When we select the Stroke of the MouseOverRectangle, we will want to apply the resource ButtonBorderBrush we defined earlier. Select the brush type Brush Resources, and select ButtonBorderBrush Resource from the list.
8. On our own, let's finish applying and creating our brush resources. 9. All we need to do now is to learn how to create external Resource Dictionaries, and we will have learned the basics of styling in Silverlight!
[ 154 ]
Chapter 7
Creating Resource Dictionaries We have already created resources and stored them internally in our XAML pages, but now we want to create a resource dictionary that can be shared across many different pages. Setting up a project correctly from the start saves time later. There are many different schools of thought on how to use resource dictionaries, but using one for your control templates and the other for brushes keeps things well organized. This separation of resource dictionaries allows you to change the theme of your application quickly or make color updates easily. 1. Let's create a folder to house our resources. Resources, in this sense, are not limited to resource dictionaries. We can use this folder for resources such as images, fonts, and so on. Inside our Project panel, right-click on the Silverlight Application, and add a new folder named Resources. Now, rightclick on the resources folder, and select Add New Item…
[ 155 ]
Designing Your Dashboard
2. We will start with our Control Resource Dictionary. This will house all the control templates in our application. Select Resource Dictionary, and name it ControlStyles.xaml.
3. You will notice that this automatically adds an App.xaml tab in our Design view. Let's click the App.xaml tab and see what has changed. You will notice that Blend has referenced our new Resource Dictionary:
4. Let›s repeat this process for our Brushes; we can name this resource dictionary ApplicationBrushes.xaml. From now on, whenever we create a resource we will add them to their perspective resource dictionary. Try adding a new Button to the project and defining its control template in the ControlStyles.xaml Resource Dictionary. When we create a style resource, we can now select our Resource dictionary under Define in… and select the resource dictionary in which we would like the resource to live.
[ 156 ]
Chapter 7
Now, you might be thinking, "What about the Resources we defined inside our MainPage.xaml for the Button and Brushes? Should we move those?" Absolutely! If you open the MainPage.xaml, you will notice that our UserControl Resources at the top of the page. Copy the Button style over to your Controlstyles.xaml resource dictionary, and your Brush Resources over to your ApplicationBrushes.xaml resource dictionary. You may run into some reference issues when you try to copy over the Button style. Use the results panel to figure out what else needs to be copied over. We are now ready to use what we have just learned to take on the styling of our Dashboard!
Getting started with styling our Dashboard Now that we have covered the basics of control templating, it's time to take on our Dashboard. The Dashboard contains many different controls, all with unique challenges in templating. We cannot cover all the ins and outs of every control, but we can walk through some of the more complex ones, and then use that knowledge to take on the rest of the dashboard. We can view the unstyled version of the application available in the Chapter 7 folder under the ApplicationUnStyled folder, or we can use the application we built from Chapter 6. Now that we have our application opened in Blend, we will need to start by setting up our resource dictionaries and assets folder like we did earlier. Let's take a look at the design. We can also view a full resolution color copy of the design available in the Images folder in the Chapter 7 folder available with this book. Here we cover the following topics: •
Creating a Custom User Control in Blend
•
Styling the Grid and Chart
Creating a custom User Control in Blend
We will start by creating a custom User Control for the background of each panel. We can see that the background of each panel is white and has a dropshadow effect. Effects like dropshadows can be done with Blend's built-in effects, but effects like this are memory hogs and can be better achieved by using offset rectangles. To get started, you will need to complete the following steps:
[ 157 ]
Designing Your Dashboard
1. We will start by creating a UserControl in Blend. In the Projects panel, rightclick on the controls folder and click Add New Item… In the New Item Dialog, select UserControl, and name it PanelBackground.
2. You will notice that Blend added the PanelBackground.xaml file to our project, and we are now in a blank document. The dropshadow rectangles will need to be placed in a grid with negative margins so its size doesn't get included in our panel size. 3. Create a Grid and put a left, right, and bottom margin of -4 on that grid. This means that the grid will hang off four pixels on the left, right, and bottom of our panel.
[ 158 ]
Chapter 7
4. Inside this grid, we will place four rectangles offsetting each other by one and each being slightly darker than the other. The following is the XAML for the four rectangles:
5. Now that our drop shadow is in place, we will add an Opacity Mask to the grid we just created. The Opacity masks allow us to mask parts of an object using a brush. To create a fading effect, we will use a gradient brush. The color doesn't matter, but the alpha of the gradient stops does. We want the gradient to go from 0% to 100%. Our XAML should look as follows:
6. Now that our dropshadow and opacity mask are in place, we will need to add a white rectangle in the LayoutRoot, making sure it's in front of the grid housing our dropshadow. 7. Next, we will add a rectangle with a Height of 3, a Fill of #FFE2E2E2, and aligned to the top. Our completed XAML should look as follows:
8. Let's build our project, and then open our Dashboard.xaml under Views. [ 159 ]
Designing Your Dashboard
9. Navigate to the Assets panel or the Assets button in the toolbar, and search for the PanelBackground. You will notice it is now a control:
We now need to add the User Control to the background of all the User Controls being pulled into our Dashboard.xaml. Remember to make sure that the Height and Width are set to Auto, and that the Vertical and Horizontal Alignment to Stretch, this allows for our User Control to fill the whole area of each panel's background. Once all of our panel backgrounds are in place, we can start styling the two major controls we are using throughout our dashboard.
Styling the Grid and Chart Our dashboard uses two complex controls, and understanding how to style them can be difficult. Unlike the Button that we created earlier, which consisted of a template, the grid and chart consist of multiple templates that make up the control. All of these templates can be edited by right clicking and selecting Additional Templates. It is very easy to edit templates and make the control overly complicated, so it is best to start with properties that are already exposed to us, and work from there. 1. Open FinancialIndicatorControl.xaml under controls in our project panel, and select the FinancialKPI chart. 2. Now, in the Properties panel, we can see several properties that we can change.
[ 160 ]
Chapter 7
3. Using our mock-up as reference, we can see our grid has no vertical or horizontal grid lines or a border. Let's set the brush properties for these to Null or No brush:
4. Next, we can set the AlternatingRowBackground brush to #FFF5F5F5. Remember, we want to convert our brushes into resources so we can quickly make color updates later if needed. We can either do this now or remember to come back later. 5. For explanatory purposes, let's convert the alternating row background brush into a resource and save it to ApplicationBrushes.xaml. We can name our resource AlternatingRowBrush:
Now that our exposed properties are handled, it's time to start editing the templates of our grid. As we mentioned earlier, controls like a grid consist of a main template and sub-templates that make up different parts of the control. If we right-click and open the additional templates menu, we can see the other templates that this particular control uses. Using the chart and grid template diagrams, Which are located under the Diagrams folder in the Chapte 7 folder available with the book, we can see what template affects what part of the control. Using these diagrams, the knowledge we have gained from this chapter, and the source code from the projects available for download, means that we are able to make a professionally styled dashboard. [ 161 ]
Designing Your Dashboard
Summary Microsoft Expression Blend is a powerful tool that is not just for designers. Having a simple understanding of Blend's layout, a few key styling terms, and the ability to create resources, resource dictionaries, and user controls makes any developer more independent, without having to rely too much on a designer. Developers can now create visually striking applications that look just as good as those created by designers. The next chapter will focus on building an end-to-end solution that uses the Microsoft SQL Server AdventureWorks sample database.
[ 162 ]
Building an End-to-End Solution By now, you should have a good understanding of the Silverlight platform and what is involved when designing a good dashboard experience. In this chapter, we are going to expand your knowledge of building Silverlight dashboards by focusing on building an end-to-end solution that uses the Microsoft SQL Server AdventureWorks sample database. Throughout this chapter, we will explore how to use the N-Tier application model to build out the AdventureWorks dashboard application. We will dive into the key patterns and technologies you need to understand to build an N-Tier application, including how to use the Model View View-Model (MVVM) pattern to take advantage of the rich data binding capabilities in Silverlight, how to use Windows Communication Foundation (WCF) to expose data to your application, and how to utilize patterns such as service layer and repository to tie everything together. In this chapter, we will cover the following topics: •
Dashboard prerequisites
•
Dashboard requirements
•
Designing the solution
•
Setting up the data source
•
Building the server components
•
Defining the presentation layer
Building an End-to-End Solution
Dashboard prerequisites Before we get started, there are a couple of prerequisites that you will need to have installed on your machine to build this sample application. First, you will need to have Microsoft SQL Server 2008 running; if you need to, you can download the free Microsoft SQL Server 2008 express edition. In addition, you will need to download and restore the AdventureWorks sample database. If you haven't downloaded this yet, it would be a good time to download the sample code for this chapter. We will be covering a lot of different code blocks; so having the sample handy will make it easier to follow along. A list of prerequisites and download links can be found here: •
SQL Server 2008 Express: http://www.microsoft.com/express/Database/
•
Adventure Works Database: http://msftdbprodsamples.codeplex.com/
•
Sample Code Download: Download the code bundle for this book for the PacktPub website
Dashboard requirements When building any application, a good place to start before diving into coding is to review the requirements and features of the application. The AdventureWorks dashboard sample contains an executive-style dashboard that highlights the Key Performance Indicators (KPI) for running the AdventureWorks business. Here is an image of the executive dashboard and all its screen elements. The screen contains several KPI values displayed using grids and charts. Above the KPI values are the facets used for filtering the data displayed on the dashboard.
[ 164 ]
Chapter 8
The main screen (KPI Dashboard) contains five components: •
Header (Filters): This section contains the facets (filters) that an end user would use to filter the different components of the dashboard.
•
Financial Indictors: This section lists the financial Key Performance Indicators (KPIs).
•
Yearly Sales by Region: This section displays the years, sales for each region in the AdentureWorks database.
[ 165 ]
Building an End-to-End Solution
•
Top Products: This section displays the top products sold, based on the selected facets.
•
Top Customers: This section displays the top customer, based on the selected facets.
Designing the solution When defining the technical design for your solution, it is important to keep the functional and non-functional requirements of your application in mind. This is particularly important when designing a dashboard application. Your users need easy and quick access to their information, so that they make the correct decision without delay.
Describing an N-Tier application design The AdventureWorks dashboard application will be using an N-Tier layered approach. The Silverlight client will be built using the Model View View-Model (MVVM) pattern and be responsible for maintaining state across service calls to minimize the need for refreshing data. The MVVM pattern is a perfect fit when you are using N-Tier application architecture. The pattern promotes loosely couple the different components of the application into separate classes. Each class is only responsible for a small set of functionality. This allows you to easily abstract calling the service layer of the application to retrieve the data to be displayed in the dashboard. A single composite Windows Communication Foundation (WCF) service will be used to retrieve the data for the dashboard. The WCF service will be responsible for loading the domain (business) model of the application by calling different data access repositories that handle the loading of each set of KPI values from the AdventueWorks SQL Server database. Coming up with the correct data access strategy when building a dashboard application is the most critical technical design decision you need to make. Generally, dashboards need data from several different sources. Instead of trying to access all the different sources in real time, a better approach is to aggregate the data into a single database. This will require some more upfront planning and work, but greatly simplifies and speeds up the user experience for using your dashboard.
[ 166 ]
Chapter 8
The AdventureWorks database we are going to use follows this model. It uses a data warehouse star schema physical data model. The following image shows the three original sources for the data in the AdventureWorks database. Once data was loaded from each of these sources, it was aggregated into the star schema model. In the sample, we will be using a set of custom stored procedures to make accessing the data easier, and structure the data in the format that best meets the requirements of the dashboard.
Silverlight Client
WCF
AdventureWorks Database
Order Entry
Customer
Product
Coming up with a good technical design can be a very complex process. There are no silver bullets or magic cookie-cutter approaches to solve every challenge you might encounter. It's always good to keep things in the right context, and remember the golden rule of technical design "It Depends". A good example of this is dealing with non-functional requirements. It may seem like a good idea to load all the data your application might need upfront. Although this would minimize refreshing the application as the user interacts with it, it would require a longer load time that would impact the usability and scalability of your application. Another approach is to load only the necessary data you need upfront, and call back to your data source as you need additional data. Unfortunately, this approach can impact application usability and scalability as well. Properly handling security can be challenging too. It might seem easy to just turn on HTTPS or just use Windows Authentication, but, that impacts the performance of the application, and limits your application to only be available when someone is connected to your network.
[ 167 ]
Building an End-to-End Solution
The list of key non-functional requirements are as follows: •
Performance: How effectively does the application handle loading, saving, or processing data.
•
Scalability: How well does the application handle increased user demand.
•
Security: How secure is your solution. Do the right people have access to the correct information, and is everyone restricted to only the information they need.
•
Usability: How happy are users using your application. Does the application help them do their job or get in there way.
•
Interoperability: How effectively can the application interact with external systems.
To handle these complexities, N-Tier design promotes the concept of layer architecture. Each layer focuses on a small set of responsibilities, and uses abstraction to make each layer loosely coupled from the other layers. This makes it possible to switch out one layer without impacting the other layers, or expand a layer to meet additional features.
Sample project structure When using an N-Tier application design approach, your solution structure will include several projects. Each project will contain a small subset of the classes required for the application. Typically, you have three to four projects: Silverlight Client, Web Site (Service Project), Business Layer (Domain Model), and Data Access Layer. We will now walkthrough the different projects in the sample solution, touching on the key classes and responsibilities of each project. The Silverlight client Chapter8 project contains: •
View (Screens and Controls) of the dashboard
•
View-Models that are data bound to the views
•
Service layer used for calling the WCF data access service
[ 168 ]
Chapter 8
The next project in the solution is the business layer project: Chapter8.Business. This project contains the domain model of the application. Each class has been set up as WCF Data contract; this allows them to be serialized by the WCF service and returned to the Silverlight client. To make things easier and more maintainable, the domain model classes will be shared between a Silverlight class library that will be referenced by the Silverlight client, and a .NET class library that will be used by the WCF service.
[ 169 ]
Building an End-to-End Solution
This project Chapter8.Web.Business is the server-side equivalent to the Silverlight business model class library. This project is referenced by the Web Site project that uses these classes when loading the data for the dashboard. The arrow icon next to each class means that the classes are being shared between this project and the Chapter8. Business Silverlight class library.
[ 170 ]
Chapter 8
The last project in the solution is the website Chaper8.Web for the dashboard application. This project contains the ASPX host page for the Silverlight client, the WCF service, and data access layer for the application.
[ 171 ]
Building an End-to-End Solution
Setting up the Data Source We will be using the Microsoft SQL Server AdventureWorks sample database as the data source for our dashboard. The AdventureWorks database represents a fictitious multinational manufacturing company that manufactures and sells metal and composite bicycles in different regions worldwide, including North America, Europe, and Asia. The Dashboard we are going to build will focus on displaying North America data related to top products and customers and financial Key Performance Indicators (KPI) stored in the AdevntureWorks database. If you do not have the AdventureWorks database installed, see the Dashboard Prerequisites section in this chapter for details of where to download and install the sample database.
[ 172 ]
Chapter 8
Reviewing the database schema The installer for AdventureWorks sets up several sample databases and OLAP cubes that you can use for building applications. For the purposes of this book, we are going to use the AdventureWorksDW2008R2 database. This database represents a typical enterprise data warehouse that uses a star schema and fact tables to aggregate data. It is the main data source for the OLAP cubes that ships with the AdventureWorks download. Now is a good time to install the custom SQL Scripts that come in the chapter's download. You can find the SQL scripts located in the Chapter8.Web project SQL directory. The scripts contain a set of custom stored procedures for retrieving data for the dashboard from the AdventureWorksDW2008 database.
[ 173 ]
Building an End-to-End Solution
Here are the key tables we are going to use in the AdventureWorks Dashboard. Fact tables contain the measures (KPI) data that will be displayed in the dashboard, and dimension tables contain the conditions that can be used for grouping and filtering the data in the fact tables. For example, we want to see the top selling products online, so we will need to take the measures defined in the FactInternetSales database, and group them by the products and product classes in the DimProduct Table. •
FactInternetSales: Internet Sales Measures
•
FactResellerSales: Reseller Measures
•
FactCallCenter: Customer Support Measures
•
FactSalesQuotas: Sales Quotes Measures
•
FactFinance: Financial Measures
•
DimDepartmentGroup: Department and Groups
•
DimAccount: Financial Accounts
•
DimOrganization: Organizations
•
DimScenarios: Data Scenarios (Actual and Budget)
•
DimSalesTerritory: Sales Territories
•
DimCustomer: Customers
•
DimGeography: Geography Locations
•
DimProduct: Products
•
DimDate: Dates and Time
Stored procedures To make it easier to consume the data stored in the AdventureWorks database, the sample uses a set of stored procedures that structure the data based on the requirements for the dashboard. Each stored procedure is responsible for loading the KPI data for its corresponding dashboard component (Grid, Chart, and so on). To keep things simple, we will be using dynamic SQL to keep the custom stored procedure as straightforward as possible. There are a couple of important things to keep in mind when using dynamic SQL. Firstly, they are prone to SQL injection attacks, and they do not offer the best performance for querying large sets of data. For our sample dashboard, we are only dealing with several hundred rows at most, so using dynamic SQL is not a large performance hit.
[ 174 ]
Chapter 8
For a production dashboard application, you should consider alternatives types of data access. One approach would be to de-normalize the database schema to match the expected output for your dashboard. The biggest drawback to this approach would be managing changes to the schema as the requirements to your application change. Plus for larger datasets, you could potentially expand the storage requirement for your application significantly. Another approach to consider is creating and deploying a SQL Server data analysis cube to your server and sending MDX queries to filter the dashboard's data. This approach would offer the best scalability and most flexibility for querying and filtering data. Unfortunately, Silverlight does not contain any libraries for reading and querying SQL Server data analysis cubes. So, you would need to build these capabilities into your WCF service, which would require significant upfront design to be build a scalable and manageable solution. If you are interested in using SQL Server Analysis cubes with your dashboard, you can take a look at XML for Analysis in Analysis Services (XMLA). XMLA is a web services (ISAPI Filter) that allows you to send MDX queries using SOAP messages. For more information see: http://msdn.microsoft.com/ en-us/library/ms186654(v=sql.90).aspx
spTopUsInternetProducts The top product sales stored procedure returns the list of top products sold online within the US. The procedure filters its data based on the date range, sales territory, and product category lists passed in as follows: CREATEPROCEDURE [dbo].[spTopUsInternetProducts] @DateTimeStart DateTime, @DateTimeEnd DateTime, @TerritoryList nvarchar(200), @CategoryList nvarchar(200) AS EXEC('SELECT DP.EnglishProductName AS ProductName, SUM(FIS.SalesAmount) AS Sales FROM FactInternetSales FIS INNER JOIN DimProduct DP ON DP.ProductKey = FIS.ProductKey INNER JOIN DimProductCategory DC ON DC.ProductCategoryKey = DP.ProductSubcategoryKey INNER JOIN DimDate DD ON DD.DateKey = FIS.OrderDateKey INNER JOIN DimSalesTerritory DS ON DS.SalesTerritoryKey = FIS.SalesTerritoryKey [ 175 ]
Building an End-to-End Solution WHERE DS.SalesTerritoryCountry = ''United States'' AND DS.SalesTerritoryRegion IN ('+ @TerritoryList +') AND DC.ProductCategoryKey IN ('+ @CategoryList +') AND DD.FullDateAlternateKey BETWEEN '''+ @DateTimeStart +''' AND '''+ @DateTimeEnd +''' GROUP BY DP.EnglishProductName ORDER BY Sales DESC')
spTopUsInternetCustomers The top customer sales stored procedure returns the list of top US customers who made purchases online. The procedure filters its data based on the date range, sales territory, and product category lists passed in as follows: CREATEPROCEDURE [dbo].[spTopUsInternetCustomers] @DateTimeStart DateTime, @DateTimeEnd DateTime, @TerritoryList nvarchar(200), @CategoryList nvarchar(200) AS EXEC('SELECT MAX(DCS.FirstName) + '' '' + MAX(DCS.LastName) AS Name, SUM(FIS.SalesAmount) AS Sales FROM FactInternetSales FIS INNER JOIN DimCustomer DCS on DCS.CustomerKey = FIS.CustomerKey INNER JOIN DimProduct DP ON DP.ProductKey = FIS.ProductKey INNER JOIN DimProductCategory DC ON DC.ProductCategoryKey = DP.ProductSubcategoryKey INNER JOIN DimDate DD ON DD.DateKey = FIS.OrderDateKey INNER JOIN DimSalesTerritory DS ON DS.SalesTerritoryKey = FIS.SalesTerritoryKey WHERE DS.SalesTerritoryCountry = ''United States'' AND DS.SalesTerritoryRegion IN ('+ @TerritoryList +') AND DC.ProductCategoryKey IN ('+ @CategoryList +') AND DD.FullDateAlternateKey BETWEEN '''+ @DateTimeStart +''' AND '''+ @DateTimeEnd +''' GROUP BY DCS.CustomerKey ORDER BY Sales DESC')
[ 176 ]
Chapter 8
spSalesByRegion
The sales by region stored procedure returns the sales data for the different US territories. The procedure supports filtering data by product category and sales territories. A UNION SQL statement is used by the procedure to combine Internet and retail sales as follows: CREATEPROCEDURE [dbo].[spSalesByRegion] @TerritoryList nvarchar(200), @CategoryList nvarchar(200) AS EXEC('SELECT MIN(d.FullDateAlternateKey) as OrderDate, SUM(CASE WHEN d.SalesTerritoryRegion = ''Northeast'' THEN d.SalesAmount ELSE 0 END) AS NortheastSales, SUM(CASE WHEN d.SalesTerritoryRegion = ''Southeast'' THEN d.SalesAmount ELSE 0 END) AS SoutheastSales, SUM(CASE WHEN d.SalesTerritoryRegion = ''Central'' THEN d.SalesAmount ELSE 0 END) AS CentralSales, SUM(CASE WHEN d.SalesTerritoryRegion = ''Southwest'' THEN d.SalesAmount ELSE 0 END) AS SouthwestSales, SUM(CASE WHEN d.SalesTerritoryRegion = ''Northwest'' THEN d.SalesAmount ELSE 0 END) AS NorthwestSales FROM (SELECT DD.FiscalYear, FIS.SalesAmount, ST.SalesTerritoryRegion, DD.FullDateAlternateKey, DC.ProductCategoryKey FROM FactInternetSales FIS INNER JOIN DimProduct DP on DP.ProductKey = FIS.ProductKey INNER JOIN DimProductCategory DC ON DC.ProductCategoryKey = DP.ProductSubcategoryKey INNER JOIN DimSalesTerritory ST ON ST.SalesTerritoryKey = FIS.SalesTerritoryKey INNER JOIN DimDate DD on DD.DateKey = FIS.OrderDateKey [ 177 ]
Building an End-to-End Solution WHERE ST.SalesTerritoryCountry = ''United States'' AND DD.FiscalYear != 2005 UNION SELECT DD.FiscalYear, FIS.SalesAmount, ST.SalesTerritoryRegion, DD.FullDateAlternateKey, DC.ProductCategoryKey FROM FactResellerSales FIS JOIN DimProduct DP on DP.ProductKey = FIS.ProductKey INNER JOIN DimProductCategory DC ON DC.ProductCategoryKey = DP.ProductSubcategoryKey JOIN DimSalesTerritory ST ON ST.SalesTerritoryKey = FIS.SalesTerritoryKey JOIN DimDate DD on DD.DateKey = FIS.OrderDateKey WHERE ST.SalesTerritoryCountry = ''United States'' AND DD.FiscalYear != 2005 ) d WHERE d.SalesTerritoryRegion IN ('+ @TerritoryList +') AND d.ProductCategoryKey IN ('+ @CategoryList +') GROUP BY d.FiscalYear')
spFinanceData The finance data stored procedure returns sales data for the last twelve months for key financial accounts in the AdventureWorks database. The procedure uses the CASE/WHEN SQL statement to group sales data by month as follows: CREATEPROCEDURE [dbo].[spFinanceData] AS SELECT d.AccountKey, Name, Amount, JanSales, FebSales, MarSales, AprSales, MaySales, JuneSales, JulySales, AugSales, SeptSales, OctSales, [ 178 ]
Chapter 8 NovSales, DecSales FROM (SELECT DA.AccountKey, DA.AccountDescription AS Name,SUM(FF.Amount)as Amount, (SUM(FF.Amount)* .05)astarget FROM FactFinance FF INNERJOIN DimAccount DA on DA.AccountKey = FF.AccountKey INNERJOIN DimDate DD on DD.DateKey = FF.DateKey WHERE DD.FiscalYear = 2006 GROUPBY DA.AccountKey, DA.AccountDescription)AS d INNERJOIN(SELECT DA.AccountKey, SUM(CASE WHEN DD.MonthNumberOfYear = 1 THEN FF.Amount ELSE 0 END)AS JanSales, SUM(CASE WHEN DD.MonthNumberOfYear = 2 THEN FF.Amount ELSE 0 END)AS FebSales, SUM(CASE WHEN DD.MonthNumberOfYear = 3 THEN FF.Amount ELSE 0 END)AS MarSales, SUM(CASE WHEN DD.MonthNumberOfYear = 4 THEN FF.Amount ELSE 0 END)AS AprSales, SUM(CASE WHEN DD.MonthNumberOfYear = 5 THEN FF.Amount ELSE 0 END)AS MaySales, SUM(CASE WHEN DD.MonthNumberOfYear = 6 THEN FF.Amount ELSE 0 END)AS JuneSales, SUM(CASE WHEN DD.MonthNumberOfYear = 7 THEN FF.Amount ELSE 0 END)AS JulySales, SUM(CASE WHEN DD.MonthNumberOfYear = 8 THEN FF.Amount ELSE 0 END)AS AugSales, [ 179 ]
Building an End-to-End Solution SUM(CASE WHEN DD.MonthNumberOfYear = 9 THEN FF.Amount ELSE 0 END)AS SeptSales, SUM(CASE WHEN DD.MonthNumberOfYear = 10 THEN FF.Amount ELSE 0 END)AS OctSales, SUM(CASE WHEN DD.MonthNumberOfYear = 11 THEN FF.Amount ELSE 0 END)AS NovSales, SUM(CASE WHEN DD.MonthNumberOfYear = 12 THEN FF.Amount ELSE 0 END)AS DecSales FROM FactFinance FF INNERJOIN DimAccount DA on DA.AccountKey = FF.AccountKey INNERJOIN DimDate DD on DD.DateKey = FF.DateKey WHERE DD.FiscalYear = 2006 AND DA.AccountKey in(4, 8, 29, 30, 32, 96, 74, 72) GROUPBY DA.AccountKey) r ON r.AccountKey = d.AccountKey ORDERBY Name
Building the server components
Now that we have the Dashboard data source set up, we need to switch gears and focus on building out the server components needed to display data in the application. We will be building the following server components: Windows Communication Foundation (WCF) service, Domain Model, and data access repositories. The AdventureWorks Dashboard Silverlight client will reference the WCF service we are about to build to display and filter data displayed in the Dashboard.
Domain Model (Shared Between Client and Server) A Domain Model is a set of business classes, usually defined as Plain Old CLR Objects (POCO). These classes consist of data attributes (Properties) and behaviors (Methods) that are responsible for handling the business rules and logic for an application. [ 180 ]
Chapter 8
For the AdventureWorks Dashboard application, the domain model is fairly simple, and mainly focuses on defining the data attributes that will be displayed in the application. To streamline and make the application easier to maintain, the domain model classes will be shared between the client and server. They will also be used as the Data Contracts by the WCF service.
Key Classes in the Domain Model are as follows: • •
Dashboard Context: Root class in our domain model. Keeps reference
to each of the key data classes in the model.
Dashboard Filter: Represents the data filters used for filtering
the dashboard
•
FinancialKPIItem: List of Key Performance Indicators (KPI)
•
SalesTerritoryKPI: List of sales data for each region
•
KPIItem: Generic class representing a KPI Value (Used for displaying customers or products)
[ 181 ]
Building an End-to-End Solution
The DashboardContext class represents the aggregate root of our domain model. An aggregate root has the responsibility of exposing all the key classes in the model. Each key component of the dashboard is represented as a property in the context class: using System.Collections.Generic; using System.Runtime.Serialization; using Chapter8.Business.Service; namespace Chapter8.Business.Model { [DataContract(Name = "Dashboard", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassDashboardContext { [DataMember] publicIList FinancialKPI { get; set; } [DataMember] publicIList SalesTerritoryKPI { get; set; } [DataMember] publicIList ProductKPI { get; set; } [DataMember] publicIList CustomerKPI { get; set; } privateDashboardFilter filter; publicDashboardFilter Filter { get { if (this.filter == null) this.filter = newDashboardFilter(); returnthis.filter; } } } }
The DashboardFilter class represents all the data filters (Time, Regions, and Product Types) that can be used to filter the dashboard. When the user changes a filter value an instance of this class is created and passed to the WCF service and used for updating the displayed data.
[ 182 ]
Chapter 8 The WCF service passes the DashboardFilter into each repository class select method. The select method uses the filter values passed in as parameters to its cordoning stored procedure. using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Text; using Chapter8.Business.Service; namespace Chapter8.Business.Model { [DataContract(Name = "DashboardFilter", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassDashboardFilter { [DataMember] publicDateFilter DateRange { get; set; } [DataMember] publicIList DashboardFilters { get; set; } // Get the list of sales territory to filter data privatestring territoryList = string.Empty; publicstring GetterritoryList() { if (string.IsNullOrEmpty(this.territoryList)) { if (this.DashboardFilters != null) { this.territoryList = this.FilterList("Region", true); } } returnthis.territoryList; } // Get the list of product categories to filter data privatestring categoryList = string.Empty; publicstring GetCategoryList() { if (string.IsNullOrEmpty(this.categoryList)) { if (this.DashboardFilters != null) { this.categoryList = this.FilterList("ProductType", false); } } [ 183 ]
Building an End-to-End Solution returnthis.categoryList; } // Format the string filter for the dashboard privatestring FilterList(string filterType, bool includeQuotes) { StringBuilder builder = newStringBuilder(); var categoryFilters = this.DashboardFilters.Where(q => q.FilterType == filterType && q.IsChecked == true); bool hasValues = false; foreach (FilterItem item in categoryFilters) { if (builder.Length > 0) builder.Append(", "); if (includeQuotes) { builder.Append("'"); builder.Append(item.Name); builder.Append("'"); } else { builder.Append(item.Name); } hasValues = true; } string result = "0"; if (includeQuotes) { result = "''"; } if (hasValues) result = builder.ToString(); return result; } } }
The FinancialKPIItem class represents an individual financial-related Key Performance Indicator. The class contains the attributes displayed in the KPI grid including the trend data for the sparkline chart and the value/target values for the bulletgraph. [ 184 ]
Chapter 8
The bulletgraphchart displays a comparison of how well a specific KPI is doing versus its estimate target value and the percentage of the value compared to its target value. using using using using
System; System.Collections.Generic; System.Runtime.Serialization; Chapter8.Business.Service;
namespace Chapter8.Business.Model { [DataContract(Name = "FinancialKPIItem", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassFinancialKPIItem { [DataMember] publicstring Name { get; set; } [DataMember] publicdouble Value { get; set; } [DataMember] publicIList Trend { get; set; } [DataMember] publicdouble Target { get; set; } [DataMember] publicdouble TargetPosition { get; set; } [DataMember] publicdecimal PerformanceValue { get; set; } [DataMember] publicdecimal PerformanceTarget { get; set; } publicdouble PercentOfTarget { get { returnMath.Round((Value*100)/Target); } } } }
[ 185 ]
Building an End-to-End Solution
The Trend property contains a collection of Date KPI Values. Each individual DateKPI instance represents a different point displayed in the Sparkline chart. A Sparkline chart is used for tracking data trends across a period of time. In the Sparkline displayed by the sample, we are showing product sales trends for the last twelve months. using System; using System.Runtime.Serialization; using Chapter8.Business.Service; namespace Chapter8.Business.Model { [DataContract(Name = "DateKPI", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassDateKPI { [DataMember] publicDateTime Date { get; set; } [DataMember] publicdouble Value { get; set; } }
The KPIItem class represents an individual KPI item such as a customer or product. The class contains the attributes displayed by the top product and customer components. When a customer or product KPIItem is displayed, the Name and Sales properties are used from this class. The Sales collection contains the total sales for an item. In order to data bind the value to the chart we have to use a collection even though we have a single total sales value for each item. The SortedValue property is a shortcut used by the data grid to sort the items displayed by their total sales value. using System.Collections.Generic; using System.Runtime.Serialization;n using Chapter8.Business.Service; namespace Chapter8.Business.Model { [DataContract(Name = "KPIItem", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassKPIItem { [DataMember] publicstring Key { get; set; } [DataMember] publicstring Name { get; set; } [ 186 ]
Chapter 8 [DataMember] publicIList Sales { get; set; } publicdecimal SortedValue { get { decimal value = 0; if (this.Sales != null&&this.Sales.Count > 0) { value = this.Sales[0].Value; } return value; } } } }
Data Access Layer The Data Access Layer for the AdventureWorks Dashboard contains a set of repositories classes used for loading the DashboardContext class and its related properties. The repository pattern is a common data access approach used for loading and persisting a domain model. A repository is responsible for interacting with the data store (database) and mapping data to and from the domain model. To make it easier to load the domain model, we will be creating a base repository class. This class will contain the common methods used by each repository. The sub class (repositories) will define the generic return type for the select method and override the GetCommand and MapItem methods. The GetCommand method will define the stored procedure and its parameters used for retrieving the dashboard data. The MapItem method will be used for mapping for the loading of the domain model. The WCF service will create an instance of the DashboardContext class and call each repository passing in the DashboardFilter that was sent from the Silverlight client application. The Connection String for the AdventureWork Database can be found in the project's web.config file.
[ 187 ]
Building an End-to-End Solution using using using using using using
System; System.Collections.Generic; System.Configuration; System.Data; System.Data.SqlClient; Chapter8.Business.Model;
namespace Chapter8.Web.Data { publicabstractclassBaseRepository { protectedIList GetSales(decimal value) { IList items = newList(); items.Add(newNameValueKPI { Key = "Value", Name = "", Value = value }); return items; } protectedabstractIList GetEmptyResult(); protectedabstractIDbCommand GetCommand(SqlConnection connection, DashboardFilter filter); protectedabstract T MapItem(IDataReader reader); publicIList Select(DashboardFilter filter) { if (filter == null) thrownewArgumentNullException(); IList items = this.GetEmptyResult(); string connectionString = ConfigurationManager.ConnectionStrings ["AdventureWorksConnection"].ConnectionString; using (SqlConnection connection = newSqlConnection(connectionString)) { IDbCommand command = this.GetCommand(connection, filter); connection.Open(); IDataReader reader = command.ExecuteReader(); while (reader.Read()) { items.Add(this.MapItem(reader)); } [ 188 ]
Chapter 8 reader.Close(); } return items; } } }
The product and customer repository classes are similar, so we will only walk through the product repository. To view the customer repository, download the sample code for this chapter, and look for the repository in the web project's data folder. The product repository overrides the base repository abstract methods. In the GetCommand method, a SQL command is created to call the spTopInternetProducts stored procedure along with the parameters. The DashboardFilter class is used to pass the parameter values into the stored procedure. The overwritten MapItem method is used to create a new instance of the KPIItem class using the data returned from the database. using using using using
System.Collections.Generic; System.Data; System.Data.SqlClient; Chapter8.Business.Model;
namespace Chapter8.Web.Data { publicclassProductRepository : BaseRepository { protectedoverrideIList GetEmptyResult() { returnnewList(); } protectedoverrideIDbCommand GetCommand(SqlConnection connection, DashboardFilter filter) { SqlCommand command = newSqlCommand("spTopUsInternetProducts", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(newSqlParameter("DateTimeStart", filter.DateRange.StartingRange)); command.Parameters.Add(newSqlParameter("DateTimeEnd", filter.DateRange.EndingRange)); command.Parameters.Add(newSqlParameter("TerritoryList", filter.GeTterritoryList())); command.Parameters.Add(newSqlParameter("CategoryList", filter.GetCategoryList())); return command; [ 189 ]
Building an End-to-End Solution } protectedoverrideKPIItem MapItem(IDataReader reader) { returnnewKPIItem { Name = reader.GetString(reader.GetOrdinal("ProductName")), Sales = this.GetSales(reader.GetDecimal (reader.GetOrdinal("Sales"))) }; } } }
The SalesTerritoryRepository is used for loading the data that will be displayed by the sales territory chart control. The GetCommand method sets up the SQL command for calling the spSalesByRegion stored procedure. The MapItem method creates an instance of the SalesTerritoryKPI class using the data returned from the database. using using using using
System.Collections.Generic; System.Data; System.Data.SqlClient; Chapter8.Business.Model;
namespace Chapter8.Web.Data { publicclassSalesTerritoryRepository : BaseRepository { protectedoverrideIList GetEmptyResult() { returnnewList(); } protectedoverrideIDbCommand GetCommand(SqlConnection connection, DashboardFilter filter) { SqlCommand command = newSqlCommand("spSalesByRegion", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(newSqlParameter("TerritoryList", filter.GeTterritoryList())); command.Parameters.Add(newSqlParameter("CategoryList", filter.GetCategoryList())); return command; } [ 190 ]
Chapter 8 protectedoverrideSalesTerritoryKPI MapItem(IDataReader reader) { returnnewSalesTerritoryKPI { Year = reader.GetDateTime(reader.GetOrdinal("OrderDate")), NortheastSales = reader.GetDecimal(reader. GetOrdinal("NortheastSales")), SoutheastSales = reader.GetDecimal(reader.GetOrdinal("SoutheastSales")), CentralSales = reader.GetDecimal(reader.GetOrdinal("CentralSales")), SouthwestSales = reader.GetDecimal(reader.GetOrdinal("SouthwestSales")), NorthwestSales = reader.GetDecimal(reader.GetOrdinal("NorthwestSales")) }; } } }
The repository for the financial KPI is a little more complex. This is mainly because the AdventureWorks database is missing some key information needed for building the sparkline and bulletgraph controls. The GetCommand method sets up the call to the spFinanceData stored procedure. The MapItem methods create an instance of the FinancialKPIItem class using the data returned from the database. It also generates the target percent and position values that will be displayed by the bullet graph and sparkline controls. using using using using using using
System; System.Collections.Generic; System.Data; System.Data.SqlClient; Chapter8.Business.Common; Chapter8.Business.Model;
namespace Chapter8.Web.Data { publicclassFinancialRepository : BaseRepository { protectedoverrideIList GetEmptyResult() { returnnewList(); } protectedoverride System.Data.IDbCommand GetCommand (System.Data.SqlClient.SqlConnection connection, DashboardFilter filter) [ 191 ]
Building an End-to-End Solution { SqlCommand command = newSqlCommand("spFinanceData", connection); command.CommandType = CommandType.StoredProcedure; return command; } protectedoverrideFinancialKPIItem MapItem (System.Data.IDataReader reader) { string name = reader.GetString(reader.GetOrdinal("Name")); double value = reader.GetDouble(reader.GetOrdinal("Amount")); TargetCache target = this.SetTarget(name, value); returnnewFinancialKPIItem { Name = name, Value = value, Target = target.TargetPercent, TargetPosition = target.TargetPosition, Trend = this.TrendValues(reader) }; } protectedIList TrendValues(IDataReader reader) { IList items = newList(); items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader, items.Add(this.GetDateKPI(reader,
"1/1/2004", "JanSales")); "2/1/2004", "FebSales")); "3/1/2004", "MarSales")); "4/1/2004", "AprSales")); "5/1/2004", "MaySales")); "6/1/2004", "JuneSales")); "7/1/2004", "JulySales")); "8/1/2004", "AugSales")); "9/1/2004", "SeptSales")); "10/1/2004", "OctSales")); "11/1/2004", "NovSales")); "12/1/2004", "DecSales"));
return items; } privateDateKPI GetDateKPI(IDataReader reader, string date, string field) {
[ 192 ]
Chapter 8 returnnewDateKPI { Date = DataExtention.ParseInvariant(date), Value = reader.GetDouble(reader.GetOrdinal(field)) }; } privatestaticIDictionary cachedTargetValues = newDictionary(); privateRandom rnd = newRandom(); /// /// Dynamiclly setup target percent and location. ///This is used to make the bulletgraph look more realistic. /// /// privateTargetCache SetTarget(string name, double value) { if (!FinancialRepository.cachedTargetValues.ContainsKey(name)) { int direction = rnd.Next(0, 3); double percent = value*(rnd.Next(5, 25)*0.01); double taretValue = 0; if (direction == 0) taretValue = value - percent; else taretValue = value + percent; int TargetPosition = rnd.Next(90, 130); FinancialRepository.cachedTargetValues.Add(name, newTargetCache { TargetPercent = taretValue, TargetPosition = TargetPosition }); } returnFinancialRepository.cachedTargetValues[name]; } } }
[ 193 ]
Building an End-to-End Solution
Building the WCF service
Instead of building out separate WCF services for each dashboard component, we will be building a composite service that takes the filtering attributes as input and returns a complex object graph that includes all the data for the dashboard. The service will use the request/response pattern where the request parameter for the service will contain a reference to the DashboardFilter class. The result data contract contains the aggregate root DashboardContext class that is loaded using the data returned from the data repositories. When the user changes one of the facets (filters) in the dashboard, this service is called, and a new object graph is returned, based on the selected filters. To create a Silverlight-enabled WCF service, add a new item to the dashboard application website. When the Add NewItem Chapter8.Web dialog appears, select the Siverlight-enabled WCF service item template under the Silverlight section and name the service DashboardService.
Once the dialog has finished creating the service, there are a couple of things we need to change. Create an interface named IDashboardService, and update the WCF service binding information in web.config to use the newly defined service. [ 194 ]
Chapter 8
It is a best practice always to use an interface to define the service contract for a WCF service. The IDashboardService will contain a single operation named GetDashboardData. using System.ServiceModel; using Chapter8.Business.Service; namespace Chapter8.Web.Services { [ServiceContract(Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicinterfaceIDashboardService { [OperationContract] DashboardResultGetDashboardData(DashboardRequest request); } }
The DashboardService class will implement the IDashboardService interface. The GetDashboardData method checks to see whether the mock or real data source should be used to load the dashboard. If the real data source is used, the class creates an instance of the DashbaordContext class, and then loads the properties in the context class by calling the application data repositories. After the context class is loaded, the service creates an instance of the DashboardResult class, setting the root property to the instance of the DataContext class that was created and loaded. namespace Chapter8.Web.Services { [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] publicclassDashboardService : IDashboardService { publicDashboardResult GetDashboardData(DashboardRequest request) { DashboardContext result = this.GetDashboadData(request.Filter); returnnewDashboardResult {Root = result}; } privateDashboardContext GetDashboadData(DashboardFilter filter) { bool useMock = bool.Parse(ConfigurationManager. AppSettings["UseMockData"].ToString()); DashboardContext result = newDashboardContext(); if (!useMock) { IList products = newProductRepository().Select(filter); [ 195 ]
Building an End-to-End Solution if (products != null&& products.Count > 0) { result.ProductKPI = products.Take(8).ToList(); } IList customers = newCustomerRepository().Select(filter); { result.CustomerKPI = customers.Take(8).ToList(); } result.FinancialKPI = newFinancialRepository().Select(filter); result.SalesTerritoryKPI = newSalesTerritoryRepository().Select(filter); } else { MockRepository rep = newMockRepository(); result = rep.LoadData(); } return result; } } }
The DashbaordRequest class is used as the parameter for the dashboard WCF service. The class contains a single property that contains a reference to the DashboardFilter passed from the Silverlight client. using System.Runtime.Serialization; using Chapter8.Business.Model; namespace Chapter8.Business.Service { [DataContract(Name = "DashboardRequest", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassDashboardRequest { [DataMember] publicDashboardFilter Filter { get; set; } } }
The DashboardResult class is used as the return variable from the WCF service. The class contains a single property that references the loaded DashboardContext class. [ 196 ]
Chapter 8 using System.Runtime.Serialization; using Chapter8.Business.Model; namespace Chapter8.Business.Service { [DataContract(Name = "DashboardResult", Namespace = DashboardRequest.DASHBOARD_NAMESPACE)] publicclassDashboardResult { [DataMember] publicDashboardContext Root { get; set; } } }
After you have finished creating the dashboard WCF service, make sure that the service binding information in web.config is updated to use the IDashbaordService interface:
Defining the presentation layer
The AdventureWorks Dashboard application will contain a single executive-style dashboard view. To take advantage of the Silverlight platform fully, we will be using the Model View View-Model (MVVM) pattern. The MVVM pattern promotes the loose coupling of each component, and takes full advantage of the rich data binding capabilities of the Silverlight platform.
View and controls The UI of the dashboard will consist of a single view that contains each of the major sections (components) of the dashboard. Each component is created as a separate user control to simplify the XAML of the application. [ 197 ]
Building an End-to-End Solution
The loaded method in the view's code behind is used to create an instance of the DasboardViewModel and set the view's data context to the view model. By doing this, the view can data bind to the properties exposed by the view model: private DashboardViewModel viewModel; void Dashboard_Loaded(object sender, RoutedEventArgs e) { this.viewModel = newDashboardViewModel(); this.DataContext = this.viewModel; }
The header user control contains the facets (filters) used for filtering the dashboard. If you look through the control XAML, you will notice that each filter is set up to use two-way data binding. This is done so the view model is automatically updated when a user changes one of the filter values. [ 198 ]
Chapter 8 [ 200 ]
Chapter 8
The FinancialIndicatorControl contains a data grid that displays the KPI account data from the AdventureWorks database. The grid has a template column for the Sparkline chart and Bullet Graph controls. [ 201 ]
Building an End-to-End Solution
The Sparkline control is displayed in the financial KPI data grid. The control is used for displaying the trend of sales data across multiple months. To create the spark line, a custom data template is defined for the Silverlight chart control.
[ 202 ]
Chapter 8
The BulletGraph is a custom XAML control that displays a comparison between target and actual values using multiple ranges. The code for the control exposes a single data property to which the financial KPI gets bound. The template style for the control is located in generic XAML, and defines a set of rectangles that are moved around to display the target and value for the KPI. using System.Windows; using System.Windows.Controls; namespace Chapter8.Controls { publicclassBulletGraph : Control { public BulletGraph() { this.DefaultStyleKey = typeof(BulletGraph); this.Loaded += newRoutedEventHandler(BulletGraph_Loaded); } void BulletGraph_Loaded(object sender, RoutedEventArgs e) { } } }
[ 203 ]
Building an End-to-End Solution
The TopProductsControl and TopCustomerControl contain data grids that display the top "n" sales data for products and customers. When the users set one of the facets, the data displayed by the control is filtered accordingly. [ 204 ]
Chapter 8
View Model A View Model is responsible for exposing the properties and commands to which a view binds. The dashboard uses two view models: DashboardViewModel and FilterViewModel. The DashboardViewModel is the main view model. It contains collection properties for each of the dashboard components, and implements the IDashboardViewModel interface so the FilerViewModel can notify it when a user changes the one of the filter values. When the application is loaded, or when the user changes one of the filter values, the DashboardViewModel calls the service layer that is responsible for calling the WCF service we defined earlier in the chapter. When the WCF service is complete, the view model is called, and it notifies the view of the data for when the dashboard has been updated. [ 205 ]
Building an End-to-End Solution namespace Chapter8.ViewModel { publicinterfaceIDashboardViewModel { void FilterDashboard(); } } using System.Collections.Generic; using Chapter8.Business.Model; using Chapter8.Service; namespace Chapter8.ViewModel { publicclassDashboardViewModel : BaseViewModel, IDashboardViewModel { privateIDashboardService dataService; privateDashboardContext dashboard; public DashboardViewModel() : this(newDashboardService()) { } public DashboardViewModel(IDashboardService service) { this.dataService = service; this.dashboard = newDashboardContext(); this.LoadDashboard(); } protectedvoid LoadDashboard() { this.FilterViewModel = newFilterViewModel(this, this.dashboard.Filter); this.FilterViewModel.FilterDashboard(); } publicIEnumerable KPIData { get { returnthis.dashboard.FinancialKPI; } } publicIEnumerable ProductSales { get { returnthis.dashboard.ProductKPI; } }
[ 206 ]
Chapter 8 publicIEnumerable CustomerSales { get { returnthis.dashboard.CustomerKPI; } } publicIEnumerable TerritorySales { get { returnthis.dashboard.SalesTerritoryKPI; } } privateFilterViewModel filterViewModel; publicFilterViewModel FilterViewModel { get { returnthis.filterViewModel; } set { if (this.filterViewModel != value) { this.filterViewModel = value; this.SendChangedNotification("FilterViewModel"); } } } publicvoid FilterDashboard() { this.dataService.GetDashboard(this.DisplayDashboard, this.dashboard.Filter); } privatevoid DisplayDashboard(DashboardContext dashboard) { if (this.dashboard == null) { this.dashboard = dashboard; } else { this.dashboard.SalesTerritoryKPI = dashboard.SalesTerritoryKPI; this.dashboard.ProductKPI = dashboard.ProductKPI; this.dashboard.CustomerKPI = dashboard.CustomerKPI; this.dashboard.FinancialKPI = dashboard.FinancialKPI; } this.NotifyView(); } privatevoid NotifyView() { [ 207 ]
Building an End-to-End Solution this.SendChangedNotification("KPIData"); this.SendChangedNotification("TerritorySales"); this.SendChangedNotification("ProductSales"); this.SendChangedNotification("CustomerSales"); } } }
The FilterViewModel encapsulates the different attributes used for filtering the dashboard. When a filter is enabled or disabled, the view model updates the DashboardFilter and notifies the main DashboardViewModel that the view needs to be filtered. Note: To make the following code easier to follow, the properties for the view model have been omitted from the sample code. See the chapter download for the complete FilterViewModel class. using System; using System.Collections.Generic; using Chapter8.Business.Model; namespace Chapter8.ViewModel { publicclassFilterViewModel : BaseViewModel { privateIDashboardViewModel parent; privateDashboardFilter filter; public FilterViewModel(IDashboardViewModel parent, DashboardFilter filter) { this.parent = parent; this.filter = filter; this.startingDate = newDateTime(2001, 1, 1); this.endingDate = newDateTime(2004, 6, 30); } publicvoid FilterDashboard() { this.filter.DateRange = newDateFilter { StartingRange = this.StartingDate, EndingRange = this.EndingDate }; this.filter.DashboardFilters = this.GetFilterItems(); this.parent.FilterDashboard(); } [ 208 ]
Chapter 8 privateIList GetFilterItems() { IList items = newList(); items.Add(newFilterItem Name = "1", IsChecked items.Add(newFilterItem Name = "2", IsChecked items.Add(newFilterItem Name = "3", IsChecked items.Add(newFilterItem Name = "4", IsChecked
{ = { = { = { =
FilterType = "ProductType", this.bikesFilterOn }); FilterType = "ProductType", this.ComponentsFilterOn }); FilterType = "ProductType", this.ClothingFilterOn }); FilterType = "ProductType", this.AccessoriesFilterOn });
items.Add(newFilterItem { FilterType = "Region", Name = "Northeast", IsChecked = this.NortheastFilterOn items.Add(newFilterItem { FilterType = "Region", Name = "Southeast", IsChecked = this.SoutheastFilterOn items.Add(newFilterItem { FilterType = "Region", Name = "Central", IsChecked = this.CentralFilterOn }); items.Add(newFilterItem { FilterType = "Region", Name = "Southwest", IsChecked = this.SouthwestFilterOn items.Add(newFilterItem { FilterType = "Region", Name = "Northwest", IsChecked = this.NorthwestFilterOn
}); });
}); });
return items; } } }
Service Layer The Service Layer pattern is used to abstract the call to the WCF service from the dashboard view model. This allows the Dashboard and WCF service to be developed and tested independently. In addition, the Service Layer hides the complexity of calling the WCF service asynchronously from the view model. To abstract the View Model and its Service Layer, we will define an interface for the Service Layer. The interface will contain a single method named GetDashboard. The method accepts two parameters, a callback action that the service layer will call when the call to the WCF service is complete and a filter parameter that contains the filter data for filtering the dashboard.
[ 209 ]
Building an End-to-End Solution using System; using Chapter8.Business.Model; namespace Chapter8.Service { publicinterfaceIDashboardService { void GetDashboard(Action callback, DashboardFilter filter); } }
Before we create the Service Layer, we need to add a service reference to the WCF service. To add a service reference to the WCF service, right-click on the Silverlight project, and select Add Service Reference. When the dialog is displayed; click on the Discover button, and select the IDashboardService service contract. Before clicking OK, click on Advanced, and make sure the Reuse types in reference assemblies is checked. This will ensure that the shared DataContracts in the Chapter8.Business assembly are used instead of the dialog generating new client side proxy classes.
[ 210 ]
Chapter 8
To use the newly created service reference, create a new class named DashboardService, and implement the IDashboardService interface. In the GetDashboard method, call the generated DashboardServiceClient passing the filter from the view model. When the call to the WCF service is complete, the serviceClient_GetDashboardDataCompleted method is called. Inside of that method, we will call back to the view model, passing the DashboardContext returned from the WCF service. using using using using
System; Chapter8.Business.Model; Chapter8.Dashboard; Chapter8.Business.Service;
namespace Chapter8.Service { publicclassDashboardService : IDashboardService { privateAction callback; publicvoid GetDashboard(Action callback, DashboardFilter filter) { this.callback = callback; DashboardServiceClient serviceClient = newDashboardServiceClient(); serviceClient.GetDashboardDataCompleted += newEventHandler( serviceClient_GetDashboardDataCompleted); serviceClient.GetDashboardDataAsync(newDashboardRequest { Filter = filter}); } void serviceClient_GetDashboardDataCompleted(object sender, GetDashboardDataCompletedEventArgs e) { if (this.callback != null) callback(e.Result.Root); } } }
[ 211 ]
Building an End-to-End Solution
Summary This chapter provided an overview of how to build an end-to-end Silverlight Dashboard application. We outlined how to design an N-Tier application that uses the MVVM, service layer and repository patterns. We also looked at how to build a Windows Communication Foundation service that loads data from the AdventureWorks sample database. In the next chapter, we will explore the different data access approaches and technologies you can use when building a Silverlight dashboard application.
[ 212 ]
Data Access Strategies Silverlight is a Rich Internet Application (RIA) platform that allows you to use a rich multimedia experience to showcase application data. This is one of the main advantages that Silverlight has over other platforms for making your dashboard come alive. No matter how flashy you make the application, the most important part that your users care about is information (data). Whether it's the CIO of a fortune 500 company looking to track sales, or a fantasy football owner tracking his team's trends, information is power. In this chapter, we will explore the different data access strategies you can use while building a Silverlight application. How to build your own custom data services using SOAP, REST, and OData, a walkthrough of how to consume externally hosted services, and how the cross-domain security policy system works with Silverlight to call external services. In this chapter, we will cover the following topics: •
Data access overview
•
Understanding network security
•
Building services with Windows Communication Foundation
•
Exploring OData data services
Data Access Strategies
Data access overview Silverlight offers a rich set of options for integrating data services into your applications: •
You can use basic HTTP and socket-based networking classes to perform low-level network calls.
•
Take advantage of the Windows Communication Foundation (WCF) and Language Integrated Query (LINQ) application programming interfaces included in the Silverlight runtime to consume simple and complex data services.
•
Integrate externally hosted services using the Silverlight cross-domain security policy system.
Core networking classes The Silverlight networking stack includes classes for communication using raw sockets and over the HTTP protocol. The HTTP classes allow for simple communication to external resources, such as an image or XML file. For more advanced scenarios, you can use the socket classes for communication. •
HTTP classes (HttpWebRequest.HttpWebResponse or WebClient) included in the System.Net namespace. These classes allow you to communicate to a server using the HTTP or HTTPS protocol. They are the best options when you need to call an external web service or download files directly.
•
Sockets and Multicast classes included in the System.Net.Sockets namespace. These classes allow you to perform general networking calls using a socket interface, real-time duplex communication with a remote network service, or set up a one-to-many or many-to-many multicast communication.
Working with WebClient The simplest way to get data into your Silverlight application is to use the WebClient class to access a XML data file stored on the server. By default, WebClient can use a relative path to access files in the Silverlight application's XAP file's host directory (ClientBin) or one of its sub directories. For more advanced scenarios, where you may need to set the HTTP headers sent to a server, you would want to use the HttpWebRequest class.
[ 214 ]
Chapter 9
All network operations in Silverlight are performed asynchronously; so you will need to create a callback method for when the operation is complete. Depending on the type of networking call you make, you may need to use the Dispatcher class to marshal data back to the UI thread. For example, WebClient operations are automatically returned to the UI thread, but HttpWebRequest requires you to use a Dispatcher to marshal data. The following code uses the WebClient class to retrieve the Products.xml from the host domain of the running Silverlight application. Because the operation is asynchronous, you will need to set up a callback method that will be called after the file has finished being downloaded. WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler (client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("products.xml", UriKind.Relative));
We will be using XLINQ to load data from the Products.xml file into a collection of products. To make it easier to map the data into the product class, let's set up a couple of extensions methods. Extensions methods were added in .NET 3.5, and allow you to add helper methods to externally defined classes. To create an extension method, define a static class with one or more static methods. The first parameter to each method must be the class being extended. To use your own custom extension method, just add the using statement to the namespace where you defined your extension methods as follows: using System.Xml.Linq; namespace Chapter9.Common { public static class XElementExtension { public static int GetIntValue(this XElement element) { int value = 0; int.TryParse(element.Value, out value); return value; } public static double GetDoubleValue(this XElement element) { double value = 0d; double.TryParse(element.Value, out value); return value; } } } [ 215 ]
Data Access Strategies
The data in the Products.xml file will be loaded into a collection of the Product class. The class contains properties (ID, Name, Unit Price, etc…) that match the columns in the data grid that will be used for displaying the data from the Products.xml file. Throughout the chapter, we will be reusing the Product class, so refer back to this code snippet when creating the other samples. public class Product { public string ProductId {get; set;} public string ProductName {get; set;} public string Supplier {get; set;} public string Category {get; set;} public double UnitPrice {get; set;} public int UnitsInStock {get; set;} }
After the WebClient asynchronous asynchronously completes, the client_DownloadStringCompleted method will be called. If the operation was successful, the contents of the Products.xml file will be stored in the e.Result property. We will now use XLINQ, along with the extension methods and product class we previously defined, to load a collection of products. Once the collection is loaded, we will set the item source of the ProductList data grid as follows: void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { XDocument document = XDocument.Load(new StringReader(e.Result)); var result = from d in document.Root.Descendants("Product") selectnewProduct { ProductId = d.Element("ProductID").Value, ProductName = d.Element("ProductName").Value, Supplier = d.Element("Supplier").Value, Category = d.Element("Category").Value, UnitPrice = d.Element("UnitPrice").GetDoubleValue(), UnitsInStock = d.Element("UnitsInStock").GetIntValue() }; this.ProductList.ItemsSource = result; }
[ 216 ]
Chapter 9
The following XAML defines the DataGrid we will be using to display the collection of products returned from downloading the requested file. Throughout the chapter, we will be using a similarly defined grid to display the data for our sample applications.
[ 217 ]
Data Access Strategies
Using Fiddler While building a Silverlight application, it can be problematic to troubleshoot network communication. Fiddler (http://www.fiddler2.com/fiddler2/) is a HTTP communication tool that you should download to troubleshoot networking issues.
By default, Fiddler cannot trace traffic sent to http://localhost. To work around this, you can use your computer name instead of the local host, or add a period in front of the port number (http://localhost.:38090) of your services URI. To monitor your Silverlight application, fire up Fiddler. It will monitor all the HTTP traffic on your machine. As each HTTP request is sent, you can see the contents of the request and result returned from the server. Always remember to fire up Fiddler if you start encountering errors communicating from your Silverlight application.
[ 218 ]
Chapter 9
Understanding network security Silverlight uses a security policy-based approach for allowing cross-domain access. Depending on how you have configured your Silverlight application and the location of the resource (File or Web Service) you are trying to access, Silverlight will download and verify that your application (Host Domain) can access the resource. If you are running an out-browser Silverlight application with evaluated trust or accessing a resource on the same host domain (and port) as your Silverlight XAP file, the policy file is not required. The following image shows the different rules that Silverlight uses for deterring when to download and verify the cross-domain policy file. For resources on the same domain, the file is not required. Unless you have an out-of-browser application with evaluated trusted enabled, the cross-domain policy file is required for the other scenarios: Different Protocols (HTTP vs HTTPS), Sub-Domains, Ports, or Host Domains.
[ 219 ]
Data Access Strategies
Silverlight supports two different types of security policy files. The Flash policy file (Crossdomain.xml) and the Silverlight policy file (ClientsaccessPolicy.xml). If neither file can be found when your application makes a cross-domain, calling Silverlight will raise a security exception. •
Flash policy file (crossdomain.xml): This is the same cross-domain policy file that Adobe Flash uses. This file can only be used by the HTTP and Web Client classes in the System.Net namespace. The Silverlight runtime requires that all domains have full access to work.
•
Silverlight policy files (ClientAccessPolicy.xml): The policy file supports cross-domain access for the Web Client and HTTP classes; the classes in the System.Net.Socket namespace, and the client libraries used by Windows Communication Foundation (WCF).
The structure of the Silverlight cross-domain policy file allows you to define the host URI and the network path that external domains have access to. If you want to allow full access to your server, set up the policy file using "*" to allow all domains, and set the resource path to the root "/".
You can restrict access by defining specific domains and paths. For example if you want to restrict access to only the http://www.mycompany.com domain and services located in the services folder, set up your ClientAccessPolicy.xml like the policy file as follows: [ 220 ]
Chapter 9
To allow clients to send HTTP headers, you need to include the http-request-header attribute. To set up different access rules, define one or more policy elements with the correct corresponding configuration. To allow externally hosted Silverlight applications to call your services, you need to deploy a ClientAccessPolicy.xml at the root folder (domain) of the service's URI. For example if your services are deployed at the http://www.mycompany.com/services/v1/dataservice.svc, you need to deploy the policy file at the root URI (http://www.mycompany.com).
Building services with Windows Communication Foundation When building your own data services, you want to take advantage of the rich programming model that Windows Communication Foundation (WCF) provides. Depending on the type of application and its requirements, there are different service frameworks you can use as follows: •
WCF Core Services offers the most flexible programming model. It allows you to define a web service class that can be consumed by your Silverlight application. You can use Visual Studio to generate proxy classes for the service, and use the WCF client library to asynchronously interact with the service. These types of services offer the most flexibility by allowing you to configure end points using different data formats and protocols.
•
WCF Data Services allows you to expose your data source using a Representational State Transfer (REST) style. Data is exposed as an Open Data Protocol (OData) feed. You can use the HTTP networking classes or the WCF Data Service Client Library to make REST-based queries or actions (Create, Update, or Delete) method calls.
•
WCF RIA Services offers a simplified programming model for building n-tier applications. It allows you to define and share data model classes between a Silverlight client and a web service. In addition, RIA services offers built-in methods for validation, concurrency, and security. RIA services are ideally suited for simple forms over data type applications.
[ 221 ]
Data Access Strategies
Windows Communication Foundation (WCF) is a rich and extensible Application Programming Interface (API) for building and consuming services. As mentioned above, there are several different programming models you can use when working with WCF. When designing a WCF service, you will create service and data contracts. Service contracts define the operations (methods) of your service and data contracts define the message structure you are passing and returning from the services. Service behaviors are used for defining cross-cutting operations that run before or after each request. The channel used by WCF for communicating is based on the protocol and formats you defined for your services.
Now that we understand the different data access options and security restrictions for building a Silverlight consumable data service, let's put this knowledge to work. When building a WCF service, one of the most important technical design decisions you need to make is what protocol and data formats you want your service to support. Depending on your application needs, it might make sense to build a SOAP-based service that uses a binary format, or a REST-based service that returns data using the JSON format. There is a lot of debate in the industry over which is better with regards to SOAP and REST. For now, we will skip the debate; both protocols have advantages and disadvantages, and ultimately it's up to you to decide which options work best for the type of application you need to build. If you're consuming an externally hosted or cloud-based service, more than likely it will be REST or OData-based service.
[ 222 ]
Chapter 9
Working with WCF Before we dig into the details of how to build a SOAP or REST-based WCF service, let's walk through the common data access classes our services will share. After we walk through building the service layer, we will dig into how to consume each type of service in our Silverlight application.
Instead of adding our WCF services directly to the ASP.NET application that hosts our Silverlight application, we can instead create a separate host application. Using Visual Studio, add a new WCF Service application. After Visual Studio has finished generating the WCF project, add a ClientAccessPolicy.xml file, and set it up to allow access to all domains. As we previously discussed, this file is required because our services will be hosted on a different URI than the Silverlight application XAP file. If you haven't done so already, download and run the sample project for this chapter. The project includes the web client sample we previously talked about, along with the samples and WCF services we are about to build.
[ 223 ]
Data Access Strategies
The data access layer To keep things simple, our WCF services will be returning a collection of products stored in an XML data file (Products.xml). We will be using XLINQ to load the data stored in the XML file into a collection of products inside of the WCF service we will be creating. Following is the structure of the Products.xml file. Each product contains an ID, Name, Category, and so on. 401043204-423 Tunnbröd PB Knäckebröd AB Grains/Cereals 12 - 250 g pkgs. 9.00 61 10 534041202-345 Guaraná Fantástica Refrescos Americanas LTDA Beverages 12 - 355 ml cans 4.50 20 15 …
The product class looks very similar to the one we used previously. The only change is that the class and its member properties are decorated with the DataContract and DataMember attributes. These attributes are used by WCF to serialize the product class. If you omit the DataMemberattribute, the property will not be serialized. using System.Runtime.Serialization; namespace Chapter9.Model { [DataContract] public class Product { [DataMember]
[ 224 ]
Chapter 9 public string ProductId {get; set;} [DataMember] public string ProductName { get; set; } [DataMember] public string Supplier { get; set; } [DataMember] public string Category { get; set; } [DataMember] public double UnitPrice { get; set; } [DataMember] public int UnitsInStock { get; set; } }
To load the data from the Products.xml file, we will be using the repository pattern. The ProductRepository class contains two methods. The GetProduct method will return a single product based on its ID, and the GetProducts method will return a collection of all the products defined in the Products.xml file. We will use XLINQ to load the data from Products.xml into a collection of products. Note: The code uses the extension methods we previously defined. The GetProducts method calls the GetProducts method, and then uses LINQ to filter the returned collection, based on the product ID passed into the method. using using using using using using
System.Collections.Generic; System.Linq; System.Web.Hosting; System.Xml.Linq; Chapter9.Common; Chapter9.Model;
namespace Chapter9.Service.Model { public IList GetProducts() { return this.LoadProducts(); } private IList LoadProducts() { string dataFilePath = HostingEnvironment.MapPath("~/App_Data/products.xml"); XDocument document = XDocument.Load(dataFilePath);
[ 225 ]
Data Access Strategies var result = from d in document.Root.Descendants("Product") select new Product { ProductId = d.Element("ProductID").Value, ProductName = d.Element("ProductName").Value, Supplier = d.Element("Supplier").Value, Category = d.Element("Category").Value, UnitPrice = d.Element("UnitPrice").GetDoubleValue(), UnitsInStock = d.Element("UnitsInStock").GetIntValue() }; return result.ToList(); } public Product GetProduct(string productId) { IList products = this.LoadProducts(); var result = products.Where( q => q.ProductId == productId).SingleOrDefault(); return result; } }
To load the Products.xml file, we use the class HostingEnvironment to map the path to the XML file. Any type of .NET applications (WPF, ASP.Net, Windows Services, and so on) can be used to host a WCF service. So it's important that you develop the service in a host-independent way. string dataFilePath = HostingEnvironment.MapPath("~/App_Data/products.xml"); XDocument document = XDocument.Load(dataFilePath);
Now that we have defined the data access code for or service, we will switch gears and take a look at how to build SOAP and REST-based services using WCF. Both of the services we are about to define will use the product repository we just created.
[ 226 ]
Chapter 9
Building a SOAP service
Silverlight only supports a subset of the Windows Communication Foundation (WCF) features that are normally available with .NET. To create a Silverlight-enabled WCF service using Visual Studio, add a new item and select the correct template under the Silverlight node. Name the new service ProductSoapService. After the service is created, there are a few things that you should modify. 1. Create an interface for your service, and name it IProductSoapService, and add a service contract attribute to the class: [ServiceContract(Namespace = «http://mydomain»)] public interface IProductSoapService
2. Add the following using statements to the interface: using System.Collections.Generic; using System.ServiceModel; using Chapter9.Model;
3. Now, define the contents of the interface to include a GetProduct and GetProducts method. Add an operation contract attribute to each method. [OperationContract] Product GetProduct(string productId); [OperationContract] IList GetProducts();
4. Update the ProductSoapService class so that it implements the interface you just created: public class ProductSoapService : IProductSoapService
5. Make sure the soap service class has the AspNetCompatibility and that the RequrementsMode is set to Allowed: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
6. Add the following using statements to the top of the class: using using using using
System.Collections.Generic; System.ServiceModel.Activation; Chapter9.Model; Chapter9.Service.Model;
7. Update the GetProducts and GetProduct methods to call the product repository: public Product GetProduct(string productId) [ 227 ]
Data Access Strategies { public IList GetProducts() { ProductRepository repository = new ProductRepository(); return repository.GetProducts(); }
Before we try calling the service from Silverlight, make sure the web.config for the WCF service project has the necessary end-point configuration settings defined. You should make sure the end point is using the service interface IProductSoapService. [ 228 ]
Chapter 9
8. In order to use the WCF SOAP service we have just created, you need to add a service reference to the service. To do this: °°
Right-click on your Silverlight project and select Add service reference.
°°
Click the discover button to find the WCF services available in same solution as the Silverlight application.
°°
The service wizard will create a set of proxy classes that can be used to call the service. Instead of using the service wizard, you can alternatively use the WCF client library directly, and manually create the proxy classes used to load the products returned from the service.
After the wizard has finished generating the proxy classes, you can use them to call the WCF service. You can do this by creating an instance of the ProductSoapServiceClient class, and subscribing to the completed and async methods. Each operation method defined in your WCF service contract will have a completed and async method generated. To call the service method, invoke its async method. When the call to service is done, the completed method will be called. In the completed method, you can check to see whether the call was a success. If it was successful, set the item source of the DataGrid to the returned product collection. using using using using using
System; System.Windows; System.Windows.Controls; System.Windows.Navigation; Chapter9.ProductSoapService;
namespace Chapter9.Views { public partial class CallSoapService : Page { public CallSoapService() { InitializeComponent(); this.Loaded += new RoutedEventHandler(CallSoapService_Loaded); } void CallSoapService_Loaded(object sender, RoutedEventArgs e) { ProductSoapServiceClientserviceCient = new ProductSoapServiceClient(); serviceCient.GetProductsCompleted += new EventHandler (serviceCient_GetProductsCompleted);
[ 229 ]
Data Access Strategies serviceCient.GetProductsAsync(); } void serviceCient_GetProductsCompleted(object sender, GetProductsCompletedEventArgs e) { if (e.Error == null) { this.ProductList.ItemsSource = e.Result; } } } }
Building a REST service
Starting with the release of the .NET Framework 3.5 (.NET 4.0 adds additional support), it is possible to easily build a REST-based service using WCF. Representational State Transfer (REST) is an architectural style, based on the concept of accessing resources using the HTTP protocol. Each resource is uniquely identified using a URI (http://.../products), and can be accessed using one of the HTTP verbs (GET, POST, PUT, or DELETE). To learn more about REST and JSON see the following links: REST: http://msdn.microsoft.com/en-us/netframework/dd547388 JSON: http://msdn.microsoft.com/en-us/library/ bb299886.aspx
Let's walk through building a WCF REST (HTTP)-based data service and consuming it in our Silverlight application. We will use the same WCF service application we have previously created. 1. Add a new item to the service project by selecting the WCF service template. Name the new service ProductRestService. 2. Add an interface to the project named IProductService, add the Service Contract attribute above the interface. [ServiceContract] public interface IProductRestService
[ 230 ]
Chapter 9
3. Add the following using statements: using using using using
System.Collections.Generic; System.ServiceModel; System.ServiceModel.Web; Chapter9.Model;
4. Add the GetProduct and GetProducts methods to the interface. Add the operation contract and web get attributes to each method. Make sure you see the Name parameter for the operation contract. Additionally, define the UriTemplate and response format for each method. [OperationContract(Name = "GetProducts")] [WebGet(UriTemplate = «/», ResponseFormat = WebMessageFormat.Json)] IList GetProducts(); [OperationContract(Name = «GetProduct»)] [WebGet(UriTemplate = «/product/{productId}», ResponseFormat = WebMessageFormat.Json)] Product GetProduct(string productId);
5. Update the Product Rest Service so that it implements the IProductService interface. public class ProductRestService : IProductRestService
6. Add the following using statements to the class: using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Web
7. Update the GetProducts and GetProduct methods to call the product repository: public Product GetProduct(stringproductId) { public IList GetProducts() { ProductRepository repository = new ProductRepository(); return repository.GetProducts(); }
8. The service class for our REST service looks very similar to its corresponding SOAP counterpart. The only major difference is that we do not need to add the AspNetCompatibilityRequirements attribute, because we will be using the WebClient class to call the REST service.
[ 231 ]
Data Access Strategies
9. There are a couple other things we need to define for our REST service to work. Switch to the markup for the SVC file, and add the following: Factory="System.ServiceModel.Activation.WebServiceHostFactory"
10. This defines the factory that WCF will use to process calls to your REST service. Change the response format for both GetProduct and GetProducts to XML. Then load your very favorite web browser, navigate to the following URI to display the default (/) URI for the REST service: http://localhost:38090/Services/Rest/ ProductRestService.svc/.
11. The Port # for the service maybe different, because Visual Studio picks a dynamic port to load the WCF service project. Using the default URI (/) for the service, you should see a list of products returned from the service. If we change the URI to product/534041202-345, we will see a single product displayed.
[ 232 ]
Chapter 9
12. After testing our REST service using a web browser, make sure you change the format to JSON in the service interface. Our Silverlight application will use the JSON format to deserialize the data returned from the service. 13. To call our REST service, we will use the WebClient class by passing in the URI for the service. When the service call is completed, we use the DataContractJsonSerializer class to deserialize the JSON data returned from the class into a collection of products. void CallRestService_Loaded(object sender, System.Windows.RoutedEventArgs e) { Uri serviceUri = new Uri(«http://localhost:38090/Services/Rest/ ProductRestService.svc/»); WebClient client = new WebClient(); client.OpenReadCompleted += new OpenReadCompletedEventHandler (client_OpenReadCompleted); client.OpenReadAsync(serviceUri); } void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { DataContractJsonSerializerserializer = newDataContractJsonSerializer(typeof(IList)); IList data = (IList)serializer.ReadObject (e.Result); this.ProductList.ItemsSource = data; }
Exploring OData data services The Open Data Protocol (OData) is a protocol based on the principles of REST for building queryable data services. It is built on the concepts behind the Atom publishing Protocol (AtomPub) and the Java Script Object Notation (JSON) data format. It provides a standard way for data consumer and producers to interact with each other. The core data type in OData is a feed, which is defined as a collection of entry types. An entry is a structured record that includes a key and a list of properties. Properties can be defined as simple (e.g., string) or complex (e.g., address) types. An entry can have related entries named links and be part of a hierarchy. For example to access a feed of customer entries, we would use the following URI (http://...//OData.svc/Customers). [ 233 ]
Data Access Strategies
A number of OData-supported client libraries are available that make it easier to call OData producers. In Silverlight, you can use the WCF Data Service client library to query an OData source using LINQ. The Language Integrated Query (LINQ) language is a set of extensions introduced with .NET 3.5 that allows you to query a data source easily. LINQ can be used to query any data source that implements the IQueryable interface such as IEnumerable Collections, WCF Data Services, Entity Framework, and so on. To use the WCF Data Service client library, add a service reference using the Visual Studio | Add Service Reference wizard. This wizard will generate the service context and proxy classes you will use in your Silverlight application as in the following image:
For a more in-depth overview of OData AND a list of consumers and producers, see the OData portal at http://www.odata.org.
[ 234 ]
Chapter 9
Building an OData service
We will be using the WCF Data Service framework to host our custom OData service. WCF Data Services is a framework that allows you to publish an ODatabased service easily by defining an Entity Data Model (EDM). You can easily define an EDM by using the Entity Framework designer in Visual Studio or using attributes to define a custom EDM model class. To create a custom entity model class, all we need to do is decorate a class with the following properties: EntityPropertyMapping and DataServiceKey. The EntityPropertyMapping attribute is used to map a property of an entity to the metadata element for the feed. DataServiceKey is used for defining the key used for identifying an entity.using System.Data.Services.Common; namespace Chapter9.Service.Model { [EntityPropertyMapping("ProductName", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, true)] [DataServiceKey("ProductId")] public class ProductRecord { public string ProductId { get; set; } public string ProductName { get; set; } public string Supplier { get; set; } public string Category { get; set; } public double UnitPrice { get; set; } public int UnitsInStock { get; set; } } }
The product record repository class contains the IQueryable data source that will be hosted by WCF Data Service. The class uses XLINQ to load a collection of product records. The products property returns the loaded product collection as an IQueryable data source as follows: using using using using using
System.Collections.Generic; System.Linq; System.Web.Hosting; System.Xml.Linq; Chapter9.Common;
namespace Chapter9.Service.Model { [ 235 ]
Data Access Strategies public class ProductRecordRepository { public ProductRecordRepository() { this.LoadProducts(); } public IQueryable Products { get { return productRecordList.AsQueryable(); } } private List productRecordList; private void LoadProducts() { string dataFilePath = HostingEnvironment.MapPath ("~/App_Data/products.xml"); XDocument document = XDocument.Load(dataFilePath); var result = from d in document.Root.Descendants("Product") select new ProductRecord { ProductId = d.Element("ProductID").Value, ProductName = d.Element("ProductName").Value, Supplier = d.Element("Supplier").Value, Category = d.Element("Category").Value, UnitPrice = d.Element("UnitPrice").GetDoubleValue(), UnitsInStock = d.Element("UnitsInStock").GetIntValue() }; productRecordList = result.ToList(); } } }
[ 236 ]
Chapter 9
To host our custom IQueryable data source using WCF Data Services, we need to create a class that inherits from the DataService base class, where the generic type contains one or more IQueryable properties. The InitializeService method is used for defining the service's behaviors and the security (read/write) access for the entries returned from the service. using System.Data.Services; using System.Data.Services.Common; using Chapter9.Service.Model; namespace Chapter9.Service.Services.OData { public class ProductODataService : DataService { public static void InitializeService (DataServiceConfigurationconfig) { config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); config.SetServiceOperationAccessRule ("*", ServiceOperationRights.All); config.MaxResultsPerCollection = 100; config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } } }
In our Silverlight application, we can consume the OData service we just built by adding a service reference to the hosted WCF Data Service. To call the service, we need to pass the URI for the service to the service data context, and then asynchronously invoke the data service query by calling it's begin execute method. When the async call completes, we can get the results returned from the service call, and then bind it to a grid defined in our view. You will need to make sure that you set the grid's item source on the UI thread by invoking the UI dispatcher as follows: Uri dataSourceUri = new Uri("http://localhost:38090/Services/OData/ ProductODataService.svc/"); ProductDataSource context = new ProductDataSource(dataSourceUri); IEnumerable results; var query = (from p in context.Products where p.UnitPrice > 25 select p); DataServiceQuery dataServiceQuery = query as DataServiceQuery; [ 237 ]
Data Access Strategies dataServiceQuery.BeginExecute((asyncResult) => { results = dataServiceQuery.EndExecute(asyncResult); Dispatcher.BeginInvoke(() => { this.ProductList.ItemsSource = results.ToList(); }); }, null);
We will need to use LINQ to define the query we will be sending to the OData service. When the service gets invoked, the LINQ query is converted into the correct URI for calling the service. var query = (from p in context.Products where p.UnitPrice > 25 select p);
The LIQN query above will be converted into the following URI: …/
ProductODataService.svc/Products()?$filter=UnitPrice%20gt%2025.0.
The query will only return products that have a unit price that is greater than 25.
Consuming an external service Throughout this chapter, we have looked at how to build and consume our own custom services. While in most cases, you will build your own service, there are times that you will need to consume one or more external services hosted by a thirdparty vendor or deploy in the cloud-based platform. To consume an external service, we follow the same process we have been using to call our own custom services. The only extra step is to make sure the external service we are calling has a client policy file deployed that allows access for all domains or allows access to the host domain for our Silverlight applications. In the following sample, we will be calling the NorthWnd OData service hosted by the OData portal (http://www.odata.org). The NorthWnd service is hosted at the following URI: http://services.odata.org/Northwind/Northwind.svc. Add a service reference to the externally hosted ODataService. The service wizard will generate the NorthWindEnities class and the service proxy for the NorthWind service. Using the NorthWindEntities class, set up a LINQ query to get a list of customers who have a title of owner. To call the service invoked, begin the execute method of the data service class. When the call to the external service is complete, the end execute method will be called to return a collection of customers. Using the UI dispatcher, return the execution to the UI thread, and set the item source of the CustomerList data grid. [ 238 ]
Chapter 9
As we did in the previous OData sample, we will need to use the WCF Data Service client and LINQ to query the NorthWndService. void NorthWndOData_Loaded(object sender, RoutedEventArgs e) { Uri dataSourceUri = new Uri("http://services.odata.org/Northwind/ Northwind.svc/"); NorthwindEntities context = new NorthwindEntities(dataSourceUri); IEnumerable results; var query = (from c in context.Customers where c.ContactTitle == "Owner" select c); DataServiceQuery dataServiceQuery = query as DataServiceQuery; dataServiceQuery.BeginExecute((asyncResult) => { results = dataServiceQuery.EndExecute(asyncResult); Dispatcher.BeginInvoke(() => { this.CustomerList.ItemsSource = results.ToList(); }); }, null); }
The LINQ query returns a list of customers from the NorthWnd data service that has a contact title of Owner. When the query is invoked, the following URI is sent to the externally hosted service: http://services.odata.org/Northwind/Northwind. svc/Customers()?$filter=ContactTitle%20eq%20'Owner'.
One of the powerful attributes of the REST and OData protocol is that it is possible to test the service call by just using a web browser. If you want to directly test out your own custom service or external service, you can use your favorite web browser to test out the service's URI configuration.
[ 239 ]
Data Access Strategies
Summary In this chapter, we discussed the different data access strategies we could use for building a Silverlight application. We looked at how to use the basic HTTP classes included in the Silverlight runtime. Additionally, we discussed the advanced techniques for building and consuming SOAP, REST, or OData-based services, and how the Silverlight security policy system works for allowing cross-domain calls to external hosted resources. In the next chapter, we will look into how to build Silverlight dashboards hosted in SharePoint. We will examine how to create a Silverlight web part, and use the SharePoint client library to access SharePoint list data, and display it in Silverlight.
[ 240 ]
Building Dashboards in SharePoint and Silverlight This chapter will introduce you to the features included in SharePoint 2010 for hosting Silverlight dashboard applications. We will explore how to set up a Silverlight web part, and use the SharePoint Silverlight Client Object Model to communicate with data hosted in SharePoint. In order to run the samples for this chapter, you will need to have a SharePoint 2010 development environment set up. If you don't have one available, follow the steps below for setting up SharePoint 2010 on Windows 7. If you are not familiar with SharePoint 2010, spend some time getting up to speed before tackling the samples in this chapter. In this chapter, we will cover the following topics: •
Overview of SharePoint
•
Building a SharePoint Silverlight Dashboard
•
SharePoint Data Access Strategies
Overview of SharePoint Microsoft SharePoint 2010 is a portal platform that includes features for building content, collaboration, document management, and business intelligence applications. Prior to SharePoint 2010, it was possible to host a Silverlight application by manually creating a SharePoint hosted page or web part that included the HTML object tag. SharePoint 2010 introduces a Silverlight web part and Client Object Model, which makes it easier for Silverlight applications to access data hosted in SharePoint.
Building Dashboards in SharePoint and Silverlight
Setting up SharePoint Before we can walk through how to host a Silverlight dashboard application in SharePoint and use the Client Object Model, we need to set up a version of SharePoint 2010 to use. There are two versions of SharePoint 2010: SharePoint 2010 Foundations and SharePoint Server 2010. Since our main focus is going to be on how to use the Client Object model, we will be setting up SharePoint Foundation 2010 on Windows 7. If you need to have all the features enabled for SharePoint, or you are building a production machine, you will need to install it on a Windows 2008 64-bit machine. Even for Windows 7, you will need to have the 64-bit version installed. In order to set up SharePoint to run on Windows 7, you will need to do the following: 1. Download SharePoint 2010 Foundation from the following:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID= 49c79a8a-4612-4e7d-a0b4-3bb429b46595&displaylang=en
2. After the file is complete, follow the given steps to install it on Windows 7: °°
Copy the downloaded file to a directory on your machine e.g., c:\SharePointInstall.
°°
Open a command prompt, and run the following: c:\
SharePointInstall\SharePoint /extract:c:\ SharePointInstall; this will extract the installation files from the
download. If you download the SharePoint Server 2010 edition, run this command line instead: c:\SharePointInstall\Office Server /extract:c:\SharePointInstall. °°
Using a text editor (e.g., Notepad), open the installation configuration file config.xml located under c:\SharePointInstalltion\files\ Setup\config.xml, and add the following line to the configuration section: .
°°
Run and install the prerequisite for SharePoint 2010 Foundation.
°°
At the Command prompt, type the following c:\ SharePointInstall\ PrerequisiteInstallerFiles\ FilterPack\FilterPack.msi to install the Microsoft FilterPack 2.0.
°°
You will need to install the following items also: Microsoft Sync Framework, SQL Server NativeClient, and Windows Identify
PrerequisiteInstallerFiles\FilterPack\FilterPack.msi.
[ 242 ]
Chapter 10
°°
Open a command prompt, and run the following script. Note: all the parameters should be on the same line. You can also manually enable these features by running the Turn Windows Features On and Off under Control Panel\Program and Features.
The following script will enable the necessary Windows and IIS features required for running SharePoint 2010. It's important that this script is run successfully. If you run into issues, SharePoint may not install or run correctly. If you download the source code for this chapter, you will find a SharePointSetup.txt file that contains the script below you need to run to set up IIS to properly run SharePoint. start /w pkgmgr /iu:IIS-WebServerRole;IIS-WebServer; IIS-CommonHttpFeatures; IIS-StaticContent;IIS-DefaultDocument;IIS-DirectoryBrowsing; IIS-HttpErrors; IIS-ApplicationDevelopment;IIS-ASPNET;IIS-NetFxExtensibility; IIS-ISAPIExtensions;IIS-ISAPIFilter;IIS-HealthAndDiagnostics; IIS-HttpLogging;IIS-LoggingLibraries;IIS-RequestMonitor; IIS-HttpTracing;IIS-CustomLogging;IIS-ManagementScriptingTools; IIS-Security;IIS-BasicAuthentication; IIS-WindowsAuthentication;IIS-DigestAuthentication; IIS-RequestFiltering;IIS-Performance; IIS-HttpCompressionStatic;IIS-HttpCompressionDynamic; IIS-WebServerManagementTools;IIS-ManagementConsole; IIS-IIS6ManagementCompatibility; IIS-Metabase;IIS-WMICompatibility; WAS-WindowsActivationService;WAS-ProcessModel; WAS-NetFxEnvironment;WAS-ConfigurationAPI;WCF-HTTP-Activation; WCF-NonHTTP-Activation
3. Run the SharePoint installation (C:\SharePointInstall\setup.exe), and select the standalone installation. 4. When the installation is finished, make sure you install the SQL Server 2008 KB 970315 x64 hotfix: http://support.microsoft.com/kb/970315. 5. When the hotfix is being installed, run the SharePoint 2010 Configuration Wizard. After the wizard is complete, you should be able to load the default SharePoint site. If you experience any issues when creating the SharePoint 2010 configuration database, you may need to delete the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ Shared Tools\Web Server Extensions\14.0\Secure\FarmAdmin registry key and rerun the SharePoint configuration wizard. Additional details about setting up SharePoint 2010 on Windows 7 can be found here: http://msdn.microsoft.com/ en-us/library/ee554869(office.14).aspx [ 243 ]
Building Dashboards in SharePoint and Silverlight
Building a Silverlight web part
Now that our SharePoint development environment is set up and ready to go, let's build a simple "hello world" style Silverlight web part. Later on in the chapter, we will talk about how to create a Silverlight dashboard and connect it to SharePoint. When building a web part, it is always a good idea to start simple and then add features. This allows us to make sure the Web Part is properly set up to run in SharePoint. To begin building our Silverlight web part, you will need to complete the following steps: 1. Open Visual Studio 2010, and create a new Silverlight Navigation Application. When you are prompted to create a website, uncheck the Host the Silverlight application in a new Web site check box. We do not need a hosting application, because we will be using SharePoint to host the application.
2. Open the view\home.xaml in the Silverlight application, and add a text block that says "Hello SharePoint".
[ 244 ]
Chapter 10
3. To use the Silverlight application you just created in SharePoint, you need to create a SharePoint project using Visual Studio 2010. Make sure you are running Visual Studio under elevated Administrator permissions. This is necessary so we can deploy and debug the application under SharePoint. 4. To load Visual Studio as an administrator, save your work, and close Visual Studio, then right click on the Visual Studio 2010 shortcut and select Run as Administrator. 5. Back in Visual Studio, reload your Silverlight project, and add a new SharePoint 2010 (select Empty SharePoint Project) Project as follows:
[ 245 ]
Building Dashboards in SharePoint and Silverlight
6. When the SharePoint customization wizard is displayed, select Deploy as a sandboxed solution.
7. After the wizard is complete, right-click on the SharePoint project in the solution explorer, and add a new SharePoint module item. 8. Right-click on the newly added module file and select properties. When the property window is displayed, click on the ellipse button (…) in the Project Output Reference property.
[ 246 ]
Chapter 10
9. Click the Add button to add a new entry. Expand the deployment location property. Now change the Deployment Type to ElementFile, and set the Product Name to the name of your Silverlight project. 10. Expand the module element and delete the Sample.txt file. Open the Elements.xml file, and remove the file listing for Sample.txt. 11. Add a new entry for your Silverlight application XAP file. The XAP will be deployed to a document library named Silverlight. Either create the document library before running this solution, or change the deployed path to an existing document library.
12. At this point, our Silverlight application is ready to be deployed. Right-click on the project, and set it as the Startup Project, and then right click and select Properties. When the property dialog appears, click on the SharePoint tab. Make sure the Enabled Silverlight debugging (instead of Script debugging) check box is checked. This will allow you to debug the Silverlight application running under SharePoint. Run the application by pressing F5. 13. Now that your Silverlight application has been deployed to SharePoint, let's add it to the default SharePoint page by adding a Silverlight web part (located under the Media and Content Category), and set the path to the URI for your application XAP file for example, Silverlight/Chapter10.xap.
[ 247 ]
Building Dashboards in SharePoint and Silverlight
14. When you display your Silverlight application for the first time, it will appear squished. To modify the width and height of the web part, click on edit web part, and modify the width to be 400.
Using the Client Object Model To fully take advantage of hosting your Silverlight application in SharePoint, you need to use the SharePoint Client Object Model. The Client Object Model offers a rich API for interacting with SharePoint and content (data) it is hosting. Under the covers, the Client Object Model calls the SharePoint Window Communication Foundation (WCF) services. It is possible to call these WCF services directly, but the Client Object Model offers you a much easier way to interact with SharePoint.
[ 248 ]
Chapter 10
To use the Client Object Model, you need to reference the Silverlight Client Object Model assemblies (Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll). These assemblies can be found in the %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\ClientBin folder on your SharePoint development machine. To use the SharePoint Client Object Model, you will need to get the current SharePoint ClientContext.Current context. Using this context, you can access the website, and list data in SharePoint. The following sample gets the names of all the lists in SharePoint. The code uses the client context to query SharePoint. A LINQ expression is defined that includes the list title and its fields. SharePoint will only return the fields defined in the query. When the query is complete, it will load the listInfo collection we defined; this is the collection we will use later to access the returned data from SharePoint. private IEnumerablelistInfo; void SharePointLists_Loaded(object sender, RoutedEventArgs e) { ClientContext clientContext = ClientContext.Current; ListCollection collList = clientContext.Web.Lists; listInfo = clientContext.LoadQuery( collList.Include( list =>list.Title, list =>list.Fields.Include( field =>field.Title).Where( field =>field.Required == true && field.Hidden != true))); clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed); }
The onQuerySucceded method will be called when the query operation has completed. If an error occurs while the query is executing, the onQueryFailed method will be called. If the query is successful, we need to use the UI dispatcher so that the result is marshalled to the UI thread. In the DisplayInfo method, we loop through the listInfo collection we set up previously and create a collection of spLists that will bind to the data grid. private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgsargs) { this.Dispatcher.BeginInvoke(DisplayInfo); } [ 249 ]
Building Dashboards in SharePoint and Silverlight private void DisplayInfo() { IListlistData = new List(); foreach (List oList in listInfo) { listData.Add(new spList { Title = oList.Title }); } this.ListGrid.ItemsSource = listData; } private void onQueryFailed(object sender, ClientRequestFailedEventArgs args) { this.Dispatcher.BeginInvoke(() => { MessageBox.Show("Request failed. " + args.Message + "\n" + args.StackTrace); }); }
In the next sample, we will use the client object model to retrieve the announcement list from SharePoint. The following screenshot shows the retrieved announcement displayed in a Silverlight web part:
The following code retrieves a SharePoint list using its title. The ClientContext. Current method uses the current user credentials to log into SharePoint and gain access to the host SharePoint website the Silverlight web part is currently running under. ClientContext clientContext = ClientContext.Current; oWebsite = clientContext.Web; this.oList = oWebsite.Lists.GetByTitle("Announcements");
[ 250 ]
Chapter 10
To get the items from a list, we need to set up a CAML Query and define the fields to return from the list to get the field using the following pattern item [{FieldName}]. CAML is an XML query language used by SharePoint to filter data returned from a list. The following CAML query has a row limit set to 100 to restrict the query to only return 100 rows of data: CamlQueryc amlQuery = new CamlQuery(); camlQuery.ViewXml = "100"; this.collListItem = oList.GetItems(camlQuery); clientContext.Load(collListItem, items =>items.Include( item =>item.Id, item =>item.DisplayName, item => item["Title"], item => item["Body"], item => item["Expires"], item =>item.HasUniqueRoleAssignments)); clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
When the query is returned from executing, we load the data returned in a class named spAnnouncement by looping through the collection loaded by the CAML query. We then notify the view that the announcement is ready to be displayed. public class spAnnouncement { public class spAnnouncement { public string Title { get; set; } public string Body { get; set; } public string Expires { get; set; } } spAnnouncement announcement = new spAnnouncement(); foreach (ListItem item in this.collListItem) { announcement.Title = item["Title"].ToString(); announcement.Body = item["Body"].ToString(); announcement.Expires = item["Expires"].ToString(); }
[ 251 ]
Building Dashboards in SharePoint and Silverlight
Building a SharePoint Silverlight dashboard Now that we have a good understanding of what the SharePoint platform offers and its support for hosting Silverlight applications, let's walk through building a Silverlight dashboard application that we will host in a SharePoint 2010 website.
Setting up our data source To keep things simple, we will be using a SharePoint list as our sample's data source. In most real world scenarios, you would want to use the Business Data Catalog or deploy your own custom WCF services to the SharePoint server, and use SQL Server 2008 or another RDBMS to host your dashboard's data. To create the data source for the dashboard, add a new list to SharePoint named products. After the new list is created, rename the title field to Product Id, you will still need to use the title field to access the product ID data. Add a ProductName (string), UnitPrice(Currency), and UnitsInStock (Numeric) to the products list. Add one or more rows of data to the list using the SharePoint UI.
[ 252 ]
Chapter 10
Building our dashboard
We will be building a simple dashboard that displays the data from the SharePoint list as read-only text. The number of units available will be displayed using a bar chart. This will enable the end user to see quickly what products have the highest and lowest number of items in stock.
1. To build our dashboard application, we will be using the MVVM pattern and SharePoint Client Object Model we discussed in the previous section. To get started, let's define a base view model class that has the code for sending property notification, and a helper method for calling the view's dispatcher. using System; usingSystem.ComponentModel; namespace Chapter10.ViewModel { public class BaseViewModel : INotifyPropertyChanged { private IView view; public BaseViewModel(IView view) { this.view = view; } public void CallDispatcher(Action action) { this.view.ViewDispatcher.BeginInvoke(action); } public event PropertyChangedEventHandler PropertyChanged; protected void [ 253 ]
Building Dashboards in SharePoint and Silverlight SendChangedNotification(stringpropertyName) { if (this.PropertyChanged != null) { this.PropertyChanged (this, new PropertyChangedEventArgs(propertyName)); } } } }
2. The next step is to create the product class we will load with the data returned from SharePoint. We must create a child collection for the Units in Stock so we can bind the result to the bar chart. using System.Collections.Generic; namespace Chapter10.Model { public class Product {public class Product { public string ProductId { get; set; } public string ProductName { get; set; } public double UnitPrice { get; set; } public IListUnitsInStock { get; set; } public void AddUnitsInStock(int value) { IList data = new List(); data.Add(new NameValueItem {Name = «UnitsInStock», Value = value}); this.UnitsInStock = data; } } public class NameValueItem {public class NameValueItem { public string Name { get; set; } public int Value { get; set; } } }
[ 254 ]
Chapter 10
3. Set up the view for the Dashboard so it contains a data grid. Add the following text columns to the grid: Product ID, Product Name, and Unit Price. Add a template column that will display the bar chart for the number of units in stock. [ 255 ]
Building Dashboards in SharePoint and Silverlight [ 256 ]
Chapter 10
4. In the code behind for the view, implement the IView interface. This is used for exposing the UI dispatcher to the view model. Make sure you set the data context for the view to an instance of its view model. using using using using using
System.Windows; System.Windows.Controls; System.Windows.Navigation; System.Windows.Threading; Chapter11.ViewModel;
namespace Chapter11.Views { public partial classShareDashboard : Page, IView { {public ShareDashboard() { InitializeComponent(); this.Loaded += new RoutedEventHandler (ShareDashboard_Loaded); } void ShareDashboard_Loaded(object sender, RoutedEventArgs e) { this.DataContext = new DashboardViewModel(this); } public Dispatcher ViewDispatcher { get { return this.Dispatcher; } } // Executes when the user navigates to this page. protected override void OnNavigatedTo(NavigationEventArgs e) { } } }
5. In the view model, create a new method named LoadData. Inside of the method, create the following CAML query. This query will retrieve the listed fields from the Products List stored in SharePoint. ClientContext clientContext = ClientContext.Current; oWebsite = clientContext.Web; this.oList = oWebsite.Lists.GetByTitle(«Products»); CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = «100»; [ 257 ]
Building Dashboards in SharePoint and Silverlight this.collListItem = oList.GetItems(camlQuery); clientContext.Load(collListItem, items =>items.Include( item =>item.Id, item => item[«Title»], item => item[«ProductName»], item => item[«UnitPrice»], item => item[«UnitsInStock»], item =>item.HasUniqueRoleAssignments)); clientContext.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed); }
6. Add a new property to the view model named Products, and set it up so it notifies the view when its value changes. We will set this property when the product list is successfully retrieved from SharePoint. private IList products = null; public IList Products { get { return this.products; } set { if (this.products != value) { this.products = value; this.SendChangedNotification( «Products»); } } }
7. Add the OnQuertSucceeded and OnQueryFailed methods to the view model. The OnQuertSucceeded method will be called when the query execution is completed. OnQueryFailed will be called if an error occurs when the query is executed. 8. Add the DisplayInfo method that will be called when the query execution is completed successfully. This method will loop through the list items returned from SharePoint and create a collection of products that will bind to the dashboard. private voidDisplayInfo() { IList products = new List(); foreach (ListItem item inthis.collListItem) [ 258 ]
Chapter 10 { Product product = new Product { ProductId = item[«Title»].ToString(), ProductName = item[«ProductName»].ToString(), UnitPrice = double.Parse(item[«UnitPrice»].ToString()) }; product.AddUnitsInStock(int.Parse(item[«UnitsInStock»]. ToString())); products.Add(product); } this.Products = products; }
SharePoint Data Access Strategies When working with SharePoint, there are several different approaches you can take for accessing data. While it fairly easy to set up a SharePoint list, it is usually not the best option for a production application; especially if you have a large amount of data or a complex data structure. In such cases, you should use a RDMBS database, such as SQL server, and build custom Windows Communication Foundation (WCF) services that expose your application data to your Silverlight Dashboard. If you are using SharePoint Office Server 2010, you can use the Business Connectivity Services (BCS) to set up number of external data sources, including RDMBS, AS400 Links, or external Web Services. To access the BCS, you need to use the SharePoint Object Model from your custom Windows Communication Foundation service.
Summary In this chapter we gave an overview of how to use SharePoint 2010 to host Silverlight dashboard applications. We walked through how to setup SharePoint 2010 on Windows 7, and introduced you to building Silverlight web parts and use the client object model to retrieve data from SharePoint. Whether you are building a dashboard or other line of business application, the combination of SharePoint and Silverlight in a powerful platform to utilize.
[ 259 ]
Index Symbols .XAP extension 63 .XAP file 21
A AdventureWorks dashboard application about 172 N-Tier layered approach, using 166-168 AdventureWorks Dashboard application presentation layer, defining 197 server components, building 180 AdventureWorks dashboard sample 164 Adventure Works Database about 32, 167 URL 164 AdventureWorksDW2008R2 database 173 aesthetics 109 agile processes 102 AJAX 36, 38 analytical dashboards 88, 89 Application Programming Interface (API) 11, 222 area chart 28 ASP.NET MVC 38 ASP.NET MVC programming model 7 ASP.NET Web Forms 38 ASPX host page 171 Assets panel 129 Async 16 Async CTP about 63 URL 64 asynchronous programming, Silverlight 16 asynchronous technology 63
AtomPub 233 Atom publishing Protocol. See AtomPub Await 16
B bar chart about 28, 29, 90 benefits 90 limitations 91 Basecamp URL 110 Behaviors 39 Bitbucket about 65 URL 65 Blend about 41, 44 basics 128 custom user control, creating in 157-160 sample data, creating 52, 53 Sample Data feature 52-54 Silverlight project, creating 45, 46 splash screen 44 strengths 44 Templates feature 55-58 weaknesses 44 Blend 4 128 Blend UI panels 128-135 Blend UI, panels Assets 129 Data 130 Design View (Artboard) 130 Objects and Timeline 131 Parts 132
Projects 132 Properties 132 Resources 134 Results 134 States 135 brushes converting, into resources 152-154 Brush object 135 bullet graph about 89, 93 benefits 93 limitations 93 BulletGraph 203 bulletgraphchart 185 Business Intelligence (BI) 25 business layer 37, 39 Button Control Template, exploring 137-139 creating 136, 137 Button's Control Template exploring 137-139
ClientAccessPolicy.xml file 223 client_DownloadStringCompleted method 216 client-side application development, Silverlight 21 client-side state, Silverlight 22 COM Automation 17, 23 command binding setting up 71 CommandParameter property 71 Confluence URL 65 Control Template 136 cross-browser development simplification, Silverlight 23 crosstabs 94 CSS 38 Custom Button Control Template creating 140-144 custom User Control creating, in Blend 157-160
C
D
C# 128 Caliburn URL 72 Caliburn.Micro about 11, 63 URL 64 Caliburn.Micro 1.2 11 CASE/WHEN SQL statement 178 chart about 27 data, binding to 81, 82 styling 160, 161 thresholds, including 30 types 27-29 viewing, with multiple series 29 Chart control using 81 chartjunk 89 chart, types area 28 bar 28, 29 line 29 ClickOnce 36
DashbaordRequest class 196 dashboard application building, MVVM pattern used 73 data binding, setting up 78-82 data source, setting up 74 Model classes, defining 75, 77 UI, customizing 83, 84 View-Model classes, defining 75, 77 XAML, laying out 78-82 DashboardContext class 181, 182, 187, 194, 196 dashboard design example scenarios 105, 106 pre-attentive processing, applying to 111, 112 DashboardFilter class 181, 182, 189, 194 DashboardResult class 196 dashboards 1980 Fiat Spider example 33 2007 Chrysler Town & Country example 33 about 25, 26, 88 current state 36 ECG example 35 [ 262 ]
elements 26, 27 environment 36 evolution 34 examples 33 issues, solving 35 need for 32 prerequisites 164 requisites 164, 165 scenario-based design 102-105 scenario-based requisites 102-105 solution, designing 166 styling 157 types 88, 89 user-centered design, applying for 96, 97 scenario-based design 114 dashboards, elements about 27 gauges 27 graphs 27 reports 27 score cards 27 strategy map 27 table 27 dashboards environment desktop solution 36 Silverlight solution 37 web solution 36 DashboardService class 195 dashboards, types analytical 88, 89 operational 88, 89 strategic 88 DashboardViewModel 205 dashboard wireframe 115 data binding, to chart 81, 82 data access overview 214 Data Access Layer 187-191 data access layer, WCF 224-226 database schema reviewing 173, 174 data binding about 39, 70 setting up 78-82
data layer 37, 39 Data panel 130 data source database schema, reviewing 173, 174 setting up 74, 172 stored procedures 174, 175 DataTemplates 40 DataTemplateSelector 40 Data Transfer Object. See DTO debugging environment, Visual Studio 60-62 delegate command 72 dependency injection (DI) 6, 11-14 Design View (Artboard) 130 desktop solution 36 developer 127 digital dashboard, of ECG 35 Dispatcher class 215 DLL Hell 14 DLLs 14 Domain Model about 180 key classes 181-186 Domain Model, classes DashboardContext 181, 182 DashboardFilter 181, 182 FinancialKPIItem 181, 184 KPIItem 181, 186 SalesTerritoryKPI 181 Don't Repeat Yourself. See DRY principle dropshadows effect 157 DRY principle 6 DTO about 7, 38 INotifyPropertyChanged interface, implementing 8, 9
E electrocardiograph (ECG) monitoring 35 Entity Framework 39 Entity Framework 4 24 example scenarios, for dashboard design 105, 106 executive dashboard example 165
[ 263 ]
F features, Silverlight 17, 18 features, Storyboards 52 features, trusted application 17 Fiddler about 218 URL 218 using 218 FilterViewModel 205, 208 FinancialIndicatorControl 201 FinancialKPIItem class 181, 184, 191 Fireworks 41 flash policy file (crossdomain.xml) 220
G gauges 27 GetCommand method 187-191 GetDashboardData method 195 GetDashboard method 209, 211 Git URL 65 github URL 65 GPS systems 33 Graphics Processing Unit (GPU) 20 graphs 27 Grid styling 160, 161
H high fidelity mockups 102 HTTP 214 HTTP classes 214 HTTPS protocol 214 HttpWebRequest class 214 HttpWebResponse class 214
I ICommand interface 72 IDashboardService interface 195, 197, 211 IDashboardViewModel interface 205 InitializeService method 237 INotifyPropertyChanged interface about 9, 71
implementing, DTO used 8, 9 interaction aesthetic about 110 versus visual aesthetics 110 iPhone rough sketch 98 IProductSoapService interface 227 ISAPI Filter 175
J JavaScript 38 Java Script Object Notation. See JSON Jira URL 65 JIRA 64 jQuery 38 JSON about 38, 233 URL 230
K Key Performance Indicator (KPI) about 30, 83, 164 example 30, 31 KPI Dashboard components 165 KPI Dashboard, components financial indicators section 165 header (filters) section 165 top customers 166 top products section 166 yearly sales by region section 165 KPIItem class 181, 186
L Language Integrated Query. See LINQ line chart 29 line graph about 91 benefits 92 limitations 92 Line of Business (LOB) applications 5 LINQ 214 Linq2SQL 7 Linq-to-SQL 39 [ 264 ]
ListBox about 70 properties 57 sample data, displaying in 55, 56
M magic strings 9 Managed Extensible Framework. See MEF MapItem method 187-190 MEF about 12 comparing, with Unity 14 using 13, 14 Mercurial URL 65 Microsoft Expression Blend. See Blend Microsoft Prism URL 72 Model about 7 classes, defining 75, 77 Model View Controller. See MVC pattern Model View View-Model. See MVVM MouseOver state about 146, 147 modifying 50 transistions, adding to 148, 149 multivariate analysis 94 MVC pattern 71 MVVM about 6-9, 39, 163, 166 View First, comparing with ViewModel First 10 MVVM Light about 12 URL 72 MVVM pattern about 70-72 used, for building dashboard application 73
N NAnt URL 64 network security 219 new keyword 13
NHibernate 39 N-Tier application design overview 166-168 sample project structure 168-171 NuGet 24
O object relational mapping (ORM) 39 Objects and Timeline panel 131 OData about 22, 233 data services, building 235-238 external service, consuming 238, 239 URL 234 OData data services exploring 234 OData service building 235-238 OLAP cubes 25, 173 operational dashboards 88, 89
P panels, Blend UI Assets 129 Data 130 Design View (Artboard) 130 Objects and Timeline 131 Parts 132 Projects 132 Properties 132 Resources 134 Results 134 States 135 Parts panel 132 persona 100 pie chart about 95 benefits 95 limitations 96 PInvoke 17 pivot tables 94 pixel snapping 18 Plain Old CLR Objects. See POCO plain old WCF operations 22 POCO 38, 180 postscript vector printing 19 [ 265 ]
Button, creating 136, 137 Custom Button Control Template, creating 140-144 Visual States, adding 144-146 Resources panel 134 REST 230 REST service about 230 building 230-233 Results panel 134 Rich Internet Application (RIA) 213
pre-attentive attributes about 111 attribuites mixing warning 113 visual distractors warning 113 warnings 113 pre-attentive processing about 111 applying, to dashboard design 111, 112 prerequisites, for dashboards 164 presentation layer about 37-39 defining 197 Service Layer pattern 209-211 View and controls 197-204 View Model 205, 208 Pressed state modifying 50 Pressed State 149-151 Prism about 10, 12, 63 URL 64 Prism 4.0 10, 12 Products.xml file 216 project management, Visual Studio 64, 65 Projects panel 132 Properties panel 132 PropertyChanged event 71 prototypes 101
S
R reduced server load feature, Silverlight 21, 22 reporting 25 reports 27 repository 187 Representational State Transfer. See REST requisites, for dashboards 164, 165 resource dictionary about 135 creating 155-157 resources about 135 brushes, converting into 152-154 implementing 136 referencing 136 resources, implementing
Sales collection 186 SalesTerritoryKPI class 181, 190 sample data displaying, in ListBox 55, 56 Sample Data feature 52-54 scatterplot about 92 benefits 92 limitations 92 scenario-based design dashboards, requisites about 114 filter by geographic region 119 filter by product category 120 performance data, for key KPIs 116 sales data, viewing by both geographic region and product category at same time 121 top 10 customers, viewing based on revenue 122-125 under or over performing KPIs 117, 118 scenarios 100, 102 score cards 27 ScrollViewer control 78 security policy files, Silverlight ClientAccessPolicy.xml 220 crossdomain.xml 220 server components building 180 server components, building Data Access Layer 187-191 Domain Model 180 WCF service 194,-197
[ 266 ]
serviceClient_GetDashboardDataCompleted method 211 Service Layer pattern 209-211 services building, with WCF 221, 222 Silverlight about 5, 213 as web technology 14 asynchronous programming 16 client-side application development 21 client-side state 22 core networking classes 214 cross-browser development simplification 23 dashboard application, building 68, 69 dashboards 25, 26 data access overview 214 dependency injection (DI) 11-14 environment set up, requisites 23, 24 features 17, 18 MVVM 6-9 MVVM pattern 70-72 reasons, for using 38 reduced server load feature 21, 22 security policy files 220 styling in 135 tips, for developing 63 URL, for downloading tools 68 XAML, as declarative programming model 6 Silverlight 5 about 5 capabilities 18 enhanced Window feature 20 graphic enhancements 19 improvements 18, 19 3D capabilities 20 Silverlight application building 38-41 business layer 39 data layer 39 presentation layer 39 Silverlight dashboard application about 67 building 68, 69 Silverlight Navigation Application 68
Silverlight policy files (ClientAccessPolicy.xml) 220 Silverlight project creating, in Blend 45, 46 creating, in Visual Studio 47 Silverlight solution 37 Silverlight, styling resources, implementing 136 resources, referencing 136 Silverlight Toolkit Chart control 78 sketches 101 SketchFlow 41 small multiples about 94 benefits 95 limitations 95 SOAP service about 227 building 227, 229 socket-based networking classes 214 SortedValue property 186 Sparkline control 202 sparklines about 32, 89, 94, 186 benefits 94 limitations 94 spFinanceData procedure 178 spFinanceData stored procedure 191 splash screen, Blend 44 splash screen, Visual Studio 47 spreadsheets 25 spSalesByRegion procedure 177 spSalesByRegion stored procedure 190 spTopInternetProducts procedure 189 spTopUsInternetCustomers procedure 176 spTopUsInternetProducts procedure 175 SQL 174 SQL Server 2008 Express URL 164 stacked bar chart about 91 benefits 91 limitations 91 StackPanel control 78 States panel 135 static resource 136 stored procedures
[ 267 ]
about 174, 175 spFinanceData 178 spSalesByRegion 177 spTopUsInternetCustomers 176 spTopUsInternetProducts 175 Storyboards about 51, 101 examples 101 features 52 strategic dashboards about 88 goals 88 strategy map 27 System.Net.Sockets namespace 214
T TabControl 40 table 27 TeamCity about 64 URL 64 Team Foundation Server. See TFS Templates feature 55-58 TextBox 70 Text property 45 TFS 64 Toast Notifications 23 ToList()command 77 TopCustomerControl 204 TopProductsControl 204 TortoiseGit about 64 URL 65 TortoiseHg 64 transistions adding, to MouseOver State 148, 149 Trend property 186 TrickPlay 18 Triggers 39 trusted application features 17 typical dashboard charts about 89 bar chart 90 bullet graph 93 line graph 91, 92
pie chart 95, 96 scatterplot 92 small multiples 94 sparklines 94 stacked bar chart 91 typical dashboard graphs. See typical dashboard charts
U UI customizing 83, 84 Unfuddle about 64 URL 65 UNION SQL statement 177 Unity about 14 comparing, with MEF 14 Use Cases 102 user-centered design about 87, 99 applying, for dashboards 96, 97 requisites 100 user experience (UX) about 96 communicating 97-99 representing 97-99 user research about 99 conducting 99 high-fidelity mockups 102 persona 100 prototypes 101 scenarios 100 sketches 101 storyboards 101 wireframes 101 User Stories 102 using statement 215
V View First about 10 versus ViewModel First 10 View Model about 205, 208 [ 268 ]
classes, defining 75, 77 ViewModel 7, 39 ViewModel class 6 ViewModel First about 10 versus View First 10 ViewModelLocater class 10 Views 6, 39 visual aesthetics about 110 example 110 versus interaction aesthetics 110 VisualStateManager 41 Visual States about 41, 48, 144 adding 144-146 MouseOver 146, 147 Pressed 149-151 Visual Studio about 46, 59 debugging environment 60-62 project management tools 64 Silverlight project, creating in 47 splash screen 47 strengths 46 weaknesses 46 Visual Studio 2010 128 Visual Studio Async CTP (SP1 Refresh) 16
W WCF about 22, 163, 214 core services 220, 221 data access layer 224-226 data services 221 RIA services 221 services, building with 221, 222 working with 223 WCF Core Services 221 WCF Data Services 22, 221
WCF RIA Services 22, 221 WCF service about 166 building 194-197 WebClient working with 214-217 WebClient class 214 WebClientDownloadStringAsync method 74 web.config file 187 web host 39 web solution about 36 factors 37, 38 web technology, Silverlight 14 Windows 8 5 Windows Communication Foundation. See WCF Windows Phone 7 5 Windows Presentation Foundation. See WPF wireframes 101 WPF 6, 17
X XAML about 70, 128 as declarative programming model 6 laying out 78-82 XamlReader.Load(...) method 40 XAML snippet, for MouseOver state 51 XAML technology 38 XAP file 74 XCopy 15 XLINQ 77, 215, 224 XMLA 175 xUnit.net about 64 URL 64
[ 269 ]
Thank you for buying
Microsoft Silverlight 5: Building Rich Enterprise Dashboards 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.
About Packt Enterprise In 2010, Packt launched two new brands, Packt Enterprise and Packt Open Source, in order to continue its focus on specialization. This book is part of the Packt Enterprise brand, home to books published on enterprise software – software created by major vendors, including (but not limited to) IBM, Microsoft and Oracle, often for use in other corporations. Its titles will offer information relevant to a range of users of this software, including administrators, developers, architects, and end users.
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 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.
3.
Integrate different media types, taking the RIA experience further with Silverlight, and much more!
Microsoft Silverlight 4 Data and Services Cookbook ISBN: 978-1-847199-84-3
Paperback: 476 pages
Over 80 practical recipes for creating rich, data-driven business applications in Silverlight 1.
Design and develop rich data-driven business applications in Silverlight
2.
Rapidly interact with and handle multiple sources of data and services within Silverlight business applications
3.
Packed with practical, hands-on cookbook recipes, illustrating the techniques to solve particular data problems effectively within your Silverlight business applications
Please check www.PacktPub.com for information on our titles
Silverlight 4 User Interface Cookbook ISBN: 978-1-847198-86-0
Paperback: 280 pages
Build and implement rich, standard-friendly user interfaces with Silverlight and Expression Blend 1.
The first and only book to focus exclusively on Silverlight UI development.
2.
Have your applications stand out from the crowd with leading, innovative, and friendly user interfaces.
4.
Real world projects which you can explore in detail and make modifications as you go.
3D Game Development with Microsoft Silverlight 3: Beginner's Guide ISBN: 978-1-847198-92-1
Paperback: 452 pages
A practical guide to creating real-time responsive online 3D games in Silverlight 3 using C#, XBAP WPF, XAML, Balder, and Farseer Physics Engine 1.
Develop online interactive 3D games and scenes in Microsoft Silverlight 3 and XBAP WPF
2.
Integrate Balder 3D engine 1.0, Farseer Physics Engine 2.1, and advanced objectoriented techniques to simplify the game development process
3.
Enhance development with animated 3D characters, sounds, music, physics, stages, gauges, and backgrounds
Please check www.PacktPub.com for information on our titles