Pro Business Applications with Silverlight 4

Similar documents
Pro Business Applications with Silverlight 4

Beginning Silverlight 3

Pro.NET 4 Parallel Programming in C#

Companion ebook Available Pro Android Includes Android 1.5 SOURCE CODE ONLINE US $44.99

Python 3 for Absolute Beginners

C++ Quick Syntax Reference

Pro SQL Server 2008 Mirroring

Objective-C Quick Syntax Reference

MATLAB Programming for Numerical Analysis. César Pérez López

Web Development, Silverlight, and

Windows 10 Revealed. The Universal Windows Operating System for PC, Tablets, and Windows Phone. Kinnary Jangla

Pro Data Backup and Recovery. Steven Nelson

Excel 2010 Made Simple

Pro SQL Server 2008 Policy-Based Management. Ken Simmons Colin Stasiuk Jorge Segarra

Pro Entity Framework 4.0

Pro JavaScript Performance Monitoring and Visualization

Beginning ASP.NET MVC 4. José Rolando Guay Paz

Pro ASP.NET SharePoint 2010 Solutions Techniques for Building SharePoint Functionality into ASP.NET Applications

Swift Quick Syntax Reference

Foundation Flash Catalyst. Greg Goralski LordAlex Leon

Building Spring 2 Enterprise Applications

Practical Spring LDAP

Silverlight and ASP.NET Revealed. Matthew MacDonald

Microsoft Computer Vision APIs Distilled

Flash Builder and Flash Catalyst The New Workflow. Steven Peeters

Functional Programming in R

Essential Angular for ASP.NET Core MVC

Beginning Web Development, Silverlight, and ASP.NET AJAX

JavaScript Quick Syntax Reference

Pro ASP.NET MVC 5. Adam Freeman

C Quick Syntax Reference

Pro Perl Parsing. Christopher M. Frenz

Web Programming with Dart. Moises Belchin Patricia Juberias

Building Custom Tasks for SQL Server Integration Services

Pro Excel 2007 VBA. Jim DeMarco

MATLAB Numerical Calculations. César Pérez López

Introducing Aviary. Mike Peutz

Learn PHP 7. Object-Oriented Modular Programming using HTML5, CSS3, JavaScript, XML, JSON, and MySQL. Steve Prettyman

Web Standards Creativity: Innovations in Web Design with XHTML, CSS, and DOM Scripting

Expert C# 5.0 with.net 4.5 Framework

Beginning JSF 2 APIs and JBoss Seam. Kent Ka Iok Tong

Visual Studio Condensed. Patrick Desjardins

Pro MERN Stack. Full Stack Web App Development with Mongo, Express, React, and Node. Vasan Subramanian

Accelerated GWT. Building Enterprise Google Web Toolkit Applications. Vipul Gupta

Beginning Windows Phone 7 Development. Henry Lee and Eugene Chuvyrov

Pro ODP.NET for Oracle Database 11g. Edmund Zehoo

Beginning Silverlight 5 in C #

Windows 8 MVVM Patterns Revealed

A Programmer's Guide to

Scalable Big Data Architecture

Pro Python. Marty Alchin

Foundations of JSP Design Patterns

Agile Swift. Swift Programming Using Agile Tools and Techniques. Godfrey Nolan

Carlo Scarioni. Pro Spring Security

Silverlight Recipes. A Problem-Solution Approach. Apress* Jit Ghosh and Rob Cameron

Introducing. Silverlight 4. Gear up fast to develop line of business rich internet applications using Silverlight 4. Ashish Ghoda

Date on Database. Writings C. J. Date

ASP.NET Core Recipes

The Definitive Guide to HTML Video. Silvia Pfeiffer

"Charting the Course... MOC A Introduction to Web Development with Microsoft Visual Studio Course Summary

Android Continuous Integration

Developing C# Apps for iphone and ipad Using MonoTouch

Pro Angular 6. Third Edition. Adam Freeman

Java Quick Syntax Reference. Second Edition. Mikael Olsson

James Cryer. Pro Grunt.js

Beginning ASP.NET. 4.5 in C# Matthew MacDonald

The Windows 10 Productivity Handbook

Pro SharePoint 2013 Administration Rob Garrett

Beginning Java and Flex Migrating Java, Spring, Hibernate, and Maven Developers to Adobe Flex

Migrating to Swift from Android

iphone Design Award-Winning Projects Chris Dannen

The Definitive Guide to Grails 2

Expert Shell Scripting

Android Continuous Integration

Beginning Objective-C

Learn Excel 2016 for OS X

Raven: Scripting Java Builds with Ruby MATTHIEU RIOU

Pro ASP.NET SignalR. Real-Time Communication in.net with SignalR 2.1. Keyvan Nayyeri Darren White

Pro Python System Administration

Pro XAML with C# From Design to Deployment on WPF, Windows Store, and Windows Phone. Buddy James. Lori Lalonde

Word Business Documents

SQL Server AlwaysOn Revealed

C++ Recipes. A Problem-Solution Approach. Bruce Sutherland

Digital Illustration Fundamentals

Microsoft Visual Studio 2010

"Charting the Course to Your Success!" MOC B Programming in C# Course Summary

JavaScript Essentials for SAP ABAP Developers

RMAN Recipes for Oracle Database 11g

Practical Ruby Gems. David Berube

Android Fragments. Dave MacLean Satya Komatineni

Microsoft Mapping. Geospatial Development in Windows 10 with Bing Maps and C# Second Edition. Carmen Au Ray Rischpater

Realtime Web Apps. With HTML5 WebSocket, PHP, and jquery. Apress. Jason Lengstorf Phil Leggetter

Practical Amazon EC2, SQS, Kinesis, and S3

Pro Android C++ with the NDK

Beginning the Linux Command Line. Sander van Vugt

Beginning Ubuntu Server Administration

Beginning Ubuntu Server Administration

"Charting the Course... SharePoint 2007 Hands-On Labs Course Summary

Installing and Administering a Satellite Environment

Beginning CSS Preprocessors

Transcription:

Pro Business Applications with Silverlight 4 Chris Anderson

Pro Business Applications with Silverlight 4 Copyright 2010 by Chris Anderson All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN-13 (pbk): 978-1-4302-7207-6 ISBN-13 (electronic): 978-1-4302-7206-9 Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1 Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. President and Publisher: Paul Manning Lead Editor: Jon Hassell Technical Reviewer: Editorial Board: Clay Andres, Steve Anglin, Mark Beckner, Ewan Buckingham, Gary Cornell, Jonathan Gennick, Jonathan Hassell, Michelle Lowman, Matthew Moodie, Duncan Parkes, Jeffrey Pepper, Frank Pohlmann, Douglas Pundick, Ben Renow-Clarke, Dominic Shakeshaft, Matt Wade, Tom Welsh Coordinating Editor: Tracy Brown Copy Editors: Julie Hammond, Damon Larson, Heather Lang, Kim Wimpsett. Compositor: Bytheway Publishing Services Indexer: Toma Mulligan Artist: April Milne Cover Designer: Anna Ishchenko Distributed to the book trade worldwide by Springer-Verlag New York, Inc., 233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax 201-348-4505, e-mail orders-ny@springersbm.com, or visit www.springeronline.com. For information on translations, please e-mail rights@apress.com, or visit www.apress.com. Apress and friends of ED books may be purchased in bulk for academic, corporate, or promotional use. ebook versions and licenses are also available for most titles. For more information, reference our Special Bulk Sales ebook Licensing web page at www.apress.com/info/bulksales. The information in this book is distributed on an as is basis, without warranty. Although every precaution has been taken in the preparation of this work, neither the author(s) nor Apress shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in this work. The source code for this book is available to readers at www.apress.com. You will need to answer questions pertaining to this book in order to successfully download the code.

For my grandmother Connie, a great role model for will power, optimism, generousity, patience, and love. I miss her dearly.

Contents at a Glance Contents at a Glance...iv Contents...v About the Author... xix Acknowledgments... xx Chapter 1: Introduction...1 Chapter 2: Getting Started with Silverlight...13 Chapter 3: An Introduction to XAML...35 Chapter 4: The Navigation Framework...73 Chapter 5: Exposing Data from the Server: Using WCF RIA Services...93 Chapter 6: Implementing Summary Lists...141 Chapter 7: Building Data Entry Forms...189 Chapter 8: Securing Your Application...245 Chapter 9: Styling Your Application...269 Chapter 10: Advanced XAML and Data Binding...287 Chapter 11: Creating Custom Controls...331 Chapter 12: The Model-View-ViewModel (MVVM) Design Pattern...373 Chapter 13: Printing and Reporting...403 Chapter 14: Out of Browser Mode, and Interacting with the Operating System...427 Chapter 15: Application Deployment...483 Index...513 iv

C Contents Contents at a Glance...iv Contents...v About the Author... xix Acknowledgments... xx Chapter 1: Introduction...1 Who This Book Is For...1 About This Book...2 About the Author...3 Silverlight Overview...4 What Is Silverlight?... 4 A Short History of Silverlight... 6 What Can Silverlight Bring to Your Business Application?... 7 When Should You Not Use Silverlight?... 8 Comparing Silverlight to Other Microsoft Platforms... 9 Comparison with Adobe Flash/Flex... 11 Business Applications Overview...11 Summary...12 Chapter 2: Getting Started with Silverlight...13 Required Tools...13 Visual Studio... 13 Expression Blend 4 and SketchFlow... 14 v

Silverlight 4 Tools... 15 WCF RIA Services... 15 Silverlight Toolkit... 15 SQL Server 2008 Express Edition... 15 Silverlight Spy (and.net Reflector)... 16 Creating a Silverlight Application...16 Silverlight Application... 17 Silverlight Navigation Application... 18 Silverlight Business Application... 18 Silverlight Class Library... 18 WCF RIA Services Class Library... 19 Silverlight Unit Test Application... 19 Running and Exploring the Default Silverlight Business Application Project...19 Exploring the Initial Silverlight Project Structure...22 Project Links... 24 The Web Application Project Structure... 26 The Silverlight Application Project Structure... 28 Recommended Project Template Modifications...31 XAP Files...32 Summary...33 Chapter 3: An Introduction to XAML...35 Overcoming XAML s Steep Learning Curve...35 Why Learn XAML?...36 XAML Syntax, Document Structure, and Features...37 Core XAML Syntax... 37 Creating an Object Hierarchy... 38 Namespaces... 39 Assigning Property Values to Controls... 41 vi

Attached Properties... 44 XAML Namespace Properties... 45 Design-Time Properties... 46 Markup Extensions... 47 Namescopes... 49 Controls...50 Base Control Classes... 51 Layout Controls... 53 XAML vs. Windows Forms Controls Property Names... 57 Assigning Event Handlers... 58 Creating a Simple User Interface... 60 Resources and Resource Dictionaries...62 Styles...64 Templates...65 Data Binding...65 Binding to an Object... 66 Binding to a Collection... 69 Designing User Experiences...70 The Designer/Developer Workflow...71 XAML User Interfaces: A Different Perspective...71 Summary...72 Chapter 4: The Navigation Framework...73 Getting Started with the Navigation Framework...73 Components of the Navigation Framework...75 The Frame Control... 75 The Page Class... 76 The NavigationService Object... 76 The NavigationContext Object... 77 vii

Navigating Between Views...77 View URIs... 77 Navigation Methods on the Frame Control... 78 Navigation Methods on the NavigationService Object... 78 Using a HyperlinkButton Control... 79 Using the Source Property of the Frame Control... 79 User-Initiated Navigation... 79 Passing Data Between Views...80 Passing Data Using Query String Parameters... 80 Reading Query String Parameters... 81 Passing Complex Data Types Between Views...82 Deep Links...82 URI Mapping to Enable Friendly URIs...83 Integrating with the Browser History...85 Handling Navigation Events...87 Frame Events... 87 View Events... 88 Caching Views...89 Visual Transition Effects...90 Alternative User Interface Frameworks...91 Summary...91 Chapter 5: Exposing Data from the Server: Using WCF RIA Services...93 What Is WCF RIA Services?...94 How the WCF RIA Services Code Generator Works...95 How Do You Use WCF RIA Services?...96 Linking Your Silverlight and Web Projects... 97 Creating Your Domain Services... 97 Creating Domain Operations on Your Domain Services... 97 viii

Consuming the Domain Services... 98 Getting Started...98 Creating a Data Access Layer Using the Entity Framework...101 Configuring the Database... 101 About the Entity Framework... 101 Creating an Entity Model... 102 Domain Services...102 Understanding the Domain Service Life Cycle... 103 Creating a Domain Service... 104 Domain Operations...107 Query Operations... 107 Insert/Update/Delete Operations... 109 Invoke Operations... 111 Custom Operations... 111 Decorating Entities...112 Metadata Classes... 113 Controlling Client Entity Generation... 113 Validation... 115 Presentation... 118 Miscellaneous Data Annotations... 118 Presentation Model Types...119 Creating the Presentation Model Class... 120 Populating and Exposing Your Presentation Model Types... 121 Updating Your Presentation Model Types... 122 Sharing Code/Logic Across Tiers...123 Inspecting the Generated Code in the Silverlight Project...124 Encapsulating Logic in a Separate WCF RIA Services Class Library...125 Handling Server Errors...126 ix

Handling Data Concurrency Violations...127 Methods of Identifying Concurrency Violations... 127 Configuring the Entity Model to Check for Concurrency Violations... 128 Testing Your Solution... 129 Resolving Conflicts in the Domain Service... 130 Transactions...131 WCF RIA Services Toolkit...132 Alternative Communication Technologies...133 WCF Services... 134 WCF Data Services... 137 HTTP Requests... 138 Sockets... 139 Summary...139 Chapter 6: Implementing Summary Lists...141 Exposing a Summary Collection from the Server...142 Collections and Collection Views...144 ObservableCollection<T>... 144 Views... 144 Consuming Data from the Server...146 Understanding the Domain Context... 146 XAML-Based Approach... 146 Code-Based Approach... 148 Choosing the Right Approach... 149 Explicitly Specifying a Domain Service Host... 150 Using the BusyIndicator Control... 150 Displaying the Summary List...152 Retrieving the Data from the Server... 153 Configuring and Customizing a Control for Displaying Data... 153 x

Choosing the Right Control... 164 Manipulating Summary Lists...165 Querying Data Exposed by a Domain Operation... 165 Filtering the Summary List... 168 Sorting the Summary List... 170 Grouping the Summary List... 172 Paging the Summary List... 175 Drilling Down on a Record...178 Opening Details in a New View... 179 Opening Details in a Pop-Up Window... 180 Displaying Details Using the DataGrid s Row Details... 183 Implementing a Master/Details View... 184 Handling Errors...184 Summary...187 Chapter 7: Building Data Entry Forms...189 Creating the Data Entry User Interface...189 Laying Out the Data Entry Form... 189 Refining the Data Entry Form s Functionality... 201 Using the DataGrid for Data Entry... 212 Structuring Objects for Use by Data Entry Forms...216 Implementing the INotifyPropertyChanged Interface... 216 Implementing the IEditableObject Interface... 220 Adding Calculated Properties to Your Classes... 222 Data Validation...223 Displaying Validation Errors... 223 Types of Data Validation... 226 Defining Validation Rules... 227 Exposing Validation Errors to the User Interface... 228 xi

Notifying the User Interface of Object-Level Validation Errors... 234 The Validator Class... 235 Customizing Validation Attribute Error Messages... 238 Submitting Changes to the Server...238 Change-Tracking... 238 Submitting Changes via the DomainDataSource Control... 239 Submitting Changes via a Domain Context... 239 Handling Errors... 240 Handling Concurrency Violations... 242 Summary...243 Chapter 8: Securing Your Application...245 Implementing Server-Side Security Using RIA Services...245 The ASP.NET Membership API... 246 Configuring Your Database for Forms Authentication... 247 Authentication... 249 Requiring Authentication... 250 Role-Based Operation Access Restrictions... 251 Returning a Subset of Data Based on the User s ID or Role... 253 Permitting Update/Delete Operations According to Data... 253 Exposing Custom User Profile Data... 253 User Registration... 254 Avoiding SQL Injection Attacks... 255 Sanitizing Errors Sent to the Client... 256 Implementing Client-Side Security...256 Authenticating and Registering Users... 256 Accessing and Updating User Information... 259 Implementing Client-Side Restrictions... 260 Storing Data Locally... 262 Encrypting Data Passed Between the Server and the Client...262 xii

Cross-Domain Access Policies...263 Implementing Cross-Domain Policies for HTTP-Based Communication... 264 Implementing Cross-Domain Policies for Socket-Based Communication... 265 Implementing Cross-Scheme Access Policies... 265 Restricting Access to Your Application...266 Summary...268 Chapter 9: Styling Your Application...269 The Designer/Developer Workflow...269 Defining Style Resources...271 Defining a Style Resource... 272 Defining Style Resources at Various Locations... 273 Naming Style Resources... 275 Inheriting Style Resources... 276 Styling Constraints... 277 Control Templates...277 Default Control Templates... 278 Templating a Control... 278 Control Template Structure... 279 Theming...282 Creating a Custom Theme... 282 Silverlight Toolkit Themes... 283 Silverlight Navigation/Business Application Themed Project Templates... 283 Icons and Images...283 Animation...284 Pixel Shaders / Effects...284 Miscellaneous Styling Tips...285 Defining Constants in XAML... 285 Restoring a Control s Default Style... 286 xiii

Summary...286 Chapter 10: Advanced XAML and Data Binding...287 Advanced XAML...287 Comments in XAML... 287 Defining Constants... 288 Using OR to Combine Enumerated Values in XAML... 289 Triggers, Actions, and Behaviors... 289 Blendability... 299 Creating Consolidated Namespaces... 301 MoXAML Power Toys... 303 Advanced Data Binding...303 Assigning the Source of a Binding... 304 Binding to a Resource... 308 Defining Resources in the Code-Behind (For Binding To)... 311 Binding to Nested Properties... 311 Binding to Indexed Properties... 312 Binding to Collection Views... 312 Enhancing Data Binding... 317 Data Binding in Code... 323 Getting and Setting Attached Property Values in Code... 324 Additional Tips... 324 Summary...329 Chapter 11: Creating Custom Controls...331 Adding Functionality to an Existing Control...331 Creating User Controls...332 Creating a Simple User Control... 332 Exposing Properties... 333 Exposing Methods... 345 xiv

Exposing Events... 346 Determining If in Design-Time or Runtime Mode... 347 Constraining the User Control s Size... 347 Creating Custom Controls...347 Creating the Custom Control... 348 The Control Structure... 349 Defining the Control s Default Template... 350 Defining the Control s Behavior... 359 Content Controls...365 Containing a Single Control as Content... 365 Containing Multiple Controls as Content... 367 Attached Properties... 369 Summary...370 Chapter 12: The Model-View-ViewModel (MVVM) Design Pattern...373 The Purpose of Implementing MVVM...374 Why You Should Implement MVVM...375 MVVM Theory...376 The Layers... 376 View / View Model Configurations... 379 MVVM in Practice...380 Creating the Layers... 380 Connecting the Layers... 383 View and ViewModel Interactions... 385 Layer Interaction Summary... 392 Hotly Debated Implementation Details... 393 MVVM and RIA Services...395 Implementing the Model... 395 Implementing the View Model... 396 xv

Implementing the View... 399 Frameworks...401 Summary...401 Chapter 13: Printing and Reporting...403 The Importance of Implementing Reporting...403 Potential Solutions for Implementing Reporting...404 Generating a PDF... 404 Generating HTML... 405 Generating Office Documents... 405 Using Silverlight 4 Printing Functionality... 405 Third-Party Report Viewers... 405 Office Integration Using COM... 407 Choosing a Reporting Strategy...407 Printing Functionality in Silverlight...407 Generating and Displaying a PDF Report...409 Generating a Report on the Server... 409 Displaying the Report on the Client... 418 Summary...426 Chapter 14: Out of Browser Mode, and Interacting with the Operating System...427 Out of Browser...427 Configuring OOB Mode... 428 Installing the Application to Run Out of Browser... 429 Determining Installation Status... 431 Determining Whether Running Inside or Outside the Browser... 432 Where/How is the Application s.xap File Stored and Run?... 432 Interacting with the OOB Window... 433 Checking for Updates... 434 xvi

Debugging Out of Browser... 436 Uninstalling the Application... 436 Toast Notifications... 437 Caching Data Locally...439 Caching to Isolated Storage... 439 Caching to a Client-Side Database... 449 Detecting Network Connection Availability... 451 File System Open/Save Dialogs...451 The Open File Dialog... 452 The Save File Dialog... 456 Drag Drop Target...459 Clipboard...460 Full Screen...462 Initiating Full Screen Mode... 462 Detecting the Switch to and from Full Screen Mode... 463 Retaining Full Screen Mode When Unfocused... 463 Keyboard Access... 464 Elevated Trust...464 Enabling Elevated Trust... 465 File System Access... 466 COM Automation... 471 Custom Chrome... 478 Other Restrictions Lifted By Elevated Trust... 480 Restrictions Imposed by Elevated Trust... 481 Disabling Elevated Trust Applications with a Windows Group Policy... 481 Summary...482 Chapter 15: Application Deployment...483 Deploying the Application to the Server...483 xvii

Server Requirements... 484 Using Xcopy... 485 Publishing... 486 Creating a Web Package... 487 Creating a Setup Program... 488 Deploying the Application to the Client...488 The Default Silverlight Installation Process... 489 Customizing the Silverlight Installation Experience... 490 Pushing the Silverlight Runtime to Users in the Enterprise... 493 Building a Client Desktop Installer... 494 Improving on the Default Application Loading Screen...495 Creating the Application Pre-loader Files... 496 Designing the Application Pre-loader... 497 Updating the Application Download Progress... 499 Configuring the Application Pre-loader in the HTML File... 500 Testing the Application Pre-loader... 500 Partitioning Your Application...502 Initial Steps... 502 Assembly Caching... 502 Downloading Modules on Demand... 505 Digitally Signing Your Application...506 Summary...511 Index...513 xviii

About the Author Chris Anderson has been a professional developer for over 10 years, specializing in building desktop, web, and mobile business applications using Microsoft technologies for industries as wide ranging as accounting, property valuation, mining, the fresh produce industry, logistics, field services, sales, and construction. He holds a Bachelor of Engineering in Computer Systems with a Diploma in Engineering Practice. Chris is now a co-owner of Peer Placements (a specialist recruitment firm for software developers), in addition to working as a consultant, author, and Australian representative of the SilverlightShow.net website. Currently specializing in Silverlight Chris has spoken on this topic at conferences such as Code Camp Australia, TechEd Australia, Silverlight Code Camp Australia, REMIX Australia, and numerous Sydney Silverlight Designer and Developer Network (SDDN) meetings (for which he is a co-organizer). Chris maintains a blog at http://chrisa.wordpress.com, and can be found on Twitter at http://twitter.com/christhecoder. xix

ABOUT THE TECHNICAL REVIEWERS Acknowledgments I had no idea what I was getting into when taking on this book. Writing a book is a long, arduous task that consumes your entire life, but now that this book is complete I would like to thank those who were instrumental in helping it come to fruition. I d like to start by thanking the members of the Apress team with whom I worked closely throughout the writing process. I m grateful for their guidance and encouragement. I d like to thank Jonathon Hassell and Anne Collett, and in particular Tracy Brown, who was extremely patient with me even as deadlines were rapidly approaching. My great thanks also go to my technical editor Ilia Iordanov, who, with an eagle eye, spotted many issues I had missed, and made some great suggestions. I would especially like to thank Greg Harris (www.gregmharris.com) who gave his time to review every chapter in its draft form, and who provided me with extensive feedback. I really appreciate the amount of time and effort Greg voluntarily spent on this project. His contributions are invaluable. I would also like to thank Miguel Madero and Pencho Popadiyn, who provided additional valuable feedback on the Model-View-ViewModel Design Pattern chapter, and Sergey Klementiev for providing a solution to a problem I had with RIA Services. My thanks also go to all the Silverlight bloggers who provided solutions to difficult problems. I ve credited you in the text when you ve provided information that helped me along my way. From a personal perspective, I d really like to thank my sister Michelle, chef extraordinare, for providing me with home-cooked frozen meals that kept me decently fed for a month when I was working furiously on this book and barely leaving the house. It was a huge help. I d also like to thank Mark Wallis, who covered for me with my clients whilst I had my head down writing. I hope they ll forgive my absence. xx