Professional Microsoft SharePoint 2007 Development Using Microsoft Silverlight 2

315

Transcript of Professional Microsoft SharePoint 2007 Development Using Microsoft Silverlight 2

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page ii

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page i

Professional Microsoft® SharePoint® 2007Development Using Silverlight™ 2

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiiChapter 1: Introduction to Silverlight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Chapter 2: Your First Silverlight and SharePoint Integration . . . . . . . . . . . . . . . . 23Chapter 3: Creating Custom Field Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57Chapter 4: Branding your SharePoint site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111Chapter 5: Custom Web Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145Chapter 6: Advanced Custom Web Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169Chapter 7: Data Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205Chapter 8: Bringing It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page ii

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page iii

Professional

Microsoft® SharePoint® 2007 DevelopmentUsing Silverlight™ 2

Steve FoxPaul Stubbs

Wiley Publishing, Inc.

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page iv

Professional Microsoft® SharePoint® 2007 DevelopmentUsing Silverlight™ 2Published byWiley Publishing, Inc.10475 Crosspoint BoulevardIndianapolis, IN 46256www.wiley.com

Copyright © 2009 by Wiley Publishing, Inc., Indianapolis, Indiana

Published simultaneously in Canada

ISBN: 978-0-470-43400-0

Manufactured in the United States of America

10 9 8 7 6 5 4 3 2 1

Library of Congress Cataloging-in-Publication Data

Fox, Steven, 1970-Professional Microsoft SharePoint 2007 development using Silverlight 2 / Steve Fox, Paul Stubbs.

p. cm.Includes index.ISBN 978-0-470-43400-0 (paper/website)

1. Microsoft SharePoint (Electronic resource) 2. Silverlight (Electronic resource)3. Intranets (Computer networks) I. Stubbs, Paul R., 1969- II. Title.

TK5105.875.I6F693 2009006.7’882 — dc22

2008054925

No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by anymeans, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, orauthorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 RosewoodDrive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should beaddressed to the Permissions Department, John Wiley & Sons, Inc., 111 River Street, Hoboken, NJ 07030, (201)748-6011, fax (201) 748-6008, or online at http://www.wiley.com/go/permissions.

Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties withrespect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties,including without limitation warranties of fitness for a particular purpose. No warranty may be created or extendedby sales or promotional materials. The advice and strategies contained herein may not be suitable for everysituation. This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting,or other professional services. If professional assistance is required, the services of a competent professional personshould be sought. Neither the publisher nor the author shall be liable for damages arising herefrom. The fact that anorganization or Web site is referred to in this work as a citation and/or a potential source of further informationdoes not mean that the author or the publisher endorses the information the organization or Web site may provideor recommendations it may make. Further, readers should be aware that Internet Web sites listed in this work mayhave changed or disappeared between when this work was written and when it is read.

For general information on our other products and services please contact our Customer Care Department within theUnited States at (877) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002.

Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, and related tradedress are trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affiliates, in the United Statesand other countries, and may not be used without written permission. Microsoft, SharePoint, and Silverlight aretrademarks or registered trademarks of Microsoft Corporation in the United States and/or other countries. All othertrademarks are the property of their respective owners. Wiley Publishing, Inc. is not associated with any product orvendor mentioned in this book.

Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not beavailable in electronic books.

Fox ffirs.tex V3 - 01/30/2009 5:09pm Page v

To Nicole, for putting up with my ‘‘quiet time’’ when trying to write this book.

— Steve Fox

To my wife, Rosa, who allowed me time away to write during a coast-to-coast move,buying and selling a home, a broken finger, and a new baby girl. Without her support and understanding,

this book would not have been possible.

— Paul Stubbs

Fox f01.tex V3 - 01/30/2009 5:07pm Page vi

About the AuthorsSteve Fox has been in the IT industry for more than 12 years, working in various areas includingsearch and natural language, web development, and more recently Office and SharePoint development.He currently works for Microsoft as a Senior Technical Evangelist. When not working, he enjoyssports — especially hockey — as well as movies and writing. He is hopeful that the Buffalo Sabres willone day win the Stanley Cup. He currently lives in Seattle, Washington.

Paul Stubbs is a Senior Architect Evangelist in the Platform Architecture Team within the Developerand Platform Evangelist group at Microsoft. He focuses on solutions architecture with an emphasis oninformation worker productivity, business-to-customer (B2C) solutions, and Web 2.0 social networking.Paul has also worked with several other groups at Microsoft. He helped ship the first and second versionsof Visual Studio Tools for Office (VSTO) and Visual Studio Tools for Applications (VSTA), wherein hedeveloped a new managed code application programmability development tool for InfoPath 2007. Healso developed programmability features for future versions of Microsoft Office for the Groove team.

Fox f02.tex V3 - 01/30/2009 5:08pm Page vii

CreditsAcquisitions EditorKatie Mohr

Development EditorMaureen Spears

Technical EditorLaurence Moroney

Senior Production EditorDebra Banninger

Copy EditorCate Caffrey

Editorial ManagerMary Beth Wakefield

Production ManagerTim Tate

Vice President and Executive Group PublisherRichard Swadley

Vice President and Executive PublisherBarry Pruett

Associate PublisherJim Minatel

Project Coordinator, CoverLynsey Stanford

ProofreaderNancy Carrasco

IndexerJ & J Indexing

Fox f03.tex V3 - 01/30/2009 5:08pm Page viii

Acknowledgments

It takes many people to put together a book like this, and often this work goes unseen to the reader. I’dfirst like to thank the staff at Wiley for doing a great job of keeping us on track and making sure that ourcontent was strong and moved along at the right pace. I’d like to especially thank Maureen for keepingthe whip cracking and Katie for believing in this project in the first place. There are, I’m sure, manyothers at Wiley who touched this book in some way, and for those of you I didn’t have direct contactwith but who did work on this book, thanks! I’d secondly like to thank Laurence, acting as our TechnicalReviewer, who raised great questions along the way but kept us on track and made the book what I seeas a much better finished product. And lastly, thanks to the folks at Microsoft who helped us along theway — whether it was answering questions on forums, reviewing content, or spending a few minutesresponding to our e-mails.

— Steve Fox and Paul Stubbs

Fox ftoc.tex V3 - 01/30/2009 5:17pm Page ix

Contents

Introduction xiii

Chapter 1: Introduction to Silverlight 1

Designer and Developer Convergence 1Overview of XAML 2Silverlight Code-Behind 9Developer Environment and Tools 13

Changing the MIME Type 13Editing the web.config File 14Copying the Silverlight DLL to Your GAC 18

Why Silverlight and SharePoint? 18Summary 20Additional References 20

Chapter 2: Your First Silverlight and SharePoint Integration 23

Different Ways to Integrate with SharePoint 23Creating the Silverlight Application 25

Silverlight Solution Project Files 26Creating the Silverlight Application Code-Behind 37

Creating and Deploying the SharePoint Web Part Host Container 47Creating the Web Part Project 47Adding References to the Project 48Configuring the Web Part Project for Deployment 51

Adding the Silverlight Video Player Application to the SharePoint Site 52Troubleshooting Tips 55Summary 56Additional References 56

Chapter 3: Creating Custom Field Types 57

Lists, Columns, and Custom Field Types 57Using List Templates and Customer Lists 58

Developing Your First Custom Field Type 62Creating an ASP-Based Custom Field Type 63Developing a Silverlight-Based Custom Field Type 75

Fox ftoc.tex V3 - 01/30/2009 5:17pm Page x

Contents

Creating the Silverlight and SharePoint Integration 87Deploying the Solution 107

Summary 109Additional References 109

Chapter 4: Branding your SharePoint site 111

Custom Site Page 111Adding a Blank Branding Solution 112Adding a Custom Site Page 113Adding Your Own Content 116

Create Navigation Menu 123Custom List Page 128

Adding a Feature to the Project 129Customizing the List with Silverlight 130Creating a New Custom List View 133

Customizing the Master Page 137Creating a Basic Master Page 138Customizing the Page 141

Summary 144

Chapter 5: Custom Web Parts 145

Creating a Silverlight Control 145Creating a New Silverlight Project 146Editing the New Control 146

Content Editor Web Part 149Getting Your Application to Run 150Adding a Silverlight Plug-In 151JavaScript Only 153Silverlight Streaming 154

Customizing Web Part 154Starting a New Web Part Project 154SharePoint Solution Features 154Displaying the Silverlight Control and Adding References 155Running the Solution 158Deploying the Silverlight Application 159Uninstalling and Updating the Solution 162Render Contents 162Web Part Gallery Category 164Web Part Properties 165Debugging 166

Summary 168

x

Fox ftoc.tex V3 - 01/30/2009 5:17pm Page xi

Contents

Chapter 6: Advanced Custom Web Parts 169

Cleaning up Files and Web Parts upon Uninstall 170Using Feature Receivers 170Debugging Feature Receivers 178

Customizing Web Parts 180Using Custom Embedded JavaScript Files 181Using Customized Verbs 182Editing Custom Web Part Properties 186Using Custom Web Part Editor 189

Creating Editor Parts 193Display Mode 193Display Dynamic Silverlight UI Based on Web Part Display Mode 195

Summary 202

Chapter 7: Data Connectivity 205

Initialization Parameters 205Retrieving the InitParameters 207Using Hidden Field 210Using HTML Cookies 214

XML Data Island 220Creating the Server Control 220Setting the URL for an XML Data Source 225

Calling Web Services 225Adding a New Contact List to the SharePoint Site 227Data-Bind to the ListBox 229

Part-to-Part Communication 232Registering Controls 234Setting the ScriptableMethod Attribute 236

Summary 246

Chapter 8: Bringing It All Together 247

The Training List 248Service 250What about WCF? 259Hosting the Silverlight Application 274

Re-Skinning the Training List 276Binding Data to a Silverlight Chart 278The Application in Action 283Summary 284

Index 285

xi

Fox ftoc.tex V3 - 01/30/2009 5:17pm Page xii

Fox f04.tex V3 - 01/30/2009 3:38pm Page xiii

I n t roduc t ion

Two exciting trends in the set of Microsoft products are the recent release of Silverlight 2 and theincreased use of Microsoft Office SharePoint Server (MOSS) 2007. There is a growing community aroundboth of these products, and their convergence — something that developers see as having a great amountof potential — is in its infancy. The goal of this book is to provide developers with the knowledge theyneed to integrate Silverlight and SharePoint in different ways. The hope is not only to enhance the userexperience for SharePoint sites (both Intranet and Internet-facing sites), but also to integrate rich Internetapplications (or RIAs) into the SharePoint experience, thus leveraging the SharePoint infrastructure andintegrating greater and richer application functionality into the context of a SharePoint site.

Who This Book Is ForThis book is primarily for .NET or SharePoint developers. Now that’s a pretty broad community, sowe’d qualify that to say those developers who are interested in integrating Silverlight with SharePoint.That said, the types of skills we envisioned you as having when we wrote the book was a beginningknowledge of Silverlight. We’ll walk you through some of the basics in this book, but if you’re new toSilverlight, it might help to read a couple of introductory articles or, if you’re feeling eager, pick up aSilverlight 2 book. [Introducing Silverlight 2 (2nd Ed.) (MS Press) is a good introductory text.] Also, you’dlikely have an intermediate knowledge of SharePoint. Now if you don’t have either of these, you willstill get something from this book; you may just need to do a little side research after you finish the book.SharePoint is a very big product, so you could apply Silverlight in many different ways. We’ve givenwhat we feel are a few patterns of application, but ultimately, as you learn SharePoint more, you’ll seewhere you can apply the rich functionality enabled by Silverlight to your SharePoint solutions.

As fundamental developer skills, we’ll be using Visual Studio 2008 throughout this book as the coredevelopment tool, so you should be familiar with Visual Studio and .NET Framework 3.5. Paul and Iboth develop primarily in C#, but we feel that there is a large community of Visual Basic (VB) developersout there, and you can just as easily develop in VB as you can in C#, so we included both C# and VBcode samples. This does stretch out the code on the pages a little, but given the appeal of the technologieswe discuss in this book and the ability to use both VB and C# for development against Silverlight andSharePoint, we feel this was a worthwhile trade-off.

All that said, if you are a developer and you’re interested in transforming a SharePoint site using Sil-verlight, then you should read this book.

What This Book CoversAs mentioned above, the two primary technologies covered in this book are Silverlight 2 and MOSS 2007(which we’ll refer to as SharePoint throughout this book). To do the development work, we’ll use tools

Fox f04.tex V3 - 01/30/2009 3:38pm Page xiv

Introduction

like Visual Studio and Expression Blend. The book will start by having you create a simple Silverlightapplication and work toward more complex integrations of your Silverlight applications with variousartifacts within SharePoint. For example, we’ll cover things like integration of Silverlight applicationswith Web Parts or custom fields and discuss how data can be bound to Silverlight applications. We’llprovide code samples where appropriate and will end the book with a chapter on how you might applywhat you’ve learned to build a small Silverlight-based application in SharePoint.

How This Book Is StructuredOur approach is to progressively build on complexity as we move through the book and also to offerup different types of integration between Silverlight and SharePoint. That said, the following are thechapters and what we’ll discuss in each chapter:

❑ Chapter 1: Introduction to Silverlight — This chapter introduces you to the book and providesa high-level overview of Silverlight. It walks through a simple Silverlight application and talksabout setting up your development environment.

❑ Chapter 2: Your First Silverlight and SharePoint Integration — This chapter discusses how tocreate your first Silverlight and SharePoint integrated application. This integration is enabled byfirst creating a Silverlight media player example and then using a Web Part within SharePoint asthe host for the Silverlight application.

❑ Chapter 3: Creating Custom Field Types — This chapter shows how you can create custom fieldtypes in SharePoint lists. It walks through a couple of examples, first showing you where youuse simple ASP.NET as the code for a control and then a Silverlight application that uses a WebService to read data from and write data to SharePoint.

❑ Chapter 4: Branding Your SharePoint Site — This chapter shows how you can customize thelook and feel of your site. You will learn how to create custom Silverlight-enabled master pagesand site pages. You will also learn how to add Silverlight to existing or custom SharePoint lists.

❑ Chapter 5: Custom Web Parts — Web Parts are a core feature of SharePoint, and in this chapter,you create a simple custom Web Part using Silverlight. You will also see different strategies forbuilding and debugging Silverlight-enabled Web Parts. This chapter also teaches you how tocorrectly set up a SharePoint and Silverlight project in Visual Studio.

❑ Chapter 6: Advanced Custom Web Parts — This chapter builds on the samples started in theprevious chapter. You learn how to take your Web Parts to the next level. You discover how tocreate Silverlight-enabled Web Part Editors and Context menus as well as how to use FeatureReceivers to properly deploy your Silverlight projects to SharePoint for a true [F5] deploymentexperience.

❑ Chapter 7: Data Connectivity — This chapter demonstrates various techniques of moving databack and forth between SharePoint and Silverlight. You will also learn how to dynamically con-nect and communicate between all of the Silverlight controls and Web Parts on your SharePointpage. This enables scenarios such as loosely coupled master detail Web Parts.

❑ Chapter 8: Bringing It All Together — The final chapter discusses a simple application that tiestogether some of what you’ve learned in the book. It is not a walk-through, however, but doesprovide some key code samples for you to see how certain things can be applied when creatinga solution that integrates Silverlight and SharePoint.

xiv

Fox f04.tex V3 - 01/30/2009 3:38pm Page xv

Introduction

What You Need to Use This BookTo be able to do all of the samples in this book, you’ll need to set up a development environment withseveral things installed. First, in terms of hardware, you’ll need to set up a 32-bit development environ-ment using Windows Server 2008. Note that you can use Windows Server 2003 as your operating system;however, in this book, our development environment was the Windows 2008 Enterprise edition. You’llalso want to have a good machine (e.g., Xeon processor) with at least 3 GB of RAM, as you will more thanlikely have SharePoint as a native installation on your machine.

The baseline software you’ll need within your development environment is as follows:

❑ Windows Server 2008 (or 2003)

❑ Microsoft Office SharePoint Server 2007 (Enterprise Edition)

❑ Visual Studio 2008 SP1

❑ Silverlight 2 Tools for Visual Studio 2008 SP1

❑ Silverlight 2 SDK

❑ Silverlight 2 Client Runtime

❑ Visual Studio Extensions for Windows SharePoint Services 1.2

❑ Expression Blend 2 SP1

Once you have each of these installed, you’ll be ready to get started!

ConventionsTo help you get the most from the text and keep track of what’s happening, we’ve used a number ofconventions throughout the book.

Tips, hints, tricks, and asides to the current discussion are offset and placed in italics like this.

As for styles in the text:

❑ We highlight new terms and important words when we introduce them.

❑ We show keyboard strokes like this: Ctrl+A.

❑ We show URLs and code within the text like so: persistence.properties.

❑ We present code in two different ways:

In code examples we highlight new and important code with a gray background.

The gray highlighting is not used for code that’s less important in the presentcontext, or has been shown before.

xv

Fox f04.tex V3 - 01/30/2009 3:38pm Page xvi

Introduction

Source CodeAs you work through the examples in this book, you may choose either to type in all the code manually orto use the source code files that accompany the book. All of the source code used in this book is availablefor download at www.wrox.com. Once at the site, simply locate the book’s title (either by using the Searchbox or by using one of the title lists), and click the Download Code link on the book’s detail page to obtainall the source code for the book.

Because many books have similar titles, you may find it easiest to search by ISBN; this book’s ISBN is978-0-470-43400-0.

Once you download the code, just decompress it with your favorite compression tool. Alternately, youcan go to the main Wrox code download page at www.wrox.com/dynamic/books/download.aspx to seethe code available for this book and all other Wrox books.

ErrataWe make every effort to ensure that there are no errors in the text or in the code. However, no one isperfect, and mistakes do occur. If you find an error in one of our books, like a spelling mistake or faultypiece of code, we would be very grateful for your feedback. By sending in errata you may save anotherreader hours of frustration, and at the same time, you will be helping us provide even higher-qualityinformation.

To find the errata page for this book, go to www.wrox.com and locate the title using the Search box orone of the title lists. Then, on the book details page, click on the Book Errata link. On this page, you canview all errata that have been submitted for this book and posted by Wrox editors. A complete book listincluding links to each book’s errata is also available at www.wrox.com/misc-pages/booklist.shtml.

If you don’t spot ‘‘your’’ error on the Book Errata page, go to www.wrox.com/contact/techsupport.shtml and complete the form there to send us the error you have found. We’ll check the informationand, if appropriate, post a message to the book’s errata page and fix the problem in subsequent editionsof the book.

p2p.wrox.comFor author and peer discussion, join the P2P forums at p2p.wrox.com. The forums are a Web-basedsystem for you to post messages relating to Wrox books and related technologies and interact with otherreaders and technology users. The forums offer a subscription feature to e-mail you topics of interest ofyour choosing when new posts are made to the forums. Wrox authors, editors, other industry experts,and your fellow readers are present on these forums.

At http://p2p.wrox.com, you will find various forums that will help you not only as you read this book,but also as you develop your own applications. To join the forums, just follow these steps:

1. Go to p2p.wrox.com and click on the Register link.

2. Read the terms of use and click Agree.

xvi

Fox f04.tex V3 - 01/30/2009 3:38pm Page xvii

Introduction

3. Complete the required information to join as well as any optional information you wish toprovide, and click Submit.

4. You will receive an e-mail with information describing how to verify your account and com-plete the joining process.

You can read messages in the forums without joining P2P, but in order to post your own messages, youmust join.

Once you join, you can post new messages and respond to messages other users post. You can readmessages at any time on the Web. If you would like to have new messages from a particular forume-mailed to you, click on the ‘‘Subscribe to This Forum’’ icon by the forum name in the forum listing.

For more information about how to use the Wrox P2P, be sure to read the P2P FAQs for answers toquestions about how the forum software works as well as many common questions specific to P2P andWrox books. To read the FAQs, click on the FAQ link on any P2P page.

xvii

Fox f04.tex V3 - 01/30/2009 3:38pm Page xviii

Fox c01.tex V3 - 01/30/2009 4:56pm Page 1

Introduction to Silverlight

As software development has evolved and the process and end result become more complex andsophisticated, so too has the expectation of end-users. This not only holds true for the desktopapplication, but also has become increasingly evident in the area of web-based applications. Arecent report (see www.idea.org/find-information.html) cited the fact that ‘‘designers underesti-mate the thresholds for an effective site,’’ thus often missing the mark for their users. Furthermore,users want ‘‘good visual design’’ in their web application experience. Thus, a technological shiftwas needed to bring the delivery of richer applications, similar to those that run on desktops, to theWeb. Enter Silverlight.

Silverlight is a new technology from Microsoft that enables developers to build rich, interactiveuser experiences for web-based applications. At its essence, it is a cross-browser and cross-platformplug-in that Microsoft developed to enable a more compelling and interactive media-based appli-cation experience on the Web. Applications that you build using Silverlight give you access to alighter version of the .NET Framework and run on an end-users’ web client through the Silverlightplug-in. Thus, Silverlight offers a rich programming model that supports not only .NET 3.5 (so tech-nologies such as LINQ, C#, Visual Basic (VB), XML serialization, etc. are supported) and AJAX, butalso more dynamic languages such as JavaScript, Ruby, and Python. Silverlight also provides anextensive library of standard controls that you can customize, support for data-binding, styling,and templates. Silverlight also ships with a comprehensive SDK.

Designer and Developer ConvergenceAt the core of the Silverlight development experience is the convergence of the designer andthe developer. That is, with other technologies, it’s been difficult for designers and developersto simultaneously share the same project and code base with a rich set of supported designerand developer tools. Silverlight changes this. By integrating the Expression Blend designer tooland Visual Studio Developer tool, Microsoft has created a new way for designers and developersto collaboratively build applications. For example, often designers will craft and spec a userinterface (UI) for an application, but they won’t have a designer tool that enables them to effectively‘‘stub out’’ the UI for the developer — and then collaboratively iterate through application design

Fox c01.tex V3 - 01/30/2009 4:56pm Page 2

Chapter 1: Introduction to Silverlight

should changes be required throughout the project life cycle. Figure 1-1 graphically illustrates anintegrated experience between Expression and Visual Studio in which Julia, a UI designer for webapplications, can create the UI in Expression, and Ben, a developer of web applications, can work off thesame code base to implement the code-behind. The technical heart of this collaborative experience liesin the ability for the Silverlight plug-in not only to render what is called Extensible Application MarkupLanguage (XAML — pronounced zammel), but also to integrate that XAML with the programming codethat an application developer builds as the logic behind the web-based application. And while there aremany features that Silverlight supports, it is these two areas that you’ll focus on in this chapter and uponwhich you’ll build in subsequent chapters.

Figure 1-1

To better understand how the designer and developer work together, let’s briefly explore XAML andhow this XAML maps to the code-behind that a developer generates.

Overview of XAMLIf you’re familiar with Windows Presentation Foundation (WPF), one of the core features of .NET Frame-work 3.5, you already have come across XAML. (You should note that the Silverlight XAML is a subset ofthe WPF XAML, so there are some differences across them; thus, they’re not directly translatable acrossclient-based applications and web-based applications.) If you’re not, XAML is essentially an XML-based,declarative language that is used to build the interface for your web application — including such thingsas the core UI, any animations or graphical elements within the UI, media loading, controls, textualelements, and much more. Because XAML is XML-based, you can also apply styling and templates to it.

You primarily create XAML in one of three ways:

1. A text-based tool such as Notepad (which isn’t recommended given the tools’ support)

2. The designer within Visual Studio (codenamed ‘‘Cider’’)

3. The Expression Blend toolset.

If you’re trying to create a relatively simple or straightforward UI, then using the designer within VisualStudio may be the right option. However, we would encourage you, even as a developer, to exploreExpression Blend. While it is a broad toolset with many design-specific features, the fact that you can

2

Fox c01.tex V3 - 01/30/2009 4:56pm Page 3

Chapter 1: Introduction to Silverlight

use Expression and Visual Studio simultaneously (against the same source-code project) means thatas a developer you can experiment with UI design (in a rich environment) as well as build the customapplication code for your web-based application. That said, as a developer you can look to either VisualStudio or Expression, and if you’re a designer, you will likely want to stick with using Expression Blend.

Using XAML, you can lay out your UI and then associate events with the controls you place within yourUI. XAML provides several ‘‘structural’’ containers that you can use to position controls. For example,you can use:

❑ Canvas and then add other controls to it to build out a complete UI — or smaller part of alarger UI.

❑ The Grid object in a similar manner, although the Grid enables you to create a table-like struc-ture (i.e., a grid layout) with rows and columns.

❑ The StackPanel to stack UI elements on top of one another.

With each of the above containers, you can add other controls within them and then position these con-trols by using coordinate properties (e.g., Canvas.Left = "10"). Silverlight has a good library of controlsout-of-the-box, so you’ll have a number of choices available to you when creating your application UI.For example, Listing 1-1 provides a fairly simple UI expressed as XAML. As you look at the XML code,notice that we’re creating a UserControl object within the UI — the default type of control that is gen-erated when creating a new project. Within the UserControl, a Canvas represents the host container.Note that we’ve also set some properties on the Canvas, namely, the height, horizontal and vertical align-ment, and width. Also note that the example uses a Canvas gradient brush for the background (a stylecustomization that can be applied to your application UI), and includes various properties for each ofthe buttons, which create the layout, textual content on the button, and the look and feel for the button.Similar to the Canvas object, you’ll note that each of the elements on the Canvas has several possible prop-erties that can be set, for example, height, horizontal alignment, width, and so on. As you learn XAML,you’ll become very familiar with properties as all objects within the Silverlight have a range of propertiesthat can be set. If you use Expression Blend to create your UI, the XAML is created for you so you don’tneed to worry about entering in the specific properties you want associated with a specific object in yourUI. When in Visual Studio, you have the ability to drag-and-drop controls from the Toolbox to the XAMLcode window, but not to the XAML designer — so you need to enter the specific properties for an objectmanually.

We’ll be exploring different XAML-based UIs throughout this book, but given the fact that we’ll mainlybe discussing the integration between SharePoint and Silverlight in this book, we assume a basic knowl-edge of XAML. That said, see the ‘‘Additional References’’ section in this chapter for additional refer-ences.

Listing 1-1: Multiple controls within XAML container<UserControl

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"x:Class="ExampleGrid.Page"Width="650" Height="480"

xmlns:d=http://schemas.microsoft.com/expression/blend/2008xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d">

<Canvas

Continued

3

Fox c01.tex V3 - 01/30/2009 4:56pm Page 4

Chapter 1: Introduction to Silverlight

Listing 1-1: Multiple controls within XAML container (continued)

Height="187"HorizontalAlignment="Left"VerticalAlignment="Top"Width="650">

<Canvas.Background><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

<GradientStop Color="#FF000000"/><GradientStop Color="#FF9C8F8F" Offset="1"/>

</LinearGradientBrush></Canvas.Background>

<ButtonHeight="53"HorizontalAlignment="Left"Margin="0,0,0,0"VerticalAlignment="Top"Width="100"Content="Button"Canvas.Top="78"Canvas.Left="311.966"/>

<ButtonHeight="53"HorizontalAlignment="Left"Margin="0,0,0,0"VerticalAlignment="Top"Width="98"Content="Button"Canvas.Left="415.966"Canvas.Top="78"/>

<ButtonHeight="53"HorizontalAlignment="Stretch"Margin="0,0,0,0"VerticalAlignment="Top"Content="Button"Canvas.Top="78"Canvas.Left="210"Width="97.966"/>

<ButtonHeight="53"HorizontalAlignment="Right"Margin="0,78,210,0"VerticalAlignment="Top"Content="Button"Width="100"/>

<ButtonHeight="53"HorizontalAlignment="Right"

4

Fox c01.tex V3 - 01/30/2009 4:56pm Page 5

Chapter 1: Introduction to Silverlight

Margin="0,0,0,0"VerticalAlignment="Top"Content="Button"Width="100"Canvas.Top="78"Canvas.Left="106"/>

<ButtonHeight="53"Width="98"Content="Button"Canvas.Left="517.966"Canvas.Top="78"/>

</Canvas></UserControl>

When you render the previous XAML, it displays a Canvas with buttons laid out horizontally — onecould (loosely) argue the beginning of a custom navigation (see Figure 1-2). In a real-world scenario, adeveloper could associate events with each of the buttons by mapping the events to the actual controlswithin the XAML.

ButtonButtonButtonButton ButtonButton ButtonButton ButtonButton ButtonButton

Figure 1-2

XAML also has a rich set of attributes that allow you to, for example, provide animation, shapes, andgradient brush strokes to the objects that you add to your application. Using these extended properties,you can begin to bring life to your UI in new and interactive ways and enhance the graphical displayof your application UI. To get you more acquainted with XAML, we have put together another simpleexample — Listing 1-2. Note that this example creates a UserControl, within which several controls havebeen added to a Canvas with a white background. You’ll also note the x:Class property; this integratesthe code-behind with the XAML file in your Silverlight application. Also note the namespaces, which arestandard namespaces created by default when you create a new Silverlight project and are used to renderthe XAML.

Within this user control are various radio buttons, text-blocks, and buttons that create a simple form. Thepurpose of the form is to accept some user entry, in this case, salary information, which then surfacesa calculation based on the user entry and the selected state via the radio buttons. Within each of theseaforementioned controls, note the fact that they’re positioned on the Canvas using the Canvas.Left andCanvas.Top properties, and where an event handler was added, you’ve also got an x:Name propertyassociated with the XAML control. The event triggers in this simple UI are associated with the buttoncontrols, specifically a click event for both buttons. One of the click events, for example, denotedthrough click_calcSalaryClick, will call the calcSalaryClick method when the user clicks the button.

5

Fox c01.tex V3 - 01/30/2009 4:56pm Page 6

Chapter 1: Introduction to Silverlight

The calcSalaryClick method is where the developer enters this collaborative picture; that is, this is themethod for which they will create the logic.

If you’re not quite sure how you got to this point, don’t worry; you’ll walk through how to create a Sil-verlight project in Chapter 2. At this stage, we just want to familiarize you with a simple XAML exampleand illustrate how it hooks up to the code-behind.

Listing 1-2: Simple user control<UserControl x:Class="SLSalaryCalc.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="300" Height="250">

<Canvas Background="White"><TextBlock

Canvas.Left="10"Canvas.Top="5"FontWeight="Bold">Simple Salary Calculator

</TextBlock><RadioButton

x:Name="WAState"Canvas.Left="155"Canvas.Top="30"Content="Washington">

</RadioButton><RadioButton

x:Name="ORState"Canvas.Left="155"Canvas.Top="50"Content="Oregon">

</RadioButton><RadioButton

x:Name="ILState"Canvas.Left="155"Canvas.Top="70"Content="Illinois">

</RadioButton>

<TextBlockx:Name="lbl"HorizontalAlignment="Left"Foreground="Black"Canvas.Top="110"Canvas.Left="30">Enter Your Salary:

</TextBlock><TextBox

x:Name="myTextBox"VerticalAlignment="Center"Height="25"Width="120"Canvas.Left="160"

6

Fox c01.tex V3 - 01/30/2009 4:56pm Page 7

Chapter 1: Introduction to Silverlight

Canvas.Top="110"></TextBox><TextBlock

x:Name="total"HorizontalAlignment="Left"Foreground="Black"Canvas.Top="140"Canvas.Left="30">Your Net Salary:

</TextBlock><TextBox

x:Name="netSalary"HorizontalAlignment="Left"VerticalAlignment="Center"Canvas.Top="140"Canvas.Left="160"Height="25"Width="120">

</TextBox><Button

x:Name="calcSalary"Height="30"Width="75"Canvas.Left="80"Canvas.Top="200"Content="Calculate"Click="calcSalary_Click">

</Button><Button x:Name="clearFields"

Height="30"Width="75"Canvas.Left="180"Canvas.Top="200"Content="Clear"Click="clearFields_Click">

</Button></Canvas>

</UserControl>

When you’re building your XAML in Visual Studio, Figure 1-3 shows you the view you can expect towork with. The view is split into a designer and a XAML view. You can drag-and-drop Silverlight con-trols from the Toolbox to the XAML view, and then you add the properties manually in the XAML view.For the full drag-and-drop experience, as mentioned earlier, you’d need to use Expression Blend — whichalso provides you with a very rich set of tools to manipulate your Silverlight controls. In Figure 1-3, notethat you’ve got the controls available in the Toolbox on the left-hand side, the XAML designer and codeview in the middle, and, of course, the Solution Explorer to the right-hand side of the project view. Ifyou’re familiar with Visual Studio, then all of this is old news to you; if you’re new to Visual Studio,you’ll want to make sure you ramp up on Visual Studio to understand your available options (beyondthat of Silverlight which are covered in this book).

Because Expression Blend and Visual Studio are integrated, you can right-click on the Page.xaml file inyour Solution Explorer and select ‘‘Open in Expression Blend’’ (see Figure 1-4). This will open ExpressionBlend and automatically load the same Silverlight project, opening the XAML view by default.

7

Fox c01.tex V3 - 01/30/2009 4:56pm Page 8

Chapter 1: Introduction to Silverlight

Figure 1-3

Figure 1-4

8

Fox c01.tex V3 - 01/30/2009 4:56pm Page 9

Chapter 1: Introduction to Silverlight

When Expression Blend opens (Figure 1-5 shows a simple form in Blend), you can select the Split view,which shows both the user control and the XAML. Note that in Expression Blend, you have a similarview of the project files on the right side of the main view. You also have a Properties and Resourcestab, which you use to graphically enhance your XAML control or add additional resources to it. Onthe left side of the main view, you have your tool palette menu, where you can select specific optionssuch as Paint, Select, Magnify, and so on. You can also select controls and add them to the designer. Asmentioned previously, this is where you would drag the controls into a specific position. The build andtest experience is consistent across Visual Studio and Expression Blend; that is, when you want to testyour application, you press [F5] to test it

Figure 1-5

Silverlight Code-BehindNow that you’ve seen some XAML, which in the example represents a basic form, you’re probablywondering what the code-behind looks like. Listing 1-3 shows both the C3 and the VB code for thissimple form. Note that in this code-behind, there are two methods that are mapped to the XAML UI:calcSalary_Click and clearFields_Click. These two methods were added when you created yourXAML, but they provide the link between the user controls as objects and the events that are mapped tothose objects. For example, the calcSalary_Click event is mapped to the Calculate button, which calls

9

Fox c01.tex V3 - 01/30/2009 4:56pm Page 10

Chapter 1: Introduction to Silverlight

the calculateMyTax method, which returns a net salary based on the user input. The sample code alsochecks to see what radio button the user has selected (the state within which they live), which sets the taxrate, which is further used in the calculation of the net salary. You can see that in the sample code you’rechecking to see if either the WAState, ORState, or ILState radio buttons are checked, and whichever oneis selected, you associate with a specific tax rate. To provide some additional guidance on the code, wehave added comments inline to both the C# and the VB sample code.

Listing 1-3: Simple form code-behind

C#using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;

namespace SLSalaryCalc{

public partial class Page : UserControl{

public Page(){

InitializeComponent();}

private void calcSalary_Click(object sender, RoutedEventArgs e){

//Variables used for calculating tax and salary.double stateTax = 0.00;string userText = "";int salary = 0;

//Checking what state is entered and then setting the tax rate.if (WAState.IsChecked == true){

stateTax = .10;}else if (ORState.IsChecked == true){

stateTax = .13;}else if (ILState.IsChecked == true){

stateTax = .15;}

//Getting the user entry information (their salary).

10

Fox c01.tex V3 - 01/30/2009 4:56pm Page 11

Chapter 1: Introduction to Silverlight

userText = myTextBox.Text;salary = Int32.Parse(userText);

//Calling the method to calculate the tax rate.netSalary.Text = calculateMyTax(salary, stateTax);

}

private void clearFields_Click(object sender, RoutedEventArgs e){

myTextBox.Text = "";netSalary.Text = "";

}

//Method to calculate the tax rate.private string calculateMyTax(int salary, double stateTax){

double tax;double totalSalary;tax = salary * .28 * stateTax;totalSalary = salary - tax;return totalSalary.ToString();

}

}}

VBImports SystemImports System.Collections.GenericImports System.LinqImports System.NetImports System.WindowsImports System.Windows.ControlsImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.AnimationImports System.Windows.ShapesPartial Public Class Page

Inherits UserControl

Public Sub New()InitializeComponent()

End Sub

Private Sub calcSalary_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)’Variables used for calculating tax and salary

Dim stateTax As Double = 0.0Dim userText As String = ""

Continued

11

Fox c01.tex V3 - 01/30/2009 4:56pm Page 12

Chapter 1: Introduction to Silverlight

Listing 1-3: Simple form code-behind (continued)

Dim salary As Integer = 0

’Checking what state is entered and then setting the tax rate.If WAState.IsChecked = True Then

stateTax = 0.1ElseIf ORState.IsChecked = True Then

stateTax = 0.13ElseIf ILState.IsChecked = True Then

stateTax = 0.15End If

’Getting the user entry information (their salary).userText = myTextBox.Textsalary = Int32.Parse(userText)

’Calling the method to calculate the tax rate.netSalary.Text = calculateMyTax(salary, stateTax)

End Sub

Private Sub clearFields_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

myTextBox.Text = ""netSalary.Text = ""

End Sub

‘Method to calculate the tax ratePrivate Function calculateMyTax(ByVal salaryParam As Integer, _

ByVal stateTaxParam As Double)Dim tax As Double = 0.0Dim totalSalary As Double = 0.0Dim returnValue As Double = 0.0

tax = salaryParam * 0.28 * stateTaxParamtotalSalary = salaryParam - taxreturnValue = totalSalary.ToStringReturn returnValue

End FunctionEnd Class

The great thing is, when you build and deploy this simple form, and — in the context of thisbook — integrate with SharePoint, Silverlight executes the applications within SharePoint using theSilverlight plug-in that the user downloads and installs on his or her client. However, what’s reallynice is that it does so without needing any additional hookup code; that is, all of the code that yourequire to run your application is built and deployed as a XAP (pronounced zap) Package, which can beunzipped and inspected when trying to understand what files are packaged for deployment. Thus, whenintegrating Silverlight into your SharePoint sites, you have the option to deploy these applications toyour site very easily, and they can act as independent components within your overall SharePoint site.Depending on the purpose of your Silverlight application, this may be a desired outcome; else you maywant to tie Silverlight to specific SharePoint objects (e.g., skinning a list with Silverlight). We will discussboth of these scenarios throughout this book.

12

Fox c01.tex V3 - 01/30/2009 4:56pm Page 13

Chapter 1: Introduction to Silverlight

Developer Environment and ToolsOne of the key things you’ll need to understand before you get under way is how to set up a developmentsandbox environment so that you can build and integrate Silverlight applications into SharePoint. To dothis, you’ll want to make sure you have the following installed:

❑ Windows Server (2003 or 2008)

❑ Windows SharePoint Services 3.0 and Windows SharePoint Services Service Pack 1

❑ Microsoft Office SharePoint Server 2007 and 2007 Microsoft Office SharePoint Servers ServicePack 1 (SP1)

❑ Visual Studio 2008 Professional Edition (or above)

❑ Silverlight Tools Beta 2 for Visual Studio 2008

❑ Silverlight Beta 2 Runtime

❑ Windows SharePoint Services 3.0 Tools: Visual Studio Extensions, Version 1.2

❑ Expression Blend

Note that within this book, we’ll assume that you’re running Windows Server 2008. The links to someof the software listed above (where they are free downloads) are in the section ‘‘Additional References’’ atthe end of this chapter.

After you’ve installed each of these, you now have to ensure that your development environment isconfigured for SharePoint and Silverlight integration. To do this, you must do the following:

1. Change the MIME type in Internet Information Services (IIS) to support Silverlightapplications.

2. Change the web.config file in your root SharePoint direction to support Silverlightapplications.

3. Ensure that the System.Web.Silverlight.dll is in your global assembly cache (GAC).

Let’s examine each of these steps.

Changing the MIME TypeYou must add MIME support for Silverlight applications that you build and deploy to your SharePointserver. If you do not, when trying to integrate your Silverlight application with SharePoint, it will notrender properly. To add MIME support for Silverlight applications, do the following:

1. Click Start � Administrative Tools, and then select Internet Information Services (IIS)Manager. This will open IIS.

2. Under Web Sites in the folder structure, click on the web application that represents yourSharePoint site (e.g., SharePoint � –80).

3. In the main IIS window, click ‘‘MIME Types,’’ and then click ‘‘Open Feature.’’

13

Fox c01.tex V3 - 01/30/2009 4:56pm Page 14

Chapter 1: Introduction to Silverlight

4. In the Mime Type view, click Add, add the file-type extension, and type .xap as the ‘‘Filename extension’’ and application/x-silverlight-2 as the ‘‘MIME type’’ (see Figure 1-6).

Figure 1-6

5. Click OK to add the new MIME type to IIS.

Editing the web.config FileA web.config file houses all of the configuration settings that are required by your web application. Bydefault, the web.config file that resides in the root folder of your SharePoint directory does not supportthe rendering of Silverlight applications. Thus, you need to ensure that all of the necessary elements areadded to enable Silverlight support within your SharePoint server.

You can discover what you need to add to the web.config file through a couple of ways. The first is to doa search on the Web and find examples. The second, and easier, way is if you create a new project andselect the option to build the Silverlight application using a web site instead of a dynamic HTML pageas your test environment, the Visual Studio project creates a web.config file for you. If you open this filewithin Visual Studio, you can see all of the necessary elements that need to be added to your SharePoint

14

Fox c01.tex V3 - 01/30/2009 4:56pm Page 15

Chapter 1: Introduction to Silverlight

web.config file. For example, Listing 1-4 shows the web.config file for the example we showed you earlierin this chapter.

Listing 1-4: Sample web.config file generated by Visual Studio

<?xml version="1.0"?>

<configuration><configSections>

<sectionGroup name="system.web.extensions"type="System.Web.Configuration.SystemWebExtensionsSectionGroup,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35">

<sectionGroup name="scripting"type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">

<section name="scriptResourceHandler"type="System.Web.Configuration.ScriptingScriptResourceHandlerSection,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"requirePermission="false" allowDefinition="MachineToApplication"/>

<sectionGroup name="webServices"type="System.Web.Configuration.ScriptingWebServicesSectionGroup,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35">

<section name="jsonSerialization"type="System.Web.Configuration.ScriptingJsonSerializationSection,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35" requirePermission="false"allowDefinition="Everywhere"/>

<section name="profileService"type="System.Web.Configuration.ScriptingProfileServiceSection,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"requirePermission="false" allowDefinition="MachineToApplication"/>

<section name="authenticationService"type="System.Web.Configuration.ScriptingAuthenticationServiceSection,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"requirePermission="false" allowDefinition="MachineToApplication"/>

<section name="roleService"type="System.Web.Configuration.ScriptingRoleServiceSection,System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"requirePermission="false" allowDefinition="MachineToApplication"/>

</sectionGroup></sectionGroup>

</sectionGroup></configSections><appSettings/><connectionStrings/><system.web>

Continued

15

Fox c01.tex V3 - 01/30/2009 4:56pm Page 16

Chapter 1: Introduction to Silverlight

Listing 1-4: Sample web.config file generated by Visual Studio (continued)

<compilation debug="true"><assemblies>

<add assembly="System.Core, Version=3.5.0.0,Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

<add assembly="System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add assembly="System.Data.DataSetExtensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

<add assembly="System.Xml.Linq, Version=3.5.0.0,Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

<add assembly="System.Web.Silverlight, Version=2.0.5.0,Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></assemblies>

</compilation><authentication mode="Windows"/><!--The <customErrors> section enables configurationof what to do if/when an unhandled error occursduring the execution of a request. Specifically,it enables developers to configure html error pagesto be displayed in place of a error stack trace.

<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"><error statusCode="403" redirect="NoAccess.htm" /><error statusCode="404" redirect="FileNotFound.htm" />

</customErrors>-->

<pages><controls>

<add tagPrefix="asp"namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0,Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add tagPrefix="asp" namespace="System.Web.UI.WebControls"assembly="System.Web.Extensions, Version=3.5.0.0,Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

</controls></pages><httpHandlers>

<remove verb="*" path="*.asmx"/><add verb="*" path="*.asmx" validate="false"

type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="*" path="*_AppService.axd" validate="false"type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="GET,HEAD" path="ScriptResource.axd"type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions,Version=3.5.0.0,Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>

</httpHandlers><httpModules>

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule,

16

Fox c01.tex V3 - 01/30/2009 4:56pm Page 17

Chapter 1: Introduction to Silverlight

System.Web.Extensions, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31BF3856AD364E35"/>

</httpModules></system.web><system.codedom>

<compilers><compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"

type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089">

<providerOption name="CompilerVersion" value="v3.5"/><providerOption name="WarnAsError" value="false"/>

</compiler><compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"

warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

<providerOption name="CompilerVersion" value="v3.5"/><providerOption name="OptionInfer" value="true"/><providerOption name="WarnAsError" value="false"/>

</compiler></compilers>

</system.codedom><system.webServer>

<validation validateIntegratedModeConfiguration="false"/><modules>

<remove name="ScriptModule"/><add name="ScriptModule"

preCondition="managedHandler"type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0,Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

</modules><handlers>

<remove name="WebServiceHandlerFactory-Integrated"/><remove name="ScriptHandlerFactory"/><remove name="ScriptHandlerFactoryAppServices"/><remove name="ScriptResource"/><add name="ScriptHandlerFactory" verb="*" path="*.asmx"

preCondition="integratedMode"type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add name="ScriptHandlerFactoryAppServices" verb="*"path="*_AppService.axd" preCondition="integratedMode"type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add name="ScriptResource" preCondition="integratedMode"verb="GET,HEAD" path="ScriptResource.axd"type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

</handlers></system.webServer><runtime>

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly>

<assemblyIdentity

Continued

17

Fox c01.tex V3 - 01/30/2009 4:56pm Page 18

Chapter 1: Introduction to Silverlight

Listing 1-4: Sample web.config file generated by Visual Studio (continued)

name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/><bindingRedirect oldVersion="1.0.0.0-1.1.0.0"

newVersion="3.5.0.0"/></dependentAssembly><dependentAssembly>

<assemblyIdentityname="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>

<bindingRedirect oldVersion="1.0.0.0-1.1.0.0"newVersion="3.5.0.0"/>

</dependentAssembly></assemblyBinding>

</runtime></configuration>

Although this will get you most of the way there toward ensuring that you have the appropriate supportfor your Silverlight applications in SharePoint, one final addition is required: Add the Silverlight applica-tion as a safe control within your SharePoint web.config file. This is often overlooked and can cause someheadaches when trying to troubleshoot Silverlight applications not rendering. For example, the followingline of code shows the SafeControl entry for the Silverlight application discussed earlier in the chapter:

<SafeControl Assembly="SimpleSalary, Version=1.0.0.0, Culture=neutral,PublicKeyToken=9f4da00116c38ec5" Namespace="SimpleSalary"TypeName="SimpleSalaryCalc" Safe="True"/>

After you’ve completed these amendments to the web.config file in your root SharePoint folder, youshould be ready to move to the last step in configuring your environment.

Copying the Silverlight DLL to Your GACThe last step in configuring your server is simple: Make sure that the System.Web.Silverlight.dll existswithin your global assembly cache (GAC). The GAC will typically reside in the root Windows directoryunder the assembly folder. Also, if you’ve previously been using earlier versions of Silverlight, make surethat the version is correct — the DLL is named the same across versions, but Silverlight 2 applicationswon’t render using the Silverlight 1 (or Silverlight Beta 1) DLL. Therefore, delete the old version in yourGAC and then recopy the newer Silverlight 2 DLL to the assembly folder.

Make sure that you’re running as the administrator on the machine, or else you’ll get an ‘‘AccessDenied’’ message. You can get around this by right-clicking on the Visual Studio 2008 tools and run-ning as administrator and then using the gacutil tool to copy files to the GAC. Also, as a general rulewhen using Visual Studio 2008, right-click and select ‘‘Run as Administrator’’; otherwise, you will nothave full access to your machine when building and deploying applications.

At this point, your SharePoint server will be configured to support Silverlight applications and, assumingyou’ve installed all of the applications listed at the beginning of this section, your sandbox environmentwill be ready to go. Before moving on to the next chapter and building your first Silverlight and Share-Point integration, let’s talk a bit about why you would want to integrate SharePoint and Silverlight.

18

Fox c01.tex V3 - 01/30/2009 4:56pm Page 19

Chapter 1: Introduction to Silverlight

Why Silverlight and SharePoint?To return to the beginning of the chapter for a brief minute, we repeat that increasingly, the user expec-tation is to demand a richer user experience when interacting with web-based applications. Furthermore,the demands of these web-based applications go beyond just supporting a single browser technology orplatform — thus the need for Silverlight to support not only a richer, more compelling user experience,but also one that supports the delivery of these applications to multiple platforms, browsers, and audi-ences. In this chapter, you’ve seen a simple Silverlight example, but there are many possibilities whenbuilding Silverlight applications. For example, Figure 1-7 illustrates a Silverlight-enabled web applicationthat allows users to drill into showcase Silverlight examples through an interactive and dynamic map.This is a great example of what Silverlight can do and is available for download off the Silverlight.netweb site — along with many other samples and training.

Figure 1-7

While Silverlight can create some powerful applications, why integrate it with SharePoint? The primaryreasons are twofold:

❑ While there are some great templates that ship with SharePoint, they don’t go all the way to cus-tomize the site in the way that many organizations want, so Silverlight is a natural extension for

19

Fox c01.tex V3 - 01/30/2009 4:56pm Page 20

Chapter 1: Introduction to Silverlight

SharePoint to really take the user experience to the next level while still using the SharePointinfrastructure — especially when building on SharePoint for the wider Web.

❑ As more companies more fully utilize their SharePoint investments (both as intranets andexternally facing web sites), they are looking for tools that can take these sites to the next level.Faced with the same pressures to build richer user experiences for their web-based applications,many companies are using Microsoft Silverlight 2 to reach new user experience levels inSharePoint — thus the importance of the integration between SharePoint and Silverlight.

Beyond these two reasons, Silverlight offers a lot to the developer:

❑ As discussed, it offers a great integration for the designer to work with the developer with richtools’ support for both.

❑ It ships with many supported features such as managed code, .NET Framework 3.5, dynamiclanguages, a rich SDK, data-binding, and more. These are not only great for the aspiring Sil-verlight developer, but for the .NET developer the transition from your current developer skillsis natural because you’re still leveraging many of the core .NET features; you’re just building theapplication for a different delivery mechanism.

❑ As a developer, you’re also more able to rapidly build and deploy self-contained applicationsthat have less ‘‘hookup’’ code than traditional script-based web applications.

❑ There’s also an added layer of security given the fact that you can develop your applicationswith a managed-code environment.

❑ The support network for Silverlight is strong and growing quickly. The attention being paid tothis technology is high, and the technology is very hot. Combining it with SharePoint, whosereach is also very strong, is something you’re going to hear a lot about moving forward.

SummaryIn this chapter, you were introduced to what Silverlight is and answered the question of why (at least ata high level) Silverlight is a great fit for SharePoint — while much of this you’ll determine on your ownthroughout this book. This chapter contained a couple of simple XAML examples to get you familiar withthe declarative language that describes the Silverlight application UI, as well as providing you with theC# and VB code-behind for this simple Silverlight application. That said, you can walk away from thischapter knowing you’ve learned three key things:

❑ XAML is the declarative language that defines the UI for Silverlight applications, and you havedifferent options for building out the code-behind, which include managed code and dynamiclanguages.

❑ Designers and developers have rich tools’ support in not only Visual Studio 2008, but also in theExpression Blend suite of tools to aid in UI design.

❑ Silverlight applications are not difficult to build; however, there is some setup that is requiredwhen setting up your sandbox development environment — this is often the leading cause ofissues with applications not rendering.

In the next chapter, you’ll walk through the creation of your first Silverlight application, so you can beginthinking about how you can begin your own integrations with SharePoint and put what you’ve learnedin this chapter to practice.

20

Fox c01.tex V3 - 01/30/2009 4:56pm Page 21

Chapter 1: Introduction to Silverlight

Additional References2007 Microsoft Office SharePoint Servers Service Pack 1 (SP1): www.microsoft.com/downloads/

details.aspx?FamilyId=AD59175C-AD6A-4027-8C2F-DB25322F791B&displaylang=en.Laurence Moroney, Introducing Silverlight 2 (Microsoft Press, 2008).Patrick Tissegham’s Blog: www.u2u.info/Blogs/Patrick/default.aspx.Silverlight Web Site: www.silverlight.net.Silverlight Beta 2 Runtime: www.silverlight.net.Silverlight Tools Beta 2 for Visual Studio 2008: www.microsoft.com/downloads/details

.aspx?FamilyId=50A9EC01-267B-4521-B7D7-C0DBA8866434&displaylang=en.Windows SharePoint Services 3.0 and Windows SharePoint Services Service Pack 1: www.microsoft

.com/downloads/details.aspx?familyid=4191A531-A2E9-45E4-B71E-5B0B17108BD2&displaylang=en.

Windows SharePoint Services 3.0 Tools: Visual Studio Extensions, Version 1.2: www.microsoft.com/downloads/details.aspx?familyid=7BF65B28-06E2-4E87-9BAD-086E32185E68&displaylang=en.

21

Fox c01.tex V3 - 01/30/2009 4:56pm Page 22

Fox c02.tex V3 - 01/30/2009 4:58pm Page 23

Your First Silverlight andSharePoint Integration

In the last chapter, you saw a simple example of a Silverlight application, which provided anintroduction to the XAML and the code-behind for a basic user form. You also walked throughthe prerequisites for your development environment. At this point, it’s assumed that you’ve gotyour environment up and running and are ready to build your first Silverlight and SharePointintegration.

Different Ways to Integrate with SharePointThere are several different ways in which you can integrate Silverlight applications with SharePoint.You might classify these in three different levels of integration with SharePoint: (1) no touch, (2) lowtouch, and (3) high touch.

The no-touch option is using the Silverlight Streaming media service, where you uploadyour Silverlight application to the service and it acts as the host for you. To do this, go tohttp://silverlight.live.com/, and sign in using your Live ID. After you log in, you’ll haveaccess to your Admin page. If you click ‘‘Manage Applications,’’ you can then upload an existingXAP file to the streaming service. Figure 2-1 illustrates the Admin page for the Silverlight Streamingservice.

After you upload your application, you can then click on that application, and the streamingservice will provide different methods for you to embed a reference to the application in yourweb site. Select the iframe option, copying the code in the code snippet window. All you need to

Fox c02.tex V3 - 01/30/2009 4:58pm Page 24

Chapter 2: Your First Silverlight and SharePoint Integration

do then is add a Content Editor Web Part to your SharePoint site, select ‘‘Edit in Tool Pane,’’ open theSource Editor, and add code from the streaming service, which should look like the following:

<iframesrc="http://silverlight.services.live.com/invoke/75885/Cool_Menu/iframe.html"scrolling="no" frameborder="0" style="width:1000px; height:200px"></iframe>

Figure 2-1

What this code does is host the application inside of a Web Part, but it does not require much of theconfiguration that hosting it locally would require — thus, a no-touch approach to hosting a Silverlightapplication in SharePoint. However, you may not always want to use this approach as you’ll want moredirect integration with the SharePoint site. This necessitates either the low-touch or high-touch approach.

The low-touch and high-touch approaches require some degree of integration with SharePoint. Forexample, some of the more common ways are to:

❑ Use Web Parts as host containers for the Silverlight application.

❑ Alter the master and layout pages to consume Silverlight applications to improve branding orprovide custom navigation.

24

Fox c02.tex V3 - 01/30/2009 4:58pm Page 25

Chapter 2: Your First Silverlight and SharePoint Integration

❑ Use application and site pages as the host container.

❑ Create custom field types to provide custom functionality.

❑ Build skins for lists or other data views to enhance the user interaction with data in SharePoint.

This chapter walks you through how you can use the SharePoint Web Part as a wrapper for your Sil-verlight applications. This is an interesting method (and probably one of the more popular), because itenables you to not only create isolated hosted applications, but also interconnect the Web Parts throughthe native SharePoint provider/consumer model — via service proxies — or via custom services thatyou build. The Silverlight application that you’ll build is a custom media player that allows you to selectwhat video you’d like to play. There are also some additional media controls included in this Silverlightapplication, which allow you to stop, pause, rewind, fast forward, and mute the video.

To build this integration, we’ll walk you through the following:

❑ Creating the Silverlight application

❑ Deploying the Silverlight application

❑ Creating and deploying the SharePoint Web Part

❑ Adding the new Silverlight application to the SharePoint site (which will be hosted inside a WebPart)

After you’ve completed the integration, you’ll be able to launch your SharePoint site, navigate to the pagewhere you’ve added the Web Part that hosts the Silverlight application, and then use the custom videoplayer inside SharePoint.

Let’s get started!

Creating the Silverlight ApplicationSilverlight 2 is quite an evolution from Silverlight 1. For example, Silverlight 2 supports managed code soyou can use Visual Basic and C# to build your applications. Furthermore, Silverlight 2 ships with a set ofcontrols and facilitates the extension of controls to make the job of creating Silverlight-based user controlsmuch easier. You’ll use some of these controls in the Silverlight application to facilitate the managementof the media player.

To begin, do the following:

1. Open Visual Studio 2008 and click File � New � Project.

2. In either of the C# or Visual Basic nodes, you’ll find a new project node called Silverlight (seeFigure 2-2). If you click on it, you’ll also note two project templates: one to create a Silverlightapplication and another to create a Silverlight class library. Click ‘‘Silverlight Application,’’provide a name for it (e.g., MySilverlightApp), and accept the other default options by click-ing OK.

3. After you click OK, you will be prompted to select either the option ‘‘Add a new ASP.NETWeb project to the Solution to host Silverlight’’ or ‘‘Automatically generate an HTML testpage to host Silverlight at build time.’’ Select the first choice, accept the default options, and

25

Fox c02.tex V3 - 01/30/2009 4:58pm Page 26

Chapter 2: Your First Silverlight and SharePoint Integration

click OK. This will create the Silverlight project, which will further be hosted inside of a webapplication (as opposed to just an HTML page — which would have happened if you wouldhave selected the second aforementioned option).

Figure 2-2

Silverlight Solution Project FilesThere are a number of project files that make up the Silverlight solution (see Figure 2-3). For example,you’ll notice that in the ClientBin you have the MySilverlightApp.xap file, the ASPX and HTML testpages, and a web.config file (discussed in Chapter 1). The XAP file is the result of the compile of the Sil-verlight build process and represents an archive of the core and dependency DLLs, deployment manifest,and any dependent files. This is covered a little later on in this chapter.

Figure 2-3

26

Fox c02.tex V3 - 01/30/2009 4:58pm Page 27

Chapter 2: Your First Silverlight and SharePoint Integration

It is worth mentioning that you can use the ASPX and HTML pages to see what the reference code to aSilverlight application looks like. For example, the code sample in Listing 2-1 represents the code-behindin the MySilverlightAppTestPage.aspx page. Note that in the page, you have the directive to register theSilverlight assembly in the top part of the sample code (highlighted), and the reference to the Silverlightcontrol is contained within a DIV along with several properties that are also included (also highlighted).You can use this code when building, for example, master pages in SharePoint because the references toyour XAP file will be very similar to this reference.

Listing 2-1: ASPX test page code-behind

<%@ Page Language="C#" AutoEventWireup="true" %>

<%@ Register Assembly="System.Web.Silverlight"Namespace="System.Web.UI.SilverlightControls"

TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;"><head runat="server">

<title>Test Page For MySilverlightApp</title></head><body style="height:100%;margin:0;">

<form id="form1" runat="server" style="height:100%;"><asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager><div style="height:100%;">

<asp:Silverlight ID="Xaml1" runat="server" Source="∼/ClientBin/MySilverlightApp.xap" MinimumVersion="2.0.31005.0" Width="100%"

Height="100%" /></div>

</form></body></html>

In the MySilverlightApp C# class project, you’ll find a Properties node, in which you’ll find a deploymentmanifest along with an assembly information file; a References node (for all of the referent assemblies);an App.xaml node, which is used for application resources such as styles and data templates; and thenfinally, the Page.xaml node, which is where you build the core UI and code-behind for that UI. Most ofthe chapter is spent discussing the Page.xaml and the corresponding code-behind in the Page.xaml.cs file.

If you open the Page.xaml node, you’ll see that there is a corresponding Page.xaml.cs (or Page.xaml.vb)file. This represents the code-behind that maps to the UI — remember that Chapter 1 discussed how tomap the events to the buttons and radio buttons. These two components of the Silverlight class projectwork hand-in-glove to represent the heart of your Silverlight application.

As you learn Silverlight 2, you’ll see that you can have one Page.xaml.cs file, but you can have multipleXAML files (e.g., ctrlA.xaml, ctrlB.xaml, etc.) that can be managed through the central Page.xaml file.You might do this, for example, if you want to manage separate Silverlight controls in one Page.xamland load different controls depending on the state of an application.

27

Fox c02.tex V3 - 01/30/2009 4:58pm Page 28

Chapter 2: Your First Silverlight and SharePoint Integration

To view the XAML, right-click on the Page.xaml file and click Open. This opens a split Design/XAMLview in Visual Studio 2008. You’ll find some default XAML code that is created automatically for youwhen you create your Silverlight application (see Listing 2-2). In this code, you’ll notice the name-space, which connects the XAML to the code-behind, and the schema references, and some additionalproperties — namely, the width and height. The default user control project creates an empty Gridobject by default; you’ll be replacing this with a Canvas object and then adding additional objects withinthe Canvas.

Listing 2-2: Default XAML code

<UserControl x:Class="MySilverlightApp.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="400" Height="300"><Grid x:Name="LayoutRoot" Background="White">

</Grid></UserControl>

Open the Toolbox, and inspect the different types of controls available for you to add to the project.

In Visual Studio, you can drag-and-drop the controls from the Toolbox to the XAML view, not the actualdesigner.

The UI that you created was fairly simple; this was deliberate to illustrate the fundamental aspects ofintegration as opposed to getting too complicated a UI design so early in the book. We did, however,include some additional texturing of the controls, such as gradients, so you can see how this might bedone.

Listing 2-3 includes the XAML code that represents the UI for the sample Silverlight application. Thissample UI uses the Canvas object, and several other objects are nested within the Canvas, includinganother canvas. Figure 2-4 illustrates how the objects are nested in the Silverlight application UI.

Controls

Formatting

MediaElement

Inner Canvas

Outer Canvas

UserControl

Figure 2-4

28

Fox c02.tex V3 - 01/30/2009 4:58pm Page 29

Chapter 2: Your First Silverlight and SharePoint Integration

You can find a high-level description of the nested structure of the UI in the following table:

IU Element Description

Canvas: Outer The container for our controls

Canvas: Inner The container for the formatting of the media viewer backdrop

MediaElement Hosts the video.

Number of Rectangle objects Provides the formatting objects for the Silverlight UI.

User controls Controls added to provide functionality for the user to interactwith the video player. The controls include radio buttons, textblocks, and buttons.

You’ll note that the inner Canvas was used to host only the MediaElement and the formatting objects forthe UI. The user controls were added to the outer Canvas. This was by design to show you how you canlayer objects within a Canvas (using the ZIndex property).

For each of the objects added to the XAML-based UI, there are also set properties for each of the elements.For example, all elements have an x:Name property (used to map to events in the code-behind); many ofthe objects use the Canvas.Left and Canvas.Top properties to specifically position them on the Canvas;a width and height property are specified; and the rectangles have gradients to provide richer graphicalformatting. The full sample code is shown in Listing 2-3

Listing 2-3: Sample application XAML

<UserControl x:Class="MySilverlightApp.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="756" Height="700"><Canvas Width="754" Height="534" Canvas.Left="3" Canvas.Top="40"

x:Name="mainMediaPlayerInterface">

<Canvas x:Name="mediaPlayerView"Width="682"Height="316"Canvas.Left="52"Canvas.Top="28">

<MediaElement x:Name="moviePlayer"Canvas.Left="-56"Height="300"Width="750"Margin="5"Canvas.ZIndex="10">

</MediaElement>

<Rectangle Stroke="#66000000"RadiusX="3"RadiusY="3"

Continued

29

Fox c02.tex V3 - 01/30/2009 4:58pm Page 30

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-3: Sample application XAML (continued)

x:Name="mediaPlayerBadrop1"Width="646"Height="311"Canvas.Top="10"Canvas.ZIndex="1">

<Rectangle.Fill>

<LinearGradientBrush EndPoint="0.5,0.9"StartPoint="0.5,0.3">

<GradientStop Color="#FF2A2A2A" Offset="0.995"/><GradientStop Color="#FF636363" Offset="0"/><GradientStop Color="#FF000000" Offset="0.913"/><GradientStop Color="#FF0E0E0E" Offset="0.399"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle Stroke="#99000000"RadiusX="3"RadiusY="3"x:Name="mediaPlayerBackdrop2"Width="691"Height="268"Opacity="1"Canvas.Left="-22"Canvas.Top="19"Canvas.ZIndex="2">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.5,0.3"

StartPoint="0.5,-0.02"><GradientStop Color="#FF151414" Offset="1"/><GradientStop Color="#FF4E4E4E" Offset="0"/><GradientStop Color="#FF000000" Offset="0.913"/><GradientStop Color="#FF0E0E0E" Offset="0.399"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle RadiusX="2.304"RadiusY="2.304"x:Name="mediaPlayerBackdrop3"Width="686"Height="15.497"Canvas.Left="-20.419"Canvas.Top="20.506"Canvas.ZIndex="3">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.5,0.6"

StartPoint="0.5,-0.02"><GradientStop Color="#00FFFFFF" Offset="1"/><GradientStop Color="#9BFFFFFF" Offset="0.024"/>

30

Fox c02.tex V3 - 01/30/2009 4:58pm Page 31

Chapter 2: Your First Silverlight and SharePoint Integration

<GradientStop Color="#0AFFFFFF" Offset="0.514"/><GradientStop Color="#48FFFFFF" Offset="0.303"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle Stroke="#99000000"RadiusX="3"RadiusY="3"x:Name="videoBox_Copy"Width="30"Height="299"Canvas.ZIndex="4">

<Rectangle.Fill><LinearGradientBrush EndPoint="2.064,1.01"

StartPoint="-0.348,0.007"><GradientStop Color="#FF363636" Offset="0.99"/><GradientStop Color="#FF848484" Offset="0.005"/><GradientStop Color="#FF000000" Offset="0.591"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle RadiusX="2.441"RadiusY="2.441"x:Name="mediaPlayerBackdrop4"Width="25.044"Height="293.589"Canvas.Left="2.328"Canvas.Top="2.352"Canvas.ZIndex="5">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.402,0.989"

StartPoint="0.42,0.018"><GradientStop Color="#72000000" Offset="0"/><GradientStop Color="#A2000000" Offset="1"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle Stroke="#99000000"RadiusX="3"RadiusY="3"x:Name="mediaPlayerBackdrop5"Width="29.646"Height="298.519"Canvas.ZIndex="6">

<Rectangle.Fill><LinearGradientBrush EndPoint="2,1"

StartPoint="-0.35,0.01"><GradientStop Color="#FF363636" Offset="0.99"/><GradientStop Color="#FF848484" Offset="0.005"/><GradientStop Color="#FF000000" Offset="0.591"/>

</LinearGradientBrush>

Continued

31

Fox c02.tex V3 - 01/30/2009 4:58pm Page 32

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-3: Sample application XAML (continued)

</Rectangle.Fill></Rectangle>

<Rectangle RadiusX="2.441"RadiusY="2.441"x:Name="cover1"Width="25.044"Height="293.589"Canvas.Left="2.328"Canvas.Top="2.352"Canvas.ZIndex="7">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.402,0.989"

StartPoint="0.42,0.018"><GradientStop Color="#72000000" Offset="0"/><GradientStop Color="#A2000000" Offset="1"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle RadiusX="3"RadiusY="3"x:Name="videoBox"Width="646"Height="311"Opacity="1"Stroke="#7F000000"Canvas.ZIndex="8">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.508,0.997"

StartPoint="0.508,0.026"><GradientStop Color="#FF343434" Offset="1"/><GradientStop Color="#FF636363" Offset="0"/><GradientStop Color="#FF000000" Offset="0.928"/><GradientStop Color="#FF0E0E0E" Offset="0.399"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

<Rectangle Opacity="0.7"Stroke="#FF000000"RadiusX="0"RadiusY="0"x:Name="videoFrame"Width="640"Height="272"Canvas.Left="3"Canvas.Top="3"Fill="#FF000000"Canvas.ZIndex="9">

</Rectangle>

32

Fox c02.tex V3 - 01/30/2009 4:58pm Page 33

Chapter 2: Your First Silverlight and SharePoint Integration

</Canvas>

<!-- Controls for the media player. --><Rectangle Height="220" Width="608" Canvas.Left="69"

Canvas.Top="370" Stroke="#FF000000"><Rectangle.Fill>

<LinearGradientBrush EndPoint="0.508,0.997"StartPoint="0.508,0.026">

<GradientStop Color="#FF343434" Offset="1"/><GradientStop Color="#FF636363" Offset="0"/><GradientStop Color="#FF000000" Offset="0.928"/><GradientStop Color="#FF0E0E0E" Offset="0.399"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle><ToggleButton x:Name="btnMute"

Height="29"Width="85"Canvas.Left="139"Canvas.Top="532"Content="Mute"

Click="btnMute_Click"/><Button x:Name="btnRewind"

Height="29"Width="85" Content="<<"Canvas.Left="231"Canvas.Top="532"

Click="btnRewind_Click"/><ToggleButton x:Name="btnPlay"

Height="29"Width="85"Content=">"Canvas.Left="323"Canvas.Top="532"

Click="btnPlay_Click"/><ToggleButton x:Name="btnPause"

Height="29"Width="85"Content="||"Canvas.Left="416"Canvas.Top="532"

Click="btnPause_Click"/><Button x:Name="btnFastForward"

Height="29"Width="85"Content=">>"Canvas.Left="509"Canvas.Top="532"

Click="btnFastForward_Click"/><RadioButton x:Name="rdiobtnBear"

Height="20"Width="151"Canvas.Left="139"Canvas.Top="406"Content="Hungry Bear"

Continued

33

Fox c02.tex V3 - 01/30/2009 4:58pm Page 34

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-3: Sample application XAML (continued)

Foreground="#FFFBF5F5"Checked="rdiobtnBear_Checked"/>

<RadioButton x:Name="rdiobtnButterfly"Height="20"Width="151"Foreground="#FFFBF5F5"Content="Fluttering Butterfly"Canvas.Left="139"Canvas.Top="438"Checked="rdiobtnButterfly_Checked"/>

<RadioButton Height="20"x:Name="rdiobtnLake"Width="151"Foreground="#FFFBF5F5"Content="Calm Lake"Canvas.Left="139"Canvas.Top="471"Checked="rdiobtnLake_Checked"/>

<TextBlock x:Name="txtblckVideos"Height="26"Width="237"Canvas.Left="102"Canvas.Top="373"Text="Available Videos"TextWrapping="Wrap"Foreground="#FFFCF5F5"/>

<TextBlock x:Name="txtblckDescription"Height="26"Width="237"Foreground="#FFFCF5F5"Text="Description"TextWrapping="Wrap"Canvas.Left="323"Canvas.Top="373"/>

<TextBlock x:Name="txtblckFullDescription"Height="94"Width="286"Canvas.Left="323"Canvas.Top="406"Text=""Foreground="#FFFCF5F5"TextWrapping="Wrap"/>

<Rectangle Height="26" Width="4" Canvas.Left="69" Canvas.Top="341"Stroke="#FF000000" RenderTransformOrigin="0.5,0.5">

<Rectangle.Fill><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

<GradientStop Color="#FF000000"/><GradientStop Color="#FF9C8E8E" Offset="1"/>

</LinearGradientBrush></Rectangle.Fill><Rectangle.RenderTransform>

<TransformGroup><ScaleTransform ScaleX="-1"/><SkewTransform/>

34

Fox c02.tex V3 - 01/30/2009 4:58pm Page 35

Chapter 2: Your First Silverlight and SharePoint Integration

<RotateTransform/><TranslateTransform/>

</TransformGroup></Rectangle.RenderTransform>

</Rectangle><Rectangle Height="26" Width="4" RenderTransformOrigin="0.5,0.5"

Stroke="#FF000000" Canvas.Left="673" Canvas.Top="341"><Rectangle.RenderTransform>

<TransformGroup><ScaleTransform ScaleX="-1"/><SkewTransform/><RotateTransform/><TranslateTransform/>

</TransformGroup></Rectangle.RenderTransform><Rectangle.Fill>

<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#FF000000"/><GradientStop Color="#FF9C8E8E" Offset="1"/>

</LinearGradientBrush></Rectangle.Fill>

</Rectangle>

</Canvas>

</UserControl>

In Listing 2-3, you’ll also notice several event handlers that are associated with the user controls withinthe UI. Specifically, the event handlers map to the controls in the way shown in the following table:

Control Event

Mute toggle button (btnMute) btnMute_Click

Rewind button (btnRewind) btnRewind_Click

Play toggle button (btnPlay) btnPlay_Click

Pause toggle button (btnPause) btnPause_Click

Fast Forward button (btnFastForward) btnFastForward_Click

Bear Video radio button (rdiobtnBear) rdiobtnBear_Checked

Butterfly Video radio button (rdiobtnButterfly) rdiobtnButterfly_Checked

Lake Video radio button (rdiobtnLake) rdiobtnLake_Checked

The click events correspond to the controls that manage the videos and video player, and the radiobuttons correspond to the user selections for the video that they’d like to see played.

When creating the event handlers within the Page.xaml file, for each of the event handlers (e.g.,Click="btnMute_Click"), if you type Click and then use Visual Studio IntelliSense to add theevent handlers, Visual Studio will automatically add the stub methods for your event handlers in thePage.xaml.cs file — as opposed to cutting and pasting code where Visual Studio will not auto-generateevent handlers.

35

Fox c02.tex V3 - 01/30/2009 4:58pm Page 36

Chapter 2: Your First Silverlight and SharePoint Integration

Before moving on to the code-behind, let’s take a quick look at the Expression Blend view of this samecode. Although we are not professional designers, we did all of the coding within the ExpressionBlend tool. We did this by opening the Page.xaml file in Expression Blend after we created theoriginal Silverlight project in Visual Studio. To view the project in Expression Blend, right-click on thePage.xaml file and select ‘‘Open in Expression Blend.’’ Expression Blend will ask you to accept a securityprompt — ‘‘The project (or solution) you are trying to open could present a security risk. Do you wantto open the project anyway?’’ — so click Yes to open the project in Expression Blend. At this point, youcan add items to the designer in Expression Blend, save the file, and then switch back to Visual Studio2008, which will prompt you to reload the changes from Expression Blend into your Visual Studio 2008project. Figure 2-5 illustrates the view of the custom media player in Expression Blend.

Figure 2-5

The nice thing about editing the XAML in Expression Blend is that even though we’re not designers, wewere still able to create a decent-looking UI. With practice, you’ll certainly exceed what we’ve done hereto create your own custom application UI. Furthermore, you can toggle back and forth across ExpressionBlend and Visual Studio to see your changes reflected in real time.

Now that we’ve discussed the XAML portion of this Silverlight application, let’s move on to thecode-behind.

36

Fox c02.tex V3 - 01/30/2009 4:58pm Page 37

Chapter 2: Your First Silverlight and SharePoint Integration

Creating the Silverlight Application Code-BehindTo add code-behind for the Silverlight application, right-click on the Page.xaml file in SolutionExplorer, and click ‘‘View Code.’’ You can also expand the Page.xaml node, right-click on thePage.xaml.cs file, and select ‘‘View Code.’’ The code in this view is that which corresponds to the UIbuilt earlier — this is where you will see the specific events that correspond to the controls added tothe Silverlight application UI. The code added to the Page.xaml.cs file is shown in Listing 2-4 (C#) andListing 2-5 (VB).

If you added the event handlers using IntelliSense, Visual Studio will have already added the stubbedmethods for you in the Page.xaml.cs file.

Previously in this chapter, the methods within the code-behind were enumerated as they correspondedto the controls within the Silverlight UI. In the code sample, you can see the specifics behind each of thesemethods. Before the discussion turns to the methods, though, let’s look at the class-level variables thatyou’ll create in this sample.

There are several variables created for this application, which are listed as follows:

string currentVideo = "";string baseURI = "http://stefox-t61p/Videos/";string vidSuffix = ".wmv";

The first variable, currentVideo, represents a class-level variable that holds the selection of the video(provided in the application by the radio button selection). Also, within this application, you’ll concate-nate a string that represents the location of the video, and the string variables baseURI and vidSuffixwill be used as a part of this concatenation. You’ll also notice that an HTTP reference has been used(which points to a SharePoint site) as the base URL location for the videos. You want to have all of yourvideos located on the same SharePoint site to which you’re deploying the Silverlight application. To addyour videos, create a new document library by clicking ‘‘View All Site Content and Create in SharePoint,’’selecting Picture Library, providing a name (e.g., Videos), and clicking OK. In a production environment,you would not have all of your videos on a SharePoint server; you’d have a separate media server thatwould act as a streaming server to host and manage the video files. Given that these videos are so small,however, the sample application uses SharePoint as the host for the videos.

There are also four TimeSpan objects that you’ll create, which are listed as follows:

TimeSpan movieStartingPoint = new TimeSpan(0, 0, 0, 0, 0);TimeSpan endOfBearMovie = new TimeSpan(0, 0, 0, 12, 0);TimeSpan endOfButterflyMovie = new TimeSpan(0, 0, 0, 9, 0);TimeSpan endOfLakeMovie = new TimeSpan(0, 0, 0, 10, 0);

These are used in the rewind and fast-forward functionality for each of the movies. Because the startingpoint is always the same across all of the movies, there is only one starting-point TimeSpan object(movieStartingPoint); however, each of the movies has a different length, so different overloadswere required within each of the three endpoints (endOfBearMovie, endOfButterflyMovie, andendOfLakeMovie) in the videos.

The overloads in order are days, hours, minutes, seconds, and milliseconds.

37

Fox c02.tex V3 - 01/30/2009 4:58pm Page 38

Chapter 2: Your First Silverlight and SharePoint Integration

For each of the checked options for the radio buttons, the application sets the currentVideo stringvariable and then sets the text property of the text-block description in your application UI. ThecurrentVideo string is then used when concatenating the video URL in the btnPlay_Click event.

The TimeSpan objects are as follows:

❑ Mute Button — When the user clicks the Mute button, the Silverlight application calls thebtnMute_Click event, which sets the IsMuted property. Setting the IsMuted property to truemutes the video, and setting it to false ‘‘un-mutes’’ the video. Because the Mute button is atoggle button, you set a condition based on the checked property and then set the IsMutedproperty accordingly.

❑ Rewind and Fast Forward Buttons — When the user clicks on the Rewind or Fast Forward but-ton, the application moves the movie either to the beginning or the end of the video. This iswhere the TimeSpan objects come into play. You can also add a check to see if the video is play-ing and then pause it if it is. For the baseline repositioning of the video to work, this check isoptional.

❑ Play Button — When you click on the Play button, you’re again using the toggle button soyou can use the checked property to either play or stop the video. Note that we’re setting theSource property of the MediaElement by concatenating three strings (baseURI, currentVideo,and vidSuffix). The media player then uses this URL to look up and play the selected video.Note that if your Silverlight application cannot find the video, you will get a Network Errorexception — a generic error that means a resource could not be loaded by your Silverlightapplication. Also note that when stopping the video, it then returns to the beginning position ofthe video.

❑ Pause Button — This is similar to the other toggle-button events; it checks the state of the buttonand then pauses or plays the video. The pause function stops the video at its current position, sowhen the Play method is called, the video begins playing where it left off.

Listing 2-4 shows what was just discussed as a full code sample. As discussed, when this code runs,the controls on the Silverlight application will manage the playing, stopping, muting, rewinding, andfast-forwarding of the selected video.

Listing 2-4: Sample application code-behind

C#using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.Windows.Controls.Primitives;

namespace MySilverlightApp

38

Fox c02.tex V3 - 01/30/2009 4:58pm Page 39

Chapter 2: Your First Silverlight and SharePoint Integration

{public partial class Page : UserControl{

//String variables used to create source URL for playing video.string currentVideo = "";

string baseURI = "http://stefox-t61p/Videos/";

string vidSuffix = ".wmv";

//TimeSpan objects provide start and end points for videos,//which are used for rewind and fast-forward functionality.

TimeSpan movieStartingPoint = new TimeSpan(0, 0, 0, 0, 0);TimeSpan endOfBearMovie = new TimeSpan(0, 0, 0, 12, 0);TimeSpan endOfButterflyMovie = new TimeSpan(0, 0, 0, 9, 0);TimeSpan endOfLakeMovie = new TimeSpan(0, 0, 0, 10, 0);

public Page(){

InitializeComponent();}

//Radio button checked events set the currentVideo string and then//display descriptive text about the video that is playing.

private void rdiobtnBear_Checked(object sender, RoutedEventArgs e){

currentVideo = "Bear";txtblckFullDescription.Text =

"A video about a bear hanging out in the water.";}

private void rdiobtnButterfly_Checked(object sender, RoutedEventArgs e){

currentVideo = "Butterfly";txtblckFullDescription.Text = "A butterfly checking out a flower.";

}

private void rdiobtnLake_Checked(object sender, RoutedEventArgs e){

currentVideo = "Lake";txtblckFullDescription.Text =

"A calm lake with mountains in the distance.";}

//This event mutes and un-mutes the current video. It also//changes the text displayed in the button.

private void btnMute_Click(object sender, RoutedEventArgs e){

if (btnMute.IsChecked == true){

btnMute.Content = "Unmute";this.moviePlayer.IsMuted = true;

}else if (btnMute.IsChecked == false){

btnMute.Content = "Mute";

Continued

39

Fox c02.tex V3 - 01/30/2009 4:58pm Page 40

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-4: Sample application code-behind (continued)

this.moviePlayer.IsMuted = false;}

}//Using one of the TimeSpan objects, this event rewinds the video//to the beginning of the video.

private void btnRewind_Click(object sender, RoutedEventArgs e){

this.moviePlayer.Position = movieStartingPoint;if (this.moviePlayer.CurrentState == MediaElementState.Playing){

this.btnPlay.IsChecked = true;this.btnPlay.Content = ">";this.moviePlayer.Pause();

}}

//This event plays and stops the video. It concatenates the class-//level variables to set the Source property for the video.//Also sets the text displayed in the button.

private void btnPlay_Click(object sender, RoutedEventArgs e){

if (btnPlay.IsChecked == true){

this.moviePlayer.Source =new Uri(baseURI + currentVideo + vidSuffix);

btnPlay.Content = "Stop";this.moviePlayer.Play();

}else if (btnPlay.IsChecked == false){

btnPlay.Content = ">";this.moviePlayer.Stop();

}}

//This event pauses the video and sets the text displayed in //the button.private void btnPause_Click(object sender, RoutedEventArgs e){

if (btnPause.IsChecked == true){

btnPause.Content = "||";this.moviePlayer.Pause();

}else if (btnPause.IsChecked == false){

btnPause.Content = ">";this.moviePlayer.Play();

}}

//This event, based on the currently selected video, fast-forwards//to a specific location in the video and changes the text//displayed in the button.

private void btnFastForward_Click(object sender, RoutedEventArgs e){

40

Fox c02.tex V3 - 01/30/2009 4:58pm Page 41

Chapter 2: Your First Silverlight and SharePoint Integration

if (currentVideo == "Bear"){

this.moviePlayer.Position = endOfBearMovie;if (this.moviePlayer.CurrentState == MediaElementState.Playing){

this.btnPlay.IsChecked = true;this.btnPlay.Content = ">";this.moviePlayer.Pause();

}}else if (currentVideo == "Butterfly"){

this.moviePlayer.Position = endOfButterflyMovie;if (this.moviePlayer.CurrentState == MediaElementState.Playing){

this.btnPlay.IsChecked = true;this.btnPlay.Content = ">";this.moviePlayer.Pause();

}}else if (currentVideo == "Lake"){

this.moviePlayer.Position = endOfLakeMovie;if (this.moviePlayer.CurrentState == MediaElementState.Playing){

this.btnPlay.IsChecked = true;this.btnPlay.Content = ">";this.moviePlayer.Pause();

}}

}

}}

VBImports SystemImports System.TimeSpanImports System.Collections.GenericImports System.LinqImports System.NetImports System.WindowsImports System.Windows.ControlsImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.AnimationImports System.Windows.ShapesImports System.Windows.Controls.Primitives

Partial Public Class Page

Continued

41

Fox c02.tex V3 - 01/30/2009 4:58pm Page 42

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-4: Sample application code-behind (continued)

Inherits UserControl

‘String variables used to create source URL for playing video.Dim currentVideo As String = ""Dim baseURI As String = "http://stefox-t61p/Videos/"Dim vidSuffix As String = ".wmv"

‘TimeSpan objects provide start and end points for videos,‘which are used for rewind and fast-forward functionality.Dim movieStartingPoint As TimeSpan = New TimeSpan(0, 0, 0, 0, 0)Dim endOfBearMovie As TimeSpan = New TimeSpan(0, 0, 0, 12, 0)Dim endOfButterflyMovie As TimeSpan = New TimeSpan(0, 0, 0, 9, 0)Dim endOfLakeMovie As TimeSpan = New TimeSpan(0, 0, 0, 10, 0)

Public Sub New()InitializeComponent()

End Sub

‘Radio button checked events set the currentVideo string and then‘display descriptive text about the video that is playing.

Private Sub rdiobtnBear_Checked(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

currentVideo = "Bear"txtblckFullDescription.Text =

"A video about a bear hanging out in the water."

End Sub

Private Sub rdiobtnButterfly_Checked(ByVal sender As _System.Object, ByVal e As System.Windows.RoutedEventArgs)

currentVideo = "Butterfly"txtblckFullDescription.Text = "A butterfly checking out a flower."

End SubPrivate Sub rdiobtnLake_Checked(ByVal sender As System.Object, _

ByVal e As System.Windows.RoutedEventArgs)currentVideo = "Lake"txtblckFullDescription.Text = "A calm lake with mountains in the distance."

End Sub

’This event mutes and un-mutes the current video. It also’changes the text displayed in the button.

Private Sub btnMute_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

If (btnMute.IsChecked = True) ThenbtnMute.Content = "Unmute"moviePlayer.IsMuted = True

42

Fox c02.tex V3 - 01/30/2009 4:58pm Page 43

Chapter 2: Your First Silverlight and SharePoint Integration

ElseIf (btnMute.IsChecked = False) ThenbtnMute.Content = "Mute"moviePlayer.IsMuted = False

End If

End Sub

’Using one of the TimeSpan objects, this event rewinds the video’to the beginning of the video.

Private Sub btnRewind_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

moviePlayer.Position = movieStartingPoint

If (moviePlayer.CurrentState = MediaElementState.Playing) ThenbtnPlay.IsChecked = TruebtnPlay.Content = ">"moviePlayer.Pause()

End If

End Sub

’This event plays and stops the video. It concatenates the class-’level variables to set the Source property for the video.’Also sets the text displayed in the button.

Private Sub btnPlay_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

If (btnPlay.IsChecked = True) ThenmoviePlayer.Source = New Uri(baseURI + currentVideo + vidSuffix)btnPlay.Content = "Stop"moviePlayer.Play()

ElseIf (btnPlay.IsChecked = False) Then

btnPlay.Content = ">"moviePlayer.Stop()

End If

End Sub

’This event pauses the video and sets the text displayed in’the button.

Private Sub btnPause_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

If (btnPause.IsChecked = True) Then

btnPause.Content = "||"

Continued

43

Fox c02.tex V3 - 01/30/2009 4:58pm Page 44

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-4: Sample application code-behind (continued)

moviePlayer.Pause()

ElseIf (btnPause.IsChecked = False) Then

btnPause.Content = ">"moviePlayer.Play()

End If

End Sub

‘This event, based on the currently selected video, fast-forwards’to a specific location in the video and changes the text’displayed in the button.

Private Sub btnFastForward_Click(ByVal sender As System.Object, _ByVal e As System.Windows.RoutedEventArgs)

If (currentVideo = "Bear") ThenmoviePlayer.Position = endOfBearMovieIf (moviePlayer.CurrentState = MediaElementState.Playing) Then

btnPlay.IsChecked = TruebtnPlay.Content = ">"moviePlayer.Pause()

End If

ElseIf (currentVideo = "Butterfly") Then

moviePlayer.Position = endOfButterflyMovieIf (moviePlayer.CurrentState = MediaElementState.Playing) Then

btnPlay.IsChecked = TruebtnPlay.Content = ">"moviePlayer.Pause()

End If

ElseIf (currentVideo = "Lake") Then

moviePlayer.Position = endOfLakeMovieIf (moviePlayer.CurrentState = MediaElementState.Playing) Then

btnPlay.IsChecked = TruebtnPlay.Content = ">"moviePlayer.Pause()

End If

End If

End Sub

End Class

A couple of notes on the code are as follows:

❑ Three short WMV files that ship with Vista as sample videos were used. You can use thesevideos, or you can use your own. If you use your own, you need to change some of the sample

44

Fox c02.tex V3 - 01/30/2009 4:58pm Page 45

Chapter 2: Your First Silverlight and SharePoint Integration

code to ensure that it works properly to load the videos. For example, when the applicationconcatenates the class-level variables and sets the Source property, you’d need to make surethat the name of your video is correctly set as the currentVideo selection.

❑ All the videos were added to a SharePoint site, so this application does not dynamically generatea SharePoint server URL. Therefore, you’ll need to change the location of the baseURI to matchwhere you’ve put your videos.

❑ All of the code was executed within the same web application domain. As you’ll see later in thebook, you may sometimes need to use a cross-domain access policy file when services are callinginto the SharePoint site. This was not the case for this application.

Once you’ve got your videos loaded and the class-level variables adjusted for your ownenvironment — that is, pointing to the location of your own videos (as we could not distributethe bear, butterfly, and lake, the videos and file locations will very likely be different from yours) — youcan debug the Silverlight application by pressing [F5] on your keyboard or clicking Debug and ‘‘StartDebugging’’ from the Visual Studio project menu. This will invoke your default browser and then loadthe Silverlight application. You may see a warning that debugging is not enabled. Click OK to haveVisual Studio modify the web.config file to enable debugging. If everything is working correctly, thecustom media player will load. You will need to select one of the videos by clicking on one of the radiobuttons and then clicking Play. This will then run the videos. Test out the other user controls to ensurethat they’re also working properly.

You have a couple of options when loading resources into a Silverlight application. You can refer to themfrom another location, or you can add a folder into your Visual Studio solution and then add the videosas resources in that folder. You might find it easier to simply add and deploy any resources you use (e.g.,images or videos) using this method, as all of your assets are then self-contained and deployed with theSilverlight application.

While the Silverlight application is now working, you need to make sure you complete one step beforemoving on to the integration with SharePoint. This step is ensuring that the XAP file, the zipped archivethat contains your built Silverlight application, is located where the SharePoint Web Part can pick it upand load it.

The XAP file contains all of the core application files for your Silverlight application. Because the XAPfile is essentially a zipped archive of the built project files, you can append the XAP file with a .zipextension and then open it up to see the files that are contained within the XAP ‘‘package.’’ For example,in Figure 2-6, the resulting MySilverlightApp.xap file is renamed to MySilverlightApp.xap.zip, and thenthe archive is opened up to reveal two files, the core DLL for the project (MyFirstSilverlightApp.dll) andan AppManifest.xaml file. If there were other dependent DLLs or resource files that you needed, thesewould also be listed here.

The AppManifest.xaml file is generated and lists any dependencies from your project.

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"EntryPointAssembly="MySilverlightApp" EntryPointType="MySilverlightApp.App"RuntimeVersion="2.0.30523.6">

<Deployment.Parts><AssemblyPart x:Name="MySilverlightApp" Source="MySilverlightApp.dll" />

</Deployment.Parts></Deployment>

45

Fox c02.tex V3 - 01/30/2009 4:58pm Page 46

Chapter 2: Your First Silverlight and SharePoint Integration

Figure 2-6

Listing 2-5 illustrates the contents of the AppManifest.xaml file from the sample Silverlight applicationin this chapter. It contains key references specific to the deployment of the Silverlight application. Forexample, it shows the name of the assembly (MySilverlightApp) and the Silverlight runtime version usedto compile the application (2.0.31005.0), and then lists out the required assembly (MySilverlightApp.dll),which is also contained within the XAP archive.

Listing 2-5: AppManifest.xml file<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"EntryPointAssembly="MySilverlightApp"EntryPointType="MySilverlightApp.App" RuntimeVersion="2.0.31005.0">

<Deployment.Parts><AssemblyPart x:Name="MySilverlightApp" Source="MySilverlightApp.dll" />

</Deployment.Parts></Deployment>

Now back to the step you need to finish (after you rename your zip file back to XAP!): You need to makesure that the XAP file is copied to a location within your SharePoint site. To do this:

1. Create a new document library in SharePoint by clicking ‘‘View All Site Content in Share-Point’’ and then clicking Create and then ‘‘Document Library.’’

2. Provide a name for the document library and then click OK.

3. You then upload the XAP file to your new directory by opening the document library, click-ing Upload, and browsing to the XAP file.

4. You also need to make sure that when you update and recompile your Silverlight applica-tion, you don’t forget to copy the most recent XAP file into this directory.

5. After you’ve copied your XAP file to a location on your server, you’re now ready to move onto creating the SharePoint Web Part host container for your Silverlight application.

46

Fox c02.tex V3 - 01/30/2009 4:58pm Page 47

Chapter 2: Your First Silverlight and SharePoint Integration

You don’t necessarily need to create a document library folder to house your XAP files. You can create aClientBin folder in the root directory of your SharePoint site, or you can put the XAP file in the _layoutsfolder of your SharePoint site. These other methods will be discussed later in the book.

Creating and Deploying the SharePoint WebPart Host Container

Now that you’ve created the Silverlight application, the next thing that needs to be done is to create thehost object within SharePoint, that is, the object that will host the Silverlight application. What you’lldo in this part of the chapter is take the low-touch approach — create a Web Part and then provide areference to the Silverlight application you created earlier in the chapter — and then deploy the Web Partproject to the SharePoint site.

Creating the Web Part ProjectTo create the Web Part project:

1. Open Visual Studio, click File � New � Project � SharePoint, and select the Web Part projecttemplate (see Figure 2-7). Provide a name for your project (e.g., MySLAppWebPart), and thenclick OK.

Figure 2-7

2. After you create your project, the default name for your Web Part and the default projectshell contains a Web Part called WebPart1, which is a folder with some files that are requiredby SharePoint. You could keep this one or delete this folder and add a new Web Part with

47

Fox c02.tex V3 - 01/30/2009 4:58pm Page 48

Chapter 2: Your First Silverlight and SharePoint Integration

the name you want (e.g., MySLWebPart). To do this, right-click on the existing Web Part(WebPart1) and select Delete.

3. Next click on the WSP tab, and delete everything under WebPart1WebPart.

4. If the WSP view (the view of the Web Part package as it will be deployed to SharePoint) isnot displayed, from the main Visual Studio menu, click View � Other Windows, and selectWSP View. The reason that this is mentioned is that you will likely want a name for yourproject and Web Part more descriptive than WebPart1.

5. After confirming the deletion of the Web Part, right-click on the project in Solution Explorer,and then select Add and New Item. In the Add New Item dialog, select the SharePointproject category and then select the Web Part item template. Provide a more intuitive namefor the Web Part (see Figure 2-8).

Figure 2-8

Adding References to the ProjectAfter you’ve added your new Web Part, you’ll need to add two references to the project before you canadd code. The first is the System.Web.Extensions DLL, and the second is the System.Web.Silverlight DLL.To add these references to your project:

1. Right-click ‘‘References’’ in Solution Explorer, select Add Reference, and in the .NET tabselect the two aforementioned DLLs and click OK. At this point, you’ll now complete twosteps:

1a. Add some code to the Web Part project file.

1b. Ensure that you set the deployment server to the appropriate SharePoint site.

2. To add code to the Web Part, right-click on the Web Part code file (e.g., MySLAppWeb-Part.cs), and click ‘‘View Code.’’

48

Fox c02.tex V3 - 01/30/2009 4:58pm Page 49

Chapter 2: Your First Silverlight and SharePoint Integration

Using System;using System.Runtime.InteropServices;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Serialization;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;using Microsoft.SharePoint.WebPartPages;

namespace MySLAppWPCS{

[Guid("f73f119d-684b-4052-b1b7-72f1d981911e")]public class MySLAppWebPart : System.Web.UI.WebControls.WebParts.WebPart{

public MySLAppWebPart(){}

protected override void OnLoad(EventArgs e){

base.OnLoad(e);

ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);if (scriptManager == null){

scriptManager = new ScriptManager();this.Controls.Add(scriptManager);

}}

}}

Listing 2-6 shows the code that we have added to the Web Part project. In the code, there are two keyitems to call out:

❑ The first is the fact that you’re using the ScriptManager object to render the Silverlight applica-tion. This is because a ScriptManager control is required to load a Silverlight control on a webpage, so an instance of the ScriptManager object needs to first be added to the project. In all like-lihood, SharePoint will have an instance of the ScriptManager object running, thus the need tocheck first.

❑ The second is the instantiation of the Silverlight application as a control. In the code to follow,the object myFirstSLApp represents the instance of our Silverlight control (effectively thecustom Silverlight video player we created). After you create a new instance of the control,you’ll need to set a number of properties. Very important among these properties is the Sourceproperty, which points to the location of the XAP file and then loads that within the WebPart. The height and width of the control will affect the presentation of the application inSharePoint.

49

Fox c02.tex V3 - 01/30/2009 4:58pm Page 50

Chapter 2: Your First Silverlight and SharePoint Integration

Listing 2-6: Web Part host container code

C#using System;using System.Runtime.InteropServices;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Xml.Serialization;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;using Microsoft.SharePoint.WebPartPages;

namespace MySLAppWPCS{

[Guid("f73f119d-684b-4052-b1b7-72f1d981911e")]public class MySLAppWebPart : System.Web.UI.WebControls.WebParts.WebPart{

public MySLAppWebPart(){}

protected override void OnLoad(EventArgs e){

base.OnLoad(e);

ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);if (scriptManager == null){

scriptManager = new ScriptManager();this.Controls.Add(scriptManager);

}}

protected override void CreateChildControls(){

System.Web.UI.SilverlightControls.Silverlight myFirstSLApp= new System.Web.UI.SilverlightControls.Silverlight();

myFirstSLApp.ID = "mySLApp";myFirstSLApp.Source = "http://stefox-t61p/XAPS/MySilverlightApp.xap";myFirstSLApp.Width = new System.Web.UI.WebControls.Unit(900);myFirstSLApp.Height = new System.Web.UI.WebControls.Unit(650);

this.Controls.Add(myFirstSLApp);}

}}

VBOption Explicit OnOption Strict On

Imports SystemImports System.Runtime.InteropServices

50

Fox c02.tex V3 - 01/30/2009 4:58pm Page 51

Chapter 2: Your First Silverlight and SharePoint Integration

Imports System.Web.UIImports System.Web.UI.WebControlsImports System.Web.UI.WebControls.WebPartsImports System.Xml.SerializationImports System.Web.UI.SilverlightControls

Imports Microsoft.SharePointImports Microsoft.SharePoint.WebControlsImports Microsoft.SharePoint.WebPartPages

Namespace MySLAppWebPart

<Guid("2ee26708-e2a4-41e3-8747-ee6bb85b48be")> _Public Class MySLWebPart

Inherits System.Web.UI.WebControls.WebParts.WebPart

Public Sub New()End Sub

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)MyBase.OnLoad(e)Dim scriptMgr As New ScriptManagerscriptMgr = ScriptManager.GetCurrent(Me.Page)

If (scriptMgr Is Nothing) ThenscriptMgr = New ScriptManagerMe.Controls.Add(scriptMgr)

End IfEnd Sub

Protected Overrides Sub CreateChildControls()MyBase.CreateChildControls()

Dim myFirstSLApp As New SilverlightmyFirstSLApp.ID = "mySLApp"myFirstSLApp.Source =

"http://stefox-t61p/XAPS/MySilverlightApp.xap"myFirstSLApp.Width = New Unit(900)myFirstSLApp.Height = New Unit(650)

Me.Controls.Add(myFirstSLApp)

End Sub

End Class

End Namespace

Configuring the Web Part Project for DeploymentWith the code added, you are now ready to complete the second step: configuring the Web Part projectfor deployment. To do this:

1. From the main Visual Studio menu, click Project, and then select the project properties (e.g.,MySLAppWebPart Properties). This invokes the Properties view in your project.

2. Click the Debug tab. Check the Start Browser with the URL radio button, and then enter theroot URL for your SharePoint site (e.g., http://localhost).

51

Fox c02.tex V3 - 01/30/2009 4:58pm Page 52

Chapter 2: Your First Silverlight and SharePoint Integration

3. To test the deployment of the Web Part, click Build, and then Deploy Solution(see Figure 2-9). This automatically creates a WSP package (the CAB equivalent forSharePoint assembly deployments), which contains all of the files that are required todeploy the Web Part assembly to SharePoint, deploys the solution files to the appropriateplaces on your SharePoint site, and then stops and restarts the IIS web application.

If you are running and trying to deploy on Windows Server 2008 with UAC turned on, you need torun Visual Studio ‘‘as Administrator’’ or you will get an ‘‘Object reference not set to an instance of anobject’’ exception.

Figure 2-9

When your Silverlight application deploys, you will receive a ‘‘Deploy Succeeded’’ message just beneaththe build output view in Visual Studio. Assuming that everything was configured correctly, you’ll beable to now add the Web Part to a site within SharePoint, thus the last step in your integration betweenSharePoint and Silverlight.

Adding the Silverlight Video PlayerApplication to the SharePoint Site

At this point, you’ve created the Silverlight application, and you’ve created and deployed the Web Partcontainer for the Silverlight application. Thus, the last remaining step is to create a site that can host

52

Fox c02.tex V3 - 01/30/2009 4:58pm Page 53

Chapter 2: Your First Silverlight and SharePoint Integration

the Web Part. Before you can do this, it’s important to have completed the steps to configure yourserver — as outlined in Chapter 1. If you did not go through these steps, you should do that now tomake sure that the Silverlight application renders properly. If you’ve completed the server configurationsteps, you are now ready to create the SharePoint site that will host the Silverlight-based Web Part. Todo this:

1. Navigate to your SharePoint site. We created a separate test site for our Silverlight videoplayer application called Wrox. To create a site similar to this, navigate to the home pageof your SharePoint site, and click ‘‘Site Actions’’ and Create, and then select ‘‘Sites andWorkspaces.’’

2. Provide a name, description, type of site (we selected Blank site), and URL for your site, andthen click Create. When the new site is created, SharePoint will automatically load it for you.

3. Click ‘‘Site Actions,’’ and then click ‘‘Edit Page in SharePoint.’’ In the site, click ‘‘Add a WebPart,’’ which invokes the Web Part Gallery (see Figure 2-10). Scroll down until you find theWeb Part project you added to SharePoint (e.g., MySLAppWebPart Web Part), and thenselect the checkbox and click Add.

Figure 2-10

53

Fox c02.tex V3 - 01/30/2009 4:58pm Page 54

Chapter 2: Your First Silverlight and SharePoint Integration

This will then add the Silverlight media player application into SharePoint by way of theWeb Part as a host container. Figure 2-11 illustrates the new Web Part added and that Share-Point is still in Edit mode.

Figure 2-11

4. To exit Edit mode and publish the page, click ‘‘Exit Edit Mode’’ in the right-hand corner ofthe page.

This will publish the Web Part and the Silverlight application. After publishing, theSilverlight application will respond the same as when you were debugging it within VisualStudio 2008; it just appears as a Web Part within SharePoint (see Figure 2-12).

5. After you’ve added it to SharePoint, try out the different controls within the Silverlightapplication to make sure that they all work.

At this point, it’s worth saying Congratulations! You’ve just built and integrated your first Silverlightapplication with SharePoint.

54

Fox c02.tex V3 - 01/30/2009 4:58pm Page 55

Chapter 2: Your First Silverlight and SharePoint Integration

Figure 2-12

Troubleshooting TipsAs you know, development is not always without some degree of troubleshooting, so here are a fewthings to keep an eye on as you integrate your Silverlight applications with SharePoint:

❑ If you get ambiguous network errors when loading media, this is often because the deployedassembly cannot find the media. Make sure that the media loads properly in the Silverlightapplication first in the test environment. If it does, then, when deployed, the Silverlightapplication is not finding the media.

❑ Make sure that the XAP Source location is correct within the Web Part file. Many times, we’veloaded the Web Part without any Silverlight application — you just see the title of the Web Part.This is usually because the Web Part cannot find the XAP file.

❑ Also, make sure that when you update your Silverlight application, recopy the newest version ofthe XAP file into the source location that you’ve specified in the Web Part project. (This is if you

55

Fox c02.tex V3 - 01/30/2009 4:58pm Page 56

Chapter 2: Your First Silverlight and SharePoint Integration

choose to host your applications on SharePoint. Other ways of deploying Silverlight applicationsare discussed later in the book.)

❑ If you’ve successfully added the Web Part, but the Silverlight still does not show up, thendouble-check on the web.config file in your root SharePoint directory and make sure that itnot only has the Web Part marked as a safe control (as discussed earlier), but also has all of thenecessary elements to support the Silverlight application. See Chapter 1 for more information onserver configuration.

SummaryThis chapter built on Chapter 1, providing a complete walk-through of how to first create a customSilverlight application, the video player, and then integrate that video player with SharePoint. In theSilverlight application, you’ve seen how to create named objects within your XAML-based UI and thenmap events to these objects. The key events in the sample application were radio buttons (user selections)and controls that enabled users to interact with the video player. Some code samples were providedshowing formatting that can enhance the look and feel of your custom Silverlight applications.

The method that we used to integrate with SharePoint was a Web Part host container for the Silverlightapplication. You’ll find that this is a very common way of integrating Silverlight applications with Share-Point and probably one of the most straightforward ways. As you move through this book, the Web Partmethod will return, but you’ll go a little deeper and see how you can interconnect the Web Parts througha service-oriented architecture.

Additional ReferencesSharePoint and Silverlight Blueprints: www.ssblueprints.net/sharepoint/.SharePoint Development Resources: www.microsoft.com/click/SharePointDeveloper/.Silverlight Home Page: http://silverlight.net/default.aspx.

56

Fox c03.tex V3 - 01/30/2009 2:46pm Page 57

Creating CustomField Types

In the last two chapters, you learned the what and why for integrating SharePoint and Silverlight,and you walked through your first SharePoint and Silverlight integration. There are various waysto integrate Silverlight applications with SharePoint to enhance the user experience that you’lllearn throughout this book. Other chapters will cover customizing and branding your SharePointsite with Silverlight, data-binding with lists, and inter–Web Part communication. This chaptercovers list customization through the creation of custom field types using Web Parts as contain-ers for Silverlight applications. Specifically, this chapter discusses the how by looking at how youcan customize a list; particularly addressing how you can create customized columns by creatingcustom field types that can be rendered within lists. The chapter starts by providing some back-ground on lists, columns, and custom field types — walking you through how to create a simple(non-Silverlight-enabled) custom field for a list, and then it moves on to creating a Silverlight appli-cation that you’ll then use in a custom list template.

Lists, Columns, and Custom Field TypesOne of the core artifacts within SharePoint is the list. A list is essentially a container that can beused to create and view a collection of items. These data can represent any number of things, suchas customer lists, announcements, and documents; SharePoint lists also support having metadataassociated with these objects.

SharePoint creates a list through a set of list templates, which defines the type of items stored inthe list, the ways in which the items are presented and subsequently viewed by the end-user, howthe items will be described, and so on. You can also use the SharePoint object model to program-matically customize parts of the list. Windows SharePoint Services (WSS) 3.0, the core SharePointinfrastructure that ships with Windows Server, provides a core set of list template definitions thatcan be used when creating and customizing lists. SharePoint also provides a way for you not only tocreate lists through these templates, but also to add event receivers to the list as well. Each of the listtemplates has a set of properties that are specific to that particular list, which control, for example,the set of fields, views, or forms that are displayed for that list.

Fox c03.tex V3 - 01/30/2009 2:46pm Page 58

Chapter 3: Creating Custom Field Types

Using List Templates and Customer ListsThe SharePoint list templates are listed and described in the following table:

List Templates Description

Document Library For storing and collaborating around documents. Supports features such asversioning, edit controls (check-in and check-out), and workflow. Alsosupports integration with smart-client templates or documents.

Form Library For storing InfoPath forms

Wiki Page Library For social collaboration through wiki pages

Picture Library For storing objects like graphic and video files (a special type of documentlibrary)

Announcements For sharing news or announcements

Contacts For storing contact information. Also supports integration with Outlook.

Discussion Board For social collaboration through threaded discussion pages

Links A simple list that enables you to manage hyperlinks

Calendar To track events such as conferences or employee vacations. Also includessupport for Outlook integration.

Tasks To manage tasks or activities that are integrated (or a result of) workflow

Project Tasks For project management and project reporting. Also includes integration withMicrosoft Project.

Issue Tracking For tracking and managing issues or bugs

Survey For building and managing survey data

Custom List An empty list definition that enables you to define the fields and views thatyou want to display. You can also create a custom list using Microsoft Excelspreadsheets.

You can create a list either through the SharePoint interface (i.e., the browser) or programmatically usingVisual Studio. Creating a list through the browser is a good way to learn what options you have for thelists and what they look like when created; however, if you want to reuse a custom list, for example,across multiple sites then you can ‘‘provision’’ that list through Visual Studio. Doing this effectivelycreates and deploys the list as a feature and through a solution package; thus, you’re able to re-deployit across multiple sites or within a specific SharePoint farm. Once the solution package is deployed, thefeature can then be installed and activated at a site collection or site level. Once activated, any user whocreates a new list on that SharePoint site will have that list available to them from the available lists.

This chapter centers on the creation of a custom list. A custom list provides you a wider flexibility whencreating a list. For example, if you want to create a list that stores specific customer or project information,you can use the custom list to do this. When creating a list through the SharePoint interface, you can selectfrom a standard set of field types. A field type is a data type in SharePoint that can store content. Thus,

58

Fox c03.tex V3 - 01/30/2009 2:46pm Page 59

Chapter 3: Creating Custom Field Types

the list you create consists of the field types you choose [plus the default Title field (single line of textfield type)]. The field types you have available to you when creating a SharePoint list are shown in thefollowing table:

Field Types Description

Single line of text A single line of text with a customizable maximum number of charactersfor that line

Multiple lines of text A textbox with some limited rich-text formatting (e.g., bold, pictures,tables, etc.)

Choice A choice of custom items you define

Number A numerical value that includes minimum, maximum, and so on

Currency A monetary value that maps to a specific currency

Date and Time Date and time information

Lookup A reference to another field in another list on the SharePoint site

Yes/No A simple Boolean field that renders as true/false and displays as acheckbox

Person or Group A user or member of the SharePoint site

Hyperlink or Picture A string that is in URL format

Calculated A value that is calculated using other fields on the SharePoint site

Creating a Custom List with the SharePoint InterfaceOne of the steps that consumers of your custom field type will need to take is to add a column to alist — one that they create or one that you provision for them. Before jumping into the development ofthe custom field type, let’s first walk through what the experience of adding a field type (or column) to alist looks like using the browser as the interface.

To create a custom list using the SharePoint interface, do the following:

1. Navigate to the home page of your SharePoint site, and then click ‘‘View All Site Content.’’

2. Click on the Create button, and then under the Custom List gallery, click ‘‘Custom List.’’

3. Provide a name and description, and click Create. At this point, the custom list displays withthe one default field type associated with it: Title.

4. To add more columns (which are composed of fields and field types), click ‘‘Settings’’and ‘‘Create Column,’’ which invokes the Create Column page (see Figure 3-1). Noteall of the available columns plus some custom ones added to this site as well (e.g.,SampleFieldCtrlField, Signature, etc.).

Creating a Custom List Using Visual StudioNow that you’ve seen how you can create a custom list through the browser interaction, let’s take a lookat how you can create a list programmatically using Visual Studio 2008.

59

Fox c03.tex V3 - 01/30/2009 2:46pm Page 60

Chapter 3: Creating Custom Field Types

Figure 3-1

You can use Visual Studio to create a list programmatically:

1. Open Visual Studio 2008.

2. Select File � New Project � SharePoint, and you’ll see several different choices available toyou.

3. One of the options is ‘‘List Definition,’’ which you can use to build a custom list. If you pro-vide a name for the list and click OK, you’ll then be prompted to select a specific list for yoursolution. Figure 3-2 shows the different lists that you can create programmatically for yourSharePoint site.

One of the key differences between creating the list via the browser and via a tool like Visual Studio isthat you can add deeper customizations to the list, such as data-binding and custom field types, whencreating them.

After you complete these steps, Visual Studio creates a new list project (a Document Library as per thechoice in Figure 3-2) for you (see Figure 3-3) and adds all of the necessary files you need when deployingthe list to your SharePoint site. The nice thing about Visual Studio (and the Visual Studio extensions forWindows SharePoint Services or VSeWSS 1.2) is that you have several event receiver classes that you canuse to develop and deploy event receivers for your list. While these are not necessarily Silverlight-specific,

60

Fox c03.tex V3 - 01/30/2009 2:46pm Page 61

Chapter 3: Creating Custom Field Types

you could invoke a Silverlight application from an event receiver or you could even bind data within alist to a Silverlight application to enhance the presentation of the data in SharePoint.

Figure 3-2

Figure 3-3

As mentioned earlier, this chapter focuses on discussing the customizations at the atomiclevel — specifically the custom field type. Beyond the available field types that ship withSharePoint, you can also create custom field types. Custom field types are great for those

61

Fox c03.tex V3 - 01/30/2009 2:46pm Page 62

Chapter 3: Creating Custom Field Types

developers who really want to go to the next level and add more customization to your Share-Point sites or provide a custom way for entering data into a SharePoint list. For example, as you saw inFigure 3-1, a number of custom field types were added (e.g., Signature and Siverlight Slider Control).One specific example, called the Signature field type, is a Silverlight-enabled custom field type thatprovides a way for you to sign your name electronically on a custom list (see Figure 3-4). Here, theSilverlight application was rendered using a custom field type in SharePoint, a method you’ll exploremore in this chapter. (For more information such as hands-on labs and code samples on the Signaturefield type example shown below, go to www.mssharepointdeveloper.com.)

Figure 3-4

A custom field type essentially represents a new data type for the SharePoint site and list and is onethat can be created using managed-code — that is, C# or Visual Basic — which also takes advantage ofthe .NET platform. Custom field types can be created in various ways ranging from using native classeswithin Visual Studio to using the SharePoint-specific projects that the Visual Studio extensions for WSSprovide for you. For the remainder of this chapter, you’re going to walk through a couple of scenariosto get you really familiar with the custom field types (because they can be a little tricky to develop).The first thing you’ll do is create a simple custom field type that is based on an ASP control that you’llthen map to the custom field type. You’ll then create a Silverlight application that you’ll incorporate intoSharePoint as a custom field type control. When done, you’ll not only have a good understanding ofhow you can create a custom field type, but also you’ll understand a couple of different ways in whichyou can customize them. And specific to this book, you’ll understand how you can customize one usingSilverlight. So, let’s get started.

Developing Your First Custom Field TypeSimilar to the field types that ship with SharePoint, the custom field types have a control that will berendered. This control will more than likely provide a way for you to store data, for example, customtext fields, dropdown lists, and so on. The goal of the custom field type should be to not only providea way for the user to enter data into the control, but also to store that entered data in the custom list

62

Fox c03.tex V3 - 01/30/2009 2:46pm Page 63

Chapter 3: Creating Custom Field Types

of which the custom field type is a part. For example, the scenario you’ll walk through in this chapteruses a custom field type to enable a user to enter Likert scale survey data. The Likert scale is a five-pointscale quite often used when collecting data on surveys in the social sciences. Typically, the scale runs asfollows: ‘‘Strongly Agree,’’ ‘‘Agree,’’ ‘‘Neutral,’’ ‘‘Disagree,’’ and ‘‘Strongly Disagree.’’ When transposingthe Likert scale results into analytical form, numerical values are associated with each of the qualitativepoints on the scale, for example, 1 = Strongly Agree, 2 = Agree, and so on, all the way to 5. This way,you can perform quantitative analyses on the data collected through the survey. That said, you’ll createa Likert scale response using an ASP control and then similarly with a Silverlight application, both ofwhich will interact with their respective SharePoint lists.

Creating an ASP-Based Custom Field TypeTo create the ASP-based custom field type, open Visual Studio 2008 (making sure you have the VisualStudio Extensions for WSS 3.0 — VSeWSS 1.2 — installed), and follow these steps:

1. Click File � New � Project, and select SharePoint under Project Types and then click Empty.Provide a name for the project (e.g., LikertScaleFieldType) and click OK. This creates an emptySharePoint project, which adds some prerequisite DLL references to your project — namely,Microsoft.SharePoint, Microsoft.SharePoint.Security, and System.Web. Figure 3-5 displaysthe New Project screenshot.

Figure 3-5

2. After you’ve created the empty SharePoint project, you can add any number of otheritem-level templates. For example, you could add a Web Part item, Content Type, or FieldControl as items to the project. We will add a Field Control to the project, which willrepresent the custom field type. To do this, right-click on the main project file (which inour case is LikertScaleFieldType), and select ‘‘Add’’ and ‘‘New Item.’’ This invokes the

63

Fox c03.tex V3 - 01/30/2009 2:46pm Page 64

Chapter 3: Creating Custom Field Types

Add New Item dialog, in which you will select SharePoint as the category and then selectField Control as the item template. Provide a name for the field control (we called oursLikertScale), and then click Add (see Figure 3-6).

Figure 3-6

After you’ve done this, Visual Studio adds several objects to the solution. For example,it will add two classes: one for the field type and the other for the rendering control thatwill be displayed within the field type. It also adds Templates and XML folders, whichare folders where the custom field type XML definition file lives. Visual Studio doesnot, however, add a CONTENTTEMPLATES folder. SharePoint stores all of the ASPcontrols in this folder, so since you’re creating a custom ASP control, you need to createthis folder in your project. That way, when you build the project, Visual Studio willadd the ASP control into that folder. (VSeWSS does not assume that you’re creating anASP control, so it does not add the folder by default when you first create a SharePointproject.)

3. To add a CONTENTTEMPLATES folder, right-click on the Templates folder and select Add,and then select ‘‘New Folder.’’ This is where you add the ASCX template, which essentiallyrepresents the ASP control that you’ll render inside the custom field type.

For example, in Figure 3-7, note the fact that you’ve got a file named LikertScaleDropDownList.ascx in the CONTROLTEMPLATES folder in the project. The ASCX file is code that repre-sents an ASP dropdown list that you’ll map to items in the main field control code. Whenyou build and deploy this project, Visual Studio will copy the LikertScaleDropDownList.ascx and the fldtypes_LikerScale.xml into their respective folders within the SharePointfolder hierarchy.

You’ll come back to adding the actual ASCX file a little later on in this section, so now that you have theproject structure set up in Visual Studio, let’s take a look at each of the project Parts of the solution (seeFigure 3-7).

64

Fox c03.tex V3 - 01/30/2009 2:46pm Page 65

Chapter 3: Creating Custom Field Types

Figure 3-7

The Field Type ClassThe first class that we’ll discuss is the field type class. This class (in our project called LikertScale.Field.cs)is one that is automatically generated by Visual Studio and represents the core field type class. In thisclass, LikertScaleField inherits from SPFieldText, one of many possible derivations when creatingfield types. Also, there are two required constructors that live in this class as well. One of the coreparts of this class is the FieldRenderingControl, which is a property that is overridden and returns aBaseFieldControl object. In the following code sample, you’ll notice that the BaseFieldControl (calledfieldcontrol by default) is set to an instance of the LikertScaleFieldControl, which is the controlthat will get rendered. Listing 3-1 provides C# and Visual Basic examples of the code in the core fieldtype class.

Listing 3-1: Core field type class

C#using System;using System.Runtime.InteropServices;using System.Security.Permissions;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;

Continued

65

Fox c03.tex V3 - 01/30/2009 2:46pm Page 66

Chapter 3: Creating Custom Field Types

Listing 3-1: Core field type class (continued)

using Microsoft.SharePoint.Security;

namespace LikertScaleFieldType{

[CLSCompliant(false)][Guid("1b664652-397c-4cb6-935c-1c088694afe4")]public class LikertScaleField : SPFieldText{

public LikertScaleField(SPFieldCollection fields, string fieldName): base(fields, fieldName)

{}

public LikertScaleField(SPFieldCollection fields,string typeName, string displayName)

: base(fields, typeName, displayName){}

public override BaseFieldControl FieldRenderingControl{

[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]get{

BaseFieldControl fieldControl = new LikertScaleFieldControl();fieldControl.FieldName = this.InternalName;return fieldControl;

}}

}}

VBImports SystemImports System.Runtime.InteropServicesImports System.Security.PermissionsImports Microsoft.SharePointImports Microsoft.SharePoint.WebControlsImports Microsoft.SharePoint.Security

Namespace LikertScaleFieldTypeVB

<CLSCompliant(False)><Guid("811febc4-9959-4ff4-b144-9dcc727bff32")>Public Class LikertScaleFieldTypeField

Inherits SPFieldText

Public Sub New(ByVal fields As SPFieldCollection, ByVal fieldNameAs String)

: MyBase.New(fields, fieldName)

66

Fox c03.tex V3 - 01/30/2009 2:46pm Page 67

Chapter 3: Creating Custom Field Types

End Sub

Public Sub New(ByVal fields As SPFieldCollection,ByVal typeName As String, ByVal displayName As String)

: MyBase.New(fields, typeName, displayName)End Sub

Public Overrides ReadOnly Property FieldRenderingControl()As BaseFieldControl

<SharePointPermission(SecurityAction.LinkDemand, ObjectModel:=True)>Get

Dim fieldControl As BaseFieldControl = NewLikertScaleFieldTypeFieldControl()

fieldControl.FieldName = Me.InternalName

Return fieldControlEnd Get

End Property

End Class

End Namespace

Implementing a ControlWith the core field type class complete (essentially you’ll leave the default code in this example tokeep things simple), you now need to ensure that the core field type reference actually implementssomething — that is, a control of some sort. In this sample, we created a simple ASP control: a drop-down list that will store a collection of items (the individual Likert scale items). The LikertScaleDrop-DownList.ascx file is where this code lives and represents the ASP user interface (UI) template (seeListing 3-2). The sample code for this dropdown list is fairly short because you’ll be using the field typecontrol class to add the ‘‘code-behind’’ for this ASP UI. In Listing 3-2, note the RenderingTemplate ID(LikertScaleFieldControl), which you’ll use in the code-behind to create an instance of the controlusing the ASP control, and also note the control ID (LikertScale), of which you’ll create an instance andto which you’ll add the Likert scale items.

To add the ASCX file, right-click on the CONTROLTEMPLATES folder and click Add, and then select‘‘New Item.’’ Select the Code category, and then select HTML page. Provide a name for the control, andmake sure you append the name with ascx (e.g., LikertScaleDropDownList.ascx). When the solution addsthe file to the project, remove all of the default code from the file and add the code in Listing 3-2, whichwill render an ASP dropdown list control.

Listing 3-2: ASP dropdown list

<%@ Control Language="C#" Debug="true" %><%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c" %><%@ Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint,Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

Namespace="Microsoft.SharePoint.WebControls" %><SharePoint:RenderingTemplate ID="LikertScaleFieldControl" runat="server">

<Template><asp:DropDownList ID="LikertScale" runat="server" />

</Template></SharePoint:RenderingTemplate>

67

Fox c03.tex V3 - 01/30/2009 2:46pm Page 68

Chapter 3: Creating Custom Field Types

Hooking the Field Control Class to the ASP ControlWith the rendering template now created, you can add some additional code to the field control class(LikertScale.FieldControl.cs) to hook it to the ASP control (i.e., the asp:DropDownList control in the ascxfile you added to the solution) and then provide some additional functionality — other than an emptydropdown list.

In the field type control class (see Listing 3-3), you create an instance of the LikertScaleFieldControl,which derives from BaseFieldControl, which renders a field on a page by using a label, link, or textboxcontrol. In the LikertScaleFieldControl class, you start by creating an instance of the dropdownlist (called LikertScale). You then override the DefaultTemplateName property to return a stringmatch of the ASP control (LikertScaleFieldControl) from the ASCX file. You also override theValue property, which returns a value that will eventually populate the list. Note that you also call theEnsureChildControls method, which calls the ChildControls method if it has not been called already.The ChildControls method then assigns the dropdown list from the ASCX file to the LikertScale objectcreated earlier in the class, validates that it indeed exists (if it doesn’t, an exception will be thrown), andthen adds several items to the dropdown list. To follow, you can see both the C# and the Visual Basicsamples for the LikertScaleFieldType class (Listing 3-3).

Listing 3-3: Field type control class

C#using System;using System.Runtime.InteropServices;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;using System.IO;using System.Security.Permissions;using System.Text;using System.Xml;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.ComponentModel;using System.Configuration;using System.Diagnostics;

namespace LikertScaleFieldType{

[CLSCompliant(false)][Guid("5e9d1251-d652-445a-8b06-8689091f3440")]public class LikertScaleFieldControl : BaseFieldControl{

protected DropDownList LikertScale;

protected override string DefaultTemplateName{

get{

return "LikertScaleFieldControl";}

68

Fox c03.tex V3 - 01/30/2009 2:46pm Page 69

Chapter 3: Creating Custom Field Types

}

public override object Value{

get{

this.EnsureChildControls();return this.LikertScale.SelectedValue;

}set{

EnsureChildControls();this.LikertScale.SelectedValue =

this.ItemFieldValue.ToString();}

}

protected override void CreateChildControls(){

base.CreateChildControls();

LikertScale = TemplateContainer.FindControl("LikertScale") asDropDownList;

if (this.LikertScale == null)throw new ConfigurationErrorsException("LikertScale drop-

down list not found. Possibly corrupt control template.");

if (!this.Page.IsPostBack){

this.LikertScale.Items.AddRange(new ListItem[]{new ListItem(string.Empty, null),new ListItem("Strongly Agree", "1"),new ListItem("Agree", "2"),new ListItem("Neutral", "3"),new ListItem("Disagree", "4"),new ListItem("Strongly Disagree", "5")});

}}

}

}

VBImports System.Runtime.InteropServicesImports Microsoft.SharePointImports Microsoft.SharePoint.WebControlsImports System.IOImports System.Security.PermissionsImports System.TextImports System.Xml

Continued

69

Fox c03.tex V3 - 01/30/2009 2:46pm Page 70

Chapter 3: Creating Custom Field Types

Listing 3-3: Field type control class (continued)

Imports System.WebImports System.Web.UIImports System.Web.UI.WebControlsImports System.Web.UI.HtmlControlsImports System.ComponentModelImports System.ConfigurationImports System.Diagnostics

Namespace LikertScaleFieldType<CLSCompliant(False)><Guid("5e9d1251-d652-445a-8b06-8689091f3440")>Public Class LikertScaleFieldControl

Inherits BaseFieldControlProtected LikertScale As DropDownList

Protected Overloads Overrides ReadOnly PropertyDefaultTemplateName() As String

GetReturn "LikertScaleFieldControl"

End GetEnd Property

Public Overloads Overrides Property Value() As ObjectGet

Me.EnsureChildControls()Return AddressOf

Me.LikertScale.SelectedValueEnd GetSet

EnsureChildControls()AddressOf Me.LikertScale.SelectedValue =

AddressOf Me.ItemFieldValue.ToString()End Set

End Property

Protected Overloads Overrides Sub CreateChildControls()

MyBase.CreateChildControls()

LikertScale =TryCast(TemplateContainer.FindControl("LikertScale"), DropDownList)

If Me.LikertScale Is Nothing ThenThrow New

ConfigurationErrorsException("LikertScale drop-down list not found.Possibly corrupt control template.")

End If

If Not AddressOf AddressOf Me.Page.IsPostBack ThenAddressOf Me.LikertScale.Items.AddRange(New ListItem()

{New ListItem(String.Empty, Nothing),New ListItem("Strongly Agree", "1"),New ListItem("Agree", "2"),

70

Fox c03.tex V3 - 01/30/2009 2:46pm Page 71

Chapter 3: Creating Custom Field Types

New ListItem("Neutral", "3"),New ListItem("Disagree", "4"),New ListItem("Strongly Disagree", "5")})

End IfEnd Sub

End ClassEnd Namespace

The Custom Field Type Definition FileThe last part of the sample project is the custom field type definition file — the fldtypes_LikertScale.xmlfile that Visual Studio creates by default and adds to the XML folder in the solution. This XML file pro-vides SharePoint with field information that is used when the field is loaded and displayed in SharePoint(e.g., the TypeDisplayName and TypeShortDescription show up in the Column Gallery) and is alsorequired to properly reference any custom assemblies (FieldTypeClass). This information also shows theparent type of the field type (ParentType) and whether a user can use the field to create a column for a list(UserCreatable). Because you used Visual Studio extensions for the custom field type, when you buildthe file or when you open the project in the WSP view and click Refresh, this file will be auto-generated(see Listing 3-4). One thing that the auto-generated file is missing is presentation information, whichyou’ll find in other definition files.

Listing 3-4: Field type definition file

<?xml version="1.0" encoding="utf-8"?><FieldTypes>

<FieldType><Field Name="TypeName">LikertScaleField</Field><Field Name="TypeDisplayName">LikertScaleField</Field><Field Name="TypeShortDescription">LikertScaleField</Field><Field Name="ParentType">Text</Field><Field Name="UserCreatable">TRUE</Field><Field Name="FieldTypeClass">1b664652-397c-4cb6-935c-1c088694afe4</Field>

</FieldType></FieldTypes>

Interestingly, when the solution is built and deployed, the FieldTypeClass attribute, which provides areference to the custom field type assembly in the pre-deployed definition file, changes from a GUIDto load the fully qualified name in the post-deployed definition file. This is not a major issue, but alook at the deployed version will show there is a difference. This is shown in Listing 3-5 in the grayscreened code.

Listing 3-5: Field type definition file (post-deployment)

<?xml version="1.0" encoding="utf-8"?><FieldTypes>

<FieldType><Field Name="TypeName">LikertScaleField</Field><Field Name="TypeDisplayName">Likert Scale Field</Field><Field Name="TypeShortDescription">Likert Scale Field Type</Field><Field Name="ParentType">Text</Field><Field Name="UserCreatable">TRUE</Field>

71

Fox c03.tex V3 - 01/30/2009 2:46pm Page 72

Chapter 3: Creating Custom Field Types

Listing 3-5: Field type definition file (post-deployment) (continued)

<Field Name="FieldTypeClass"> LikertScaleFieldType.LikertScaleField,LikertScaleFieldType, Version=1.0.0.0, Culture=neutral,PublicKeyToken=9f4da00116c38ec5</Field></FieldType>

</FieldTypes>

Deploying the Custom Field TypeAfter you’ve added all of the preceding code to the specified files in your solution, you are ready todeploy the custom field type. This requires you to:

1. Successfully build the solution to ensure that the code will compile.

2. Copy the assembly into the global assembly cache (GAC) — in this case,LikertScaleFieldType.dll was the file we copied to the GAC. (The global assemblycache is the folder where many of your core assemblies are stored; it is located in theWindows/assembly path within your root drive, e.g., c:/Windows/assembly.) To dothis, you can manually copy-and-paste the DLL in administrator mode or you can use theGACUTIL utility, a utility that can be used to copy DLLs directly into the GAC.

To use the GACUTIL, navigate to Visual Studio 2008 in your Start menu and select VisualStudio Tools; right-click ‘‘Visual Studio 2008 Command Prompt’’ and select ‘‘Run as Admin-istrator.’’ Then navigate to the folder where your DLL resides (i.e., the DLL that you want tocopy into the GAC) and type in the following, which will copy the named DLL in the com-mand to the GAC:

gacutil.exe -if "<name of DLL>"

3. Make sure before you deploy that you set your SharePoint server as the default debugserver. To do this, select Project from the main Visual Studio menu, and choose your projectProperties. Then select the Debug tab, click the Start browser with the URL radio button,and enter your server name in the required field (see Figure 3-8).

Figure 3-8

72

Fox c03.tex V3 - 01/30/2009 2:46pm Page 73

Chapter 3: Creating Custom Field Types

At this point, you can now deploy the custom field type to your SharePoint site. To do this, click Build �Deploy Solution. Visual Studio will then copy all of the project files in the appropriate places (save forthe core assembly, which you’ll manually need to add to the GAC as mentioned above), and it will re-setIIS for you in the process.

Testing the Custom Field TypeTo test out the custom field type, do the following:

1. Open SharePoint and navigate to your home page.

2. Click View All Site Content � Create.

3. Under the Tracking column, click Survey (remember that a survey is another type of list).

4. Provide a Name for the list (we used Likert Scale Survey), provide a Description (optional),and then click Next (see Figure 3-9).

5. Clicking Next will then take you to the Question and Column Gallery, where you can typeyour question and then add a custom field type to the question.

6. Type a question, and then select the custom field type you just added to SharePoint (ourswill read as LikertScaleField — not a very user-friendly name, but one that could be alteredthrough amending the fldtype*.xml file).

Figure 3-9

73

Fox c03.tex V3 - 01/30/2009 2:46pm Page 74

Chapter 3: Creating Custom Field Types

Once you’ve created the new list, SharePoint will display it for you. You will now want to add the customfield type you just created to the list to test it out. To do this:

1. Click Settings � Create Column. This takes you to the Column Gallery page (recallFigure 3-1), from which you can select the custom field type you added.

2. If you followed along with the code, you will find a custom field type called LikertScaleField(not the most user-friendly name, we would agree), which you can select, provide a namefor, and then click OK. You are now taken back to the list.

3. Click New, and then complete the list data. Beside what is named the Response field (theLikertScaleField), you’ll see that you now have a choice of Likert scale options when com-pleting that portion of the survey (see Figure 3-10).

Figure 3-10

4. When you complete the data and click OK, note that the numbers that we mapped to theLikert scale options in our code (1 for Strongly Agree, 2 for Agree, etc.) show up in theResponse column (see Figure 3-11).

Figure 3-11

Creating a Silverlight-Based Custom Field TypeSo, now that we’ve walked you through all of the above, you’re probably asking yourself: ‘‘Why did weshow you all of a custom field type based on an ASP control as opposed to Silverlight?’’

74

Fox c03.tex V3 - 01/30/2009 2:46pm Page 75

Chapter 3: Creating Custom Field Types

❑ First, you’ll often want to know what the options are — and building out and using ASP formswithin SharePoint is one of the commonly used alternatives when customizing custom fieldtypes.

❑ Second, custom lists are not the only place where you could use a custom field type like the oneyou’ve just walked through. You could also create a custom field type for the Survey list typein SharePoint and more generally customize the ways in which people interact with other listswithin SharePoint.

❑ Most importantly, we wanted to give you a good understanding of how to create a customfield type before jumping into enhancing it with a Silverlight application, which in some senseadds a level of complexity to the custom field type, but also adds additional potential for richerfunctionality. That said, let’s walk through how you integrate Silverlight applications withSharePoint — specifically focusing on the custom field type as the integration point.

To build the Silverlight-based custom field type, we are going to apply many of the same principles youjust learned above in the ASP example. For example, you’ll use the same scenario (i.e., the Likert scaleoptions) to create a custom field type that can be used within to collect data from users — and can beused cross-site. You’ll also create the Silverlight-enabled custom field type using VSeWSS 1.2, so you’llsee how you can use Visual Studio to build out this customization. And then, lastly, you’ll apply the sameprinciple of rendering a custom control within the custom field type. In this case, though, the renderedcontrol will be the Silverlight application. And while the specific scenario may not have practical impli-cations for you (i.e., you may not need a survey instrument), the design pattern that integrates a customfield type with SharePoint and Silverlight via a custom service is one that you’ll apply to many differentscenarios.

Developing a Silverlight-Based Custom Field TypeSimilar to the way you created the ASP-based custom field type, you’re going to build a Silverlightcontrol that will be rendered within the custom field and will directly communicate with the SharePointobject model. There are, however, a few differences. It’s important, however, to remember that thesedifferences will open opportunities to inject rich functionality into not only the custom field types, butalso other ‘‘host containers’’ within SharePoint (such as Web Parts). Specifically, you’ll consume a WebService from within the Silverlight application that will interact with SharePoint and update a list item(i.e., a field) from the user’s response from the Silverlight application. To do this, you’ll need to completethe following:

1. Create a Web Service that will update a specific field in a SharePoint list.

2. Create a Silverlight application that will consume the Web Service.

3. Create a custom field type that will render the Silverlight control.

Let’s walk through each of these.

Creating the Web ServiceThe first step to completing the solution is to create and deploy a Web Service. You’ll create and deployone in a test environment that will accept a string parameter from a user’s input (which you’ll eventu-ally hook up to the Silverlight application), and then you’ll use that input to further update a field inSharePoint.

75

Fox c03.tex V3 - 01/30/2009 2:46pm Page 76

Chapter 3: Creating Custom Field Types

To get started, open Visual Studio 2008 and click File � New � Web Site. In the New Web Site templatesdialog, select ‘‘ASP.NET Web Service.’’ Provide a name (e.g., MyLikertWS), select ‘‘File System’’ as theLocation, your preferred managed-code language, and click OK.

By default, Visual Studio adds some code to the main Web Service class. If you hit [F5], this will invokethe Web Service, and you’ll be able to test out the one web method (HelloWorld), which returns a stringwith the value of ‘‘Hello World’’ (see VB) for the C# and VB default sample code for the default HelloWorld web method (see Listing 3-7).

Listing 3-6: Default code in Web Service core class

C#[WebService(Namespace = "http://tempuri.org/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]public class Service : System.Web.Services.WebService{

public Service () {

}

[WebMethod]public string HelloWorld() {

return "Hello World";}

}

VB<WebService(Namespace:="http://tempuri.org/")><WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)><Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>Public Class Service

Inherits System.Web.Services.WebService

<WebMethod()>Public Function HelloWorld() As String

Return "Hello World"End Function

In the Web Service that you build for this example, you’ll use the same solution you just created (i.e.,the Web Service project), but you’re going to replace the code in Listing 3-8 (on page 78) with the codethat was created by default in the Service.cs (or Service.vb) file (listed in Listing 3-7). Before you do this,though, make sure you create a strong name for your project. To do this, click on the Project properties,select the Signing tab, click ‘‘Sign the Assembly,’’ and select ‘‘Choose a strong name key file and providea name for your strong name key’’ (uncheck the ‘‘Protect my key with a password’’ checkbox).

Because you will be interacting with a SharePoint list programmatically, you need to ensure that youhave the appropriate references set up in your project. Thus, you’ll need to add the Microsoft.SharePointDLL to the project. To do this, right-click on the project, select ‘‘Add Reference,’’ click the .NET tab, select‘‘Windows SharePoint Services,’’ and click OK. Now double-click on the Service.cs file (or the Service.vbfile), and add the main code for your Service. Now that you’ve added the code, let’s walk through thesample code and discuss what it does.

76

Fox c03.tex V3 - 01/30/2009 2:46pm Page 77

Chapter 3: Creating Custom Field Types

The first thing to note in the sample code in Listing 3-8 is that you’ve added a parameter to the webmethod (userResponse), which is an input string parameter. In C#, the syntax looks as follows:

public void updateLikertList(string userResponse)

In VB, the syntax looks as follows:

Public Sub updateLikertList(userResponse As String)

This will be sent from the Silverlight application and will be used to update the custom field in theSharePoint list. Because you want to normalize the standard Likert response into a numerical stringvalue (to be consistent with what we did with the ASP-based custom field type), you create the stringvariable that you’ll use to update the SharePoint list with (updateToLikertList) and then depending onthe value of userResponse, we’ll assign a value to updateToLikertList.

In C#, the syntax for this code is as follows:

string updateToLikertList = null;

if (userResponse == "Strongly Agree"){

updateToLikertList = "1";}else if (userResponse == "Agree"){

updateToLikertList = "2";}else if (userResponse == "Neutral"){

updateToLikertList = "3";}else if (userResponse == "Disagree"){

updateToLikertList = "4";}else if (userResponse == "Strongly Disagree"){

updateToLikertList = "5";}else{

updateToLikertList = "NA";}

In VB, the syntax for this code is as follows:

Dim updateToLikertList As String = NothingIf userResponse = "Strongly Agree" Then

updateToLikertList = "1"ElseIf userResponse = "Agree" Then

updateToLikertList = "2"ElseIf userResponse = "Neutral" Then

updateToLikertList = "3"

77

Fox c03.tex V3 - 01/30/2009 2:46pm Page 78

Chapter 3: Creating Custom Field Types

ElseIf userResponse = "Disagree" ThenupdateToLikertList = "4"

ElseIf userResponse = "Strongly Disagree" ThenupdateToLikertList = "5"

ElseupdateToLikertList = "NA"

End If

After you validate the input string parameter, you access the SharePoint object model to update the listfield. To do this:

1. Create an instance of the SharePoint site collection using the SPSite object and assign itthe hard-coded value of your test site. You could choose to use a different, more genericapproach and use the object model to programmatically retrieve the root SharePoint website. The C# code for this would be:

SPWeb myRootSite = SPControl.GetContextSite(Context).RootWeb;

The Visual Basic equivalent would be:

Dim myRootSite As SPWeb = SPControl.GetContextSite(Context).RootWeb

2. Create an instance of the SharePoint site, and open the site for processing.

3. One property that you set to true for testing purposes is the AllowUnsafeUpdates property.

4. You then assign the string value Survey to the list and check to see if that list exists. If itdoesn’t, the code breaks, but if there is an instance of this list, the code continues on to thenadd one string value (the resulting updateToLikertList string value) to the list by call-ing the Add method to add items to the new SPListItem object and then calling the updatemethod to save the changes to SharePoint. The field must have a list called Answer to add thestring parameter successfully to the list.

If you put all of the above code together, it will resemble the full code sample you pasted into theService.cs or Service.vb file you created earlier. Listing 3-8 displays the entire code sample in C# andthen in VB.

Listing 3-7: New web method to update SharePoint field

C#using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Services;using Microsoft.SharePoint;

[WebService(Namespace = "http://tempuri.org/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]public class Service : System.Web.Services.WebService{

public Service ()

78

Fox c03.tex V3 - 01/30/2009 2:46pm Page 79

Chapter 3: Creating Custom Field Types

{

}

[WebMethod]public void updateLikertList(string userResponse){

string updateToLikertList = null;

if (userResponse == "Strongly Agree"){

updateToLikertList = "1";}else if (userResponse == "Agree"){

updateToLikertList = "2";}else if (userResponse == "Neutral"){

updateToLikertList = "3";}else if (userResponse == "Disagree"){

updateToLikertList = "4";}else if (userResponse == "Strongly Disagree"){

updateToLikertList = "5";}else{

updateToLikertList = "NA";}

using (SPSite mySPSite = new SPSite(@"http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

mySPWeb.AllowUnsafeUpdates = true;string SPListName = "Survey";SPList SPList = null;foreach (SPList currentSPList in mySPWeb.Lists){

if (currentSPList.Title.Equals(SPListName,StringComparison.InvariantCultureIgnoreCase))

{SPList = currentSPList;break;

}}SPListItem newSPListItem = SPList.Items.Add();newSPListItem["Answer"] = updateToLikertList;

Continued

79

Fox c03.tex V3 - 01/30/2009 2:46pm Page 80

Chapter 3: Creating Custom Field Types

Listing 3-7: New web method to update SharePoint field (continued)

newSPListItem.Update();}

}

return;}

}

VBImports System.Collections.GenericImports System.LinqImports System.WebImports System.Web.ServicesImports Microsoft.SharePoint

<WebService([Namespace] := "http://tempuri.org/")><WebServiceBinding(ConformsTo := WsiProfiles.BasicProfile1_1)>Public Class Service

Inherits System.Web.Services.WebService

Public Sub New()End Sub

<WebMethod()>Public Sub updateLikertList(userResponse As String)

Dim updateToLikertList As String = Nothing

If userResponse = "Strongly Agree" ThenupdateToLikertList = "1"

ElseIf userResponse = "Agree" ThenupdateToLikertList = "2"

ElseIf userResponse = "Neutral" ThenupdateToLikertList = "3"

ElseIf userResponse = "Disagree" ThenupdateToLikertList = "4"

ElseIf userResponse = "Strongly Disagree" ThenupdateToLikertList = "5"

ElseupdateToLikertList = "NA"

End If

Using mySPSite As New SPSite("http://stefoxdemo")Using mySPWeb As SPWeb = mySPSite.OpenWeb()

mySPWeb.AllowUnsafeUpdates = TrueDim SPListName As String = "Survey"Dim SPList As SPList = NothingFor Each currentSPList As SPList In mySPWeb.Lists

If currentSPList.Title.Equals(SPListName,StringComparison.InvariantCultureIgnoreCase) Then

SPList = currentSPListExit For

End IfNext

80

Fox c03.tex V3 - 01/30/2009 2:46pm Page 81

Chapter 3: Creating Custom Field Types

Dim newSPListItem As SPListItem = SPList.Items.Add()newSPListItem("Answer") = updateToLikertListnewSPListItem.Update()

End UsingEnd Using

ReturnEnd Sub

End Class

Testing the Web MethodNow that you’ve added the code to your solution, you’ll want to test out the Service to make sure itworks. To test out the code:

1. Change the SPSite value to your own SharePoint default site (if you didn’t use theGetContextSite method) and add a list called Survey to SharePoint with two fields calledQuestion and Answer. To do this, navigate to your SharePoint site, click ‘‘View All SiteContent,’’ and click Create. Under Custom Lists, click ‘‘Custom List,’’ and provide a nameand description and click OK. To add columns to the list, open the list and click ‘‘SiteSettings’’ and ‘‘Create Column.’’ Add a column of type ‘‘Single line of text’’ called Questionand another column of the same type called Answer. You can manually enter a question atthis point, so go ahead and do that, but leave the Answer field blank and then come back tothe Visual Studio Web Service project.

2. Hit [F5]. You’ll be prompted to enable script debugging (for IE).

3. Click Yes to continue. At this point, Visual Studio will open an instance of InternetExplorer and load the Web Service. Figure 3-12 shows what this page looks like. In theupper-left-hand portion of the page, you’ll see the web methods that are in your WebService. Because you only include one, called updateLikertList, this is the only webmethod that is listed on the page.

4. If you click on the web method, this will open another page where you can test theinvocation of the web method (see Figure 3-13). Note here that the input parameter calleduserResponse is the one you created in the method instance in the Visual Studio project.Enter one of the values from the Likert scale (i.e., Strongly Agree, Agree, Neutral, Disagree,or Strongly Disagree), and then click Invoke.

5. When you click on the Invoke button, this will update the Answer field in the Survey list(which you manually created) in your SharePoint site. Figure 3-14 displays the updated fieldlabeled 1 — your code translated the ‘‘Strongly Agree’’ string into a string value of 1 andthen updated the list field with that value.

Deploying the Web ServiceIf you’re working along with us, you’ve now successfully created the Web Service that contains the coreintegration functionality; that is, the bridge between the SharePoint custom field type and the Silverlightapplication. To deploy the Web Service will require:

1. Ensuring that the service DLL (in our case, LikertScaleWebService.dll) is added to the globalassembly cache (GAC); and

81

Fox c03.tex V3 - 01/30/2009 2:46pm Page 82

Chapter 3: Creating Custom Field Types

2. Deploying the service to a location that will allow applications to call the service. The firstpart of this step can be done by clicking Start � All Programs � Microsoft Visual Studio2008 � Visual Studio 2008 Tools, and then right-clicking ‘‘Visual Studio 2008 CommandPrompt’’ and selecting ‘‘Run as Administrator.’’ Navigate to where the service DLL islocated in the command prompt, and then use the gacutil.exe to copy the assembly file tothe GAC. For example:

gacutil.exe -if "YourAssemblyName.dll"

Figure 3-12

Figure 3-13

82

Fox c03.tex V3 - 01/30/2009 2:46pm Page 83

Chapter 3: Creating Custom Field Types

Figure 3-14

You’ll want to make sure that your ASMX file in your project is updated as per the properties of yourassembly that you just copied to your GAC. Listing 3-9 shows the code that we used for our Web Service.

Listing 3-8: ASMX sample code

<%@ WebService Language="C#" Class="Service, LikertScaleWebService, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=a6ddf78b122c208b" %>

You can now deploy the Web Service, which can be done in a couple of ways. For example, you candeploy it to the _layouts folder, or you can deploy it to the _vit_bin folder, a virtual directory withinthe default SharePoint site. In the following example, you’re going to deploy to the _layouts folder, butyou’ll do it in the next section of the chapter as a part of building out the Silverlight and SharePointcustom field type project. To prepare the Web Service for deployment and consumption, though, youfirst need to make sure that the Web Service is compatible with SharePoint. To do this, you need to runthe disco.exe tool against your ASMX file (for us, this is the LikertScaleWebService.asmx file), whichgenerates the .wsdl and .disco files — two necessary files for the discovery and execution of your WebService.

1. First copy-and-paste your ASMX file into the _layouts folder (C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\TEMPLATE\LAYOUTS).

2. Open the Visual Studio 2008 Command Prompt again, making sure to right-click and ‘‘Runas Administrator.’’

3. Type disco and then the path to the ASMX file (see Figure 3-15), for example:

disco http://stefoxdemo/_layouts/LikertScaleWebService.asmx

Note that the disco tool can raise exceptions based on errors detected in your ASMX file.For example, Figure 3-15 has the wrong name for the disco tool to show you the error thatis raised. Other errors to look out for are erroneously referenced classes in the ASMX file,which will raise breaking errors.

4. At this point, you’ve now got three core files for your Web Service in the _layouts folder, forexample:

❑ YourService.asmx

❑ YourService.wsdl; and

❑ YourService.disco

83

Fox c03.tex V3 - 01/30/2009 2:46pm Page 84

Chapter 3: Creating Custom Field Types

Figure 3-15

However, you need to ensure that the WSDL and DISCO files are supportable by SharePoint.

5. To do this, you need to make sure that the .disco file looks like that in Listing 3-10. Note thatyou can copy-and-paste most of this; just be sure to persist the correct binding references(see bolded code) in the new .disco file. The major part that makes them supportable bySharePoint is the top five lines, which include the necessary assemblies from SharePoint.

Listing 3-9: Amended DISCO file

<%@ Page="" Language="C#" Inherits="System.Web.UI.Page" %><%@ Assembly="" Name="Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Import="" Namespace="Microsoft.SharePoint.Utilities" %><%@ Import="" Namespace="Microsoft.SharePoint" %><% Response.ContentType = "text/xml"; %><discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns="http://schemas.xmlsoap.org/disco/"><contractRef

ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)+ "?wsdl"),Response.Output); %>

docRef="=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>

xmlns="http://schemas.xmlsoap.org/disco/scl/" /><soap address=

<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>

xmlns:q1="http://localhost/SLContacts/"binding="q1:LikertServiceSoap"xmlns="http://schemas.xmlsoap.org/disco/soap/" />

<soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>

xmlns:q2="http://localhost/SLContacts/"binding="q2:LikertServiceSoap12"xmlns="http://schemas.xmlsoap.org/disco/soap/" />

</discovery>

84

Fox c03.tex V3 - 01/30/2009 2:46pm Page 85

Chapter 3: Creating Custom Field Types

6. The same five lines of code that you add to the .disco file must be added to the .wsdl file. Theother part of the file you’ll need to change in the .disco file are the SOAP references atthe bottom of the file — see the gray code in Listing 3-11.

Listing 3-10: Amended WSDL file

<%@ Page="" Language="C#" Inherits="System.Web.UI.Page" %><%@ Assembly="" Name="Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Import="" Namespace="Microsoft.SharePoint.Utilities" %><%@ Import="" Namespace="Microsoft.SharePoint" %><% Response.ContentType = "text/xml"; %><wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"

xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

xmlns:tns="http://tempuri.org/"xmlns:s="http://www.w3.org/2001/XMLSchema"xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"

xmlns:http=http://schemas.xmlsoap.org/wsdl/http/targetnamespace="http://tempuri.org/"

xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><wsdl:types>

<s:schema elementformdefault="qualified"targetnamespace="http://tempuri.org/">

<s:element name="updateLikertList"><s:complextype>

<s:sequence><s:element minoccurs="0" maxoccurs="1"

name="userResponse" type="s:string" /></s:sequence>

</s:complextype></s:element><s:element name="updateLikertListResponse">

<s:complextype /></s:element>

</s:schema></wsdl:types><wsdl:message name="updateLikertListSoapIn">

<wsdl:part name="parameters" element="tns:updateLikertList" /></wsdl:message><wsdl:message name="updateLikertListSoapOut">

<wsdl:part name="parameters" element="tns:updateLikertListResponse" /></wsdl:message><wsdl:porttype name="LikertServiceSoap">

<wsdl:operation name="updateLikertList"><wsdl:input message="tns:updateLikertListSoapIn" /><wsdl:output message="tns:updateLikertListSoapOut" />

</wsdl:operation></wsdl:porttype><wsdl:binding name="LikertServiceSoap" type="tns:LikertServiceSoap">

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" /><wsdl:operation name="updateLikertList">

<soap:operation soapaction="http://tempuri.org/updateLikertList"style="document" />

Continued85

Fox c03.tex V3 - 01/30/2009 2:46pm Page 86

Chapter 3: Creating Custom Field Types

Listing 3-10: Amended WSDL file (continued)

<wsdl:input><soap:body use="literal" />

</wsdl:input><wsdl:output>

<soap:body use="literal" /></wsdl:output>

</wsdl:operation></wsdl:binding><wsdl:binding name="LikertServiceSoap12" type="tns:LikertServiceSoap">

<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" /><wsdl:operation name="updateLikertList">

<soap12:operationsoapaction="http://tempuri.org/updateLikertList" style="document" />

<wsdl:input><soap12:body use="literal" />

</wsdl:input><wsdl:output>

<soap12:body use="literal" /></wsdl:output>

</wsdl:operation></wsdl:binding><wsdl:service name="LikertService">

<wsdl:port name="LikertServiceSoap" binding="tns:LikertServiceSoap"><soap:address location=

"<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output);%>" />

</wsdl:port><wsdl:port name="LikertServiceSoap12" binding="tns:LikertServiceSoap12">

<soap12:address location="<%SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output);%>" />

</wsdl:port></wsdl:service>

</wsdl:definitions>

7. To complete the process of making the Web Service compatible with SharePoint,there is one final step: Rename the WSDL and DISCO files as ASPX files (e.g.,LikertScaleWebServicedisco.aspx). SharePoint does not support straight .wsdl and.disco files, but instead requires you to create ‘‘re-direction’’ pages. Figure 3-16 displays thefinal Web Service files that you should now similarly have (with your own assembly names,of course) in your _layouts folder.

At this point, you can put the Web Service development work aside. You’ll use the files we just createdin the next section of the chapter, but first you want to go ahead and build out the Silverlight applicationand the SharePoint custom field type.

You can also deploy Web Services to the _vti_bin folder for consumption in SharePoint. For a completewalk-through on the latter, see: http://msdn.microsoft.com/en-us/library/ms464040.aspx.

86

Fox c03.tex V3 - 01/30/2009 2:46pm Page 87

Chapter 3: Creating Custom Field Types

You can also deploy Web Services or Windows Communication Foundation (WCF) services as well totheir own IIS web application. To do this is a little more involved than what we’ve discussed above. Formore information, see: http://msdn.microsoft.com/en-us/library/aa480190.aspx.

Figure 3-16

Creating the Silverlight and SharePoint IntegrationIn this section, you’ll create the Silverlight application and also add the SharePoint custom field type asa project to the solution. This way, you can create dependencies across the two projects and more easilycontrol the deployment and cleanup of the project files when refactoring the code. To start, then, let’screate a blank solution and then progressively add all of the pieces we need to complete the Silverlightand SharePoint integration.

To create a blank solution:

1. Open a new instance of Visual Studio 2008, and then click File � New Project. Under OtherProject Types, click ‘‘Visual Studio Solutions,’’ and then click ‘‘Blank Solution.’’

2. Provide a name (e.g., WroxChapterThreeSLSP) and a location for your solution.

3. After you’ve done this, right-click on the Solution and select Add � New Project, and selectthe Silverlight project category.

4. In the Templates pane, select ‘‘Silverlight Application,’’ provide a name for your application,and click OK.

5. When prompted, select ‘‘Automatically generate a test page to host Silverlight at buildtime.’’ This will add the Silverlight application to your blank solution.

Silverlight Application User InterfaceAs you’ve seen in past chapters, the core components of the Silverlight application are the Page.xaml fileand the Page.xaml.cs (or Page.xaml.vb) file. In this chapter, you’ll create a simple control that you’ll ren-der inside of the custom field type. (In future chapters, you’ll see more complex Silverlight applicationsthat have multiple .xaml files interacting with one another.)

The Page.xaml file contains several controls that are hosted on a Canvas object. We have spruced up thecanvas with a little bit of gradient and a Silverlight image, but since neither one of us is a design expert,we’ll leave the heavy design imagination to you — our very smart readers. The main elements of ourSilverlight control are:

1. A textbox that provides some title text for the control

2. Five radio buttons for each of the Likert scale options

3. A button that will pass the user selection to an event that calls the Web Service (which willupdate the list). Listing 3-12 shows the code for the Silverlight control user interface (UI).

87

Fox c03.tex V3 - 01/30/2009 2:46pm Page 88

Chapter 3: Creating Custom Field Types

Note that we’ve used a button as the post to the list, but a more streamlined approach mightbe using a postback to push a hidden value and then add that to the list. This approachnegates the need for a button control within the Silverlight application. For simplicity ofillustration, we’ve added a control that handles the posting of the value to the field.

Listing 3-11: Page.xaml file

<UserControl x:Class="FinalWroxSLAppC3v2.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="365" Height="235"><Canvas x:Name="LayoutRoot">

<Canvas.Background><LinearGradientBrush>

<GradientStop Color="White" Offset="0" /><GradientStop Color="LightGray" Offset="1" />

</LinearGradientBrush></Canvas.Background>

<TextBlock x:Name="titleBlock"Canvas.Top="10"Canvas.Left="120"FontSize="13"FontWeight="bold"Margin="3">

- Likert Scale -</TextBlock>

<Image Source="Images/logoSL.jpg"Height="50"Canvas.Left="190"Canvas.Top="80" >

</Image>

<Image Source="Images/logoSL.jpg"Height ="50"Canvas.Left="190"Canvas.Top="180"RenderTransformOrigin="0.0,0.0">

<Image.RenderTransform><ScaleTransform ScaleY="-1"></ScaleTransform>

</Image.RenderTransform><Image.OpacityMask>

<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"><GradientStop Color="#00000000" Offset="0.5"/><GradientStop Color="#FFFFFFFF" Offset="1.0"/>

</LinearGradientBrush></Image.OpacityMask>

</Image>

<RadioButton x:Name="radioBtnStronglyAgree"Canvas.Top="40"Canvas.Left="50"

88

Fox c03.tex V3 - 01/30/2009 2:46pm Page 89

Chapter 3: Creating Custom Field Types

Content="Strongly Agree"IsChecked="true"Background="Blue"Margin="3"MouseEnter="radioBtnStronglyAgree_MouseEnter"MouseLeave="radioBtnStronglyAgree_MouseLeave"Click="radioBtnStronglyAgree_Click">

</RadioButton><RadioButton x:Name="radioBtnAgree"

Canvas.Top="70"Canvas.Left="50"Content="Agree"Background="Blue"Margin="3"MouseEnter="radioBtnAgree_MouseEnter"MouseLeave="radioBtnAgree_MouseLeave"Click="radioBtnAgree_Click">

</RadioButton><RadioButton x:Name="radioBtnNeutral"

Canvas.Top="100"Canvas.Left="50"Content="Neutral"Background="Blue"Margin="3"MouseEnter="radioBtnNeutral_MouseEnter"MouseLeave="radioBtnNeutral_MouseLeave"Click="radioBtnNeutral_Click">

</RadioButton><RadioButton x:Name="radioBtnDisagree"

Canvas.Top="130"Canvas.Left="50"Content="Disagree"Background="Blue"Margin="3"MouseEnter="radioBtnDisagree_MouseEnter"MouseLeave="radioBtnDisagree_MouseLeave"Click="radioBtnDisagree_Click">

</RadioButton><RadioButton x:Name="radioBtnStronglyDisagree"

Canvas.Top="160"Canvas.Left="50"Content="Strongly Disagree"Background="Blue"Margin="3"MouseEnter="radioBtnStronglyDisagree_MouseEnter"MouseLeave="radioBtnStronglyDisagree_MouseLeave"Click="radioBtnStronglyDisagree_Click">

</RadioButton><Button x:Name="btnEnterResponse"

Canvas.Left="50"Width="75"Height="25"

Continued

89

Fox c03.tex V3 - 01/30/2009 2:46pm Page 90

Chapter 3: Creating Custom Field Types

Listing 3-11: Page.xaml file (continued)

Content="Submit"Canvas.Top="200"Click="btnEnterResponse_Click"ToolTipService.ToolTip="Click to Submit Response to

SharePoint List."></Button></Canvas>

</UserControl>

You’ll also note that in the XAML code, you’ve added a number of event handlers. For example, for eachof the radio buttons, you’ll see a MouseEnter and MouseLeave event. These are events that we addedto illustrate that you can do more with the radio buttons than just have a user selection. You can, forexample, simply change the text formatting as we’ve done in this example, or you could affect otherparts of a larger Silverlight application — think changing menu options depending on a user selection.When rendered in the Visual Studio Cider designer, the UI appears as illustrated in Figure 3-17.

Figure 3-17

Silverlight Application Code-BehindThe code-behind that maps to the Silverlight application is fairly straightforward (see Listing 3-13). Foreach of the MouseEnter and MouseLeave events, we’ve added some code that changes the formattingof the radio button text (the text property is expressed as Content in the radio button control). Noticethat we’ve also created a class-level string variable called userResponseFromXAML. This is the currentselection of the user and represents the string that will get passed to the Web Service. The main eventthat will call the Web Service is the btnEnterResponse_Click event, and if you remember the WebService logic, it accepts the string parameter and then checks to see if the string is of a certain Likert scaleoption. Depending on the value, it then translates the value into an integer value between 1 and 5. (Theextrapolation here would be using the numerical values for statistical analyses.) Note that we’ve added aplaceholder for the Web Service code, which is discussed later in the chapter.

90

Fox c03.tex V3 - 01/30/2009 2:46pm Page 91

Chapter 3: Creating Custom Field Types

Listing 3-12: XAML code-behind

C#using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.ServiceModel;

namespace FinalWroxSLAppC3v2{

public partial class Page : UserControl{

public Page(){

InitializeComponent();}

string userResponseFromXAML = null;

//Mouse events for the Strongly Agree option.private void radioBtnStronglyAgree_MouseEnter(object sender,

MouseEventArgs e){

radioBtnStronglyAgree.FontWeight = FontWeights.Bold;}

private void radioBtnStronglyAgree_MouseLeave(object sender,MouseEventArgs e)

{radioBtnStronglyAgree.FontWeight = FontWeights.Normal;

}//Mouse events for the Agree option.private void radioBtnAgree_MouseEnter(object sender, MouseEventArgs e){

radioBtnAgree.FontWeight = FontWeights.Bold;}

private void radioBtnAgree_MouseLeave(object sender, MouseEventArgs e){

radioBtnAgree.FontWeight = FontWeights.Normal;}//Mouse events for the Neutral option.private void radioBtnNeutral_MouseEnter(object sender, MouseEventArgs e){

radioBtnNeutral.FontWeight = FontWeights.Bold; Continued

91

Fox c03.tex V3 - 01/30/2009 2:46pm Page 92

Chapter 3: Creating Custom Field Types

Listing 3-12: XAML code-behind (continued)

}

private void radioBtnNeutral_MouseLeave(object sender, MouseEventArgs e){

radioBtnNeutral.FontWeight = FontWeights.Normal;}//Mouse events for the Disagree option.private void radioBtnDisagree_MouseEnter(object sender, MouseEventArgs e){

radioBtnDisagree.FontWeight = FontWeights.Bold;}private void radioBtnDisagree_MouseLeave(object sender, MouseEventArgs e){

radioBtnDisagree.FontWeight = FontWeights.Normal;}//Mouse events for the Strongly Disagree option.private void radioBtnStronglyDisagree_MouseEnter(object sender,

MouseEventArgs e){

radioBtnStronglyDisagree.FontWeight = FontWeights.Bold;}

private void radioBtnStronglyDisagree_MouseLeave(object sender,MouseEventArgs e)

{radioBtnStronglyDisagree.FontWeight = FontWeights.Normal;

}

//Setting the class-level string variable for each selected radio button.private void radioBtnStronglyAgree_Click(object sender, RoutedEventArgs e){

userResponseFromXAML = radioBtnStronglyAgree.Content.ToString();}

private void radioBtnAgree_Click(object sender, RoutedEventArgs e){

userResponseFromXAML = radioBtnAgree.Content.ToString();}

private void radioBtnNeutral_Click(object sender, RoutedEventArgs e){

userResponseFromXAML = radioBtnNeutral.Content.ToString();}

private void radioBtnDisagree_Click(object sender, RoutedEventArgs e){

userResponseFromXAML = radioBtnDisagree.Content.ToString();}

private void radioBtnStronglyDisagree_Click(object sender,RoutedEventArgs e)

{userResponseFromXAML = radioBtnStronglyDisagree.Content.ToString();

}

92

Fox c03.tex V3 - 01/30/2009 2:46pm Page 93

Chapter 3: Creating Custom Field Types

//Calling the Web service to update the ‘Answer’ column with theselected Likert scale response.

private void btnEnterResponse_Click(object sender, RoutedEventArgs e){

//Web service code goes here.}

}

VBImports System.Collections.GenericImports System.LinqImports System.NetImports System.WindowsImports System.Windows.ControlsImports System.Windows.DocumentsImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.AnimationImports System.Windows.ShapesImports System.ServiceModel

Namespace FinalWroxSLAppC3v2Public Partial Class Page

Inherits UserControlPublic Sub New()

InitializeComponent()End Sub

Private userResponseFromXAML As String = Nothing

Private Sub radioBtnStronglyAgree_MouseEnter(sender As Object,e As MouseEventArgs)

radioBtnStronglyAgree.FontWeight = FontWeights.BoldEnd Sub

Private Sub radioBtnStronglyAgree_MouseLeave(sender As Object,e As MouseEventArgs)

radioBtnStronglyAgree.FontWeight = FontWeights.NormalEnd Sub

Private Sub radioBtnAgree_MouseEnter(sender As Object, eAs MouseEventArgs)

radioBtnAgree.FontWeight = FontWeights.BoldEnd Sub

Private Sub radioBtnAgree_MouseLeave(sender As Object, eAs MouseEventArgs)

radioBtnAgree.FontWeight = FontWeights.NormalEnd Sub

Private Sub radioBtnNeutral_MouseEnter(sender As Object, eAs MouseEventArgs)

radioBtnNeutral.FontWeight = FontWeights.Bold

Continued

93

Fox c03.tex V3 - 01/30/2009 2:46pm Page 94

Chapter 3: Creating Custom Field Types

Listing 3-12: XAML code-behind (continued)

End Sub

Private Sub radioBtnNeutral_MouseLeave(sender As Object, eAs MouseEventArgs)

radioBtnNeutral.FontWeight = FontWeights.NormalEnd Sub

Private Sub radioBtnDisagree_MouseEnter(sender As Object, eAs MouseEventArgs)

radioBtnDisagree.FontWeight = FontWeights.BoldEnd SubPrivate Sub radioBtnDisagree_MouseLeave(sender As Object, e

As MouseEventArgs)radioBtnDisagree.FontWeight = FontWeights.Normal

End Sub

Private Sub radioBtnStronglyDisagree_MouseEnter(sender AsObject, e As MouseEventArgs)

radioBtnStronglyDisagree.FontWeight = FontWeights.BoldEnd Sub

Private Sub radioBtnStronglyDisagree_MouseLeave(sender AsObject, e As MouseEventArgs)

radioBtnStronglyDisagree.FontWeight = FontWeights.NormalEnd Sub

Private Sub radioBtnStronglyAgree_Click(sender As Object, eAs RoutedEventArgs)

userResponseFromXAML = radioBtnStronglyAgree.Content.ToString()End Sub

Private Sub radioBtnAgree_Click(sender As Object, e As RoutedEventArgs)userResponseFromXAML = radioBtnAgree.Content.ToString()

End Sub

Private Sub radioBtnNeutral_Click(sender As Object, eAs RoutedEventArgs)

userResponseFromXAML = radioBtnNeutral.Content.ToString()End Sub

Private Sub radioBtnDisagree_Click(sender As Object, eAs RoutedEventArgs)

userResponseFromXAML = radioBtnDisagree.Content.ToString()End Sub

Private Sub radioBtnStronglyDisagree_Click(sender As Object, eAs RoutedEventArgs)

userResponseFromXAML =radioBtnStronglyDisagree.Content.ToString()

End Sub

Private Sub btnEnterResponse_Click(sender As Object, eAs RoutedEventArgs)

94

Fox c03.tex V3 - 01/30/2009 2:46pm Page 95

Chapter 3: Creating Custom Field Types

‘Web service code goes here.End Sub

End ClassEnd Namespace

At this point, right-click on the Silverlight project node and select Build. Make sure that the projectbuilds. You can right-click on the project, select Debug, and then ‘‘Start a New Instance’’ to test outthe functionality of the application. At this point, note that the Web Service will not work because youhaven’t hooked it up. To do this, you need to deploy the Silverlight application where it can securely callthe Web Service. Let’s move on to creating the custom field type, and then we’ll come back to the WebService to complete this chapter.

Creating the SharePoint Custom Field TypeIn this section, you use the same solution in which the Silverlight application lives to create the SharePointcustom field type:

1. In this solution, right-click on the solution and select Add, and then choose New Project.

2. In the Project types category, select SharePoint, and then select Empty. Provide a name foryour project (e.g., SLCustomFieldType). This creates a shell SharePoint project for you usingthe VSeWSS 1.2 add-on functionality; however, you need to add a project item template. Todo this, right-click on the project, and select Add and then ‘‘New Item.’’

3. In the Add New Item dialog, select the SharePoint category and then click on the Field Con-trol item template, provide a name (e.g., SLSPlikertField), and click OK. This will add someprerequisite files to your solution, which you will use to customize the field type.

At this point, there are two key files you need to take a look at. The first is the *.field.cs (or vb) file, and thesecond is the *.fieldcontrol.cs (or vb) file. The first of these files (in our case, the SLSPLikertField.field.cs)is the file that will render the custom field type. Earlier in the chapter, we used these two class filesto create the ASP-based custom field type. There is little difference in the field type class across theASP-based approach and the Silverlight-based approach: Both have the same field constructors andthe same override property, the FieldRenderingControl. You can see this in the sample code listed inListing 3-14.

Listing 3-13: Custom field type code

C#using System;using System.Runtime.InteropServices;using System.Security.Permissions;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;using Microsoft.SharePoint.Security;

namespace SLCustomFieldType{

[CLSCompliant(false)]

Continued

95

Fox c03.tex V3 - 01/30/2009 2:46pm Page 96

Chapter 3: Creating Custom Field Types

Listing 3-13: Custom field type code (continued)

[Guid("751ec33e-b741-44e5-a420-c4bf2e6ded6c")]public class SLSPLikertFieldField : SPFieldText{

public SLSPLikertFieldField(SPFieldCollection fields, string fieldName): base(fields, fieldName)

{}

public SLSPLikertFieldField(SPFieldCollection fields, stringtypeName, string displayName)

: base(fields, typeName, displayName){}

public override BaseFieldControl FieldRenderingControl{

[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]get{

BaseFieldControl fieldControl = new SLSPLikertFieldFieldControl();fieldControl.FieldName = this.InternalName;

return fieldControl;}

}}

}

VBImports System.Runtime.InteropServicesImports System.Security.PermissionsImports Microsoft.SharePointImports Microsoft.SharePoint.WebControlsImports Microsoft.SharePoint.Security

Namespace SLCustomFieldType

<CLSCompliant(False)> _<Guid("751ec33e-b741-44e5-a420-c4bf2e6ded6c")>Public Class SLSPLikertFieldField

Inherits SPFieldTextPublic Sub New(fields As SPFieldCollection, fieldName As String)

MyBase.New(fields, fieldName)End Sub

Public Sub New(fields As SPFieldCollection, typeName As String,displayName As String)

MyBase.New(fields, typeName, displayName)End Sub

Public Overloads Overrides ReadOnly PropertyFieldRenderingControl() As BaseFieldControl

<SharePointPermission(SecurityAction.LinkDemand,ObjectModel := True)>

Get

96

Fox c03.tex V3 - 01/30/2009 2:46pm Page 97

Chapter 3: Creating Custom Field Types

Dim fieldControl As BaseFieldControl = NewSLSPLikertFieldFieldControl()

fieldControl.FieldName = AddressOf Me.InternalName

Return fieldControlEnd Get

End PropertyEnd Class

End Namespace

In the other class (in our case, SLSPLikertField.fieldcontrol.cs) that is created by the project, where thecustom field control is defined, it has some differences across these two classes. You’ll note that in thissecond class, you create an HTMLInputHidden field, which is an optional field that you can use to passparameters to SharePoint from your Silverlight application. Also, you create an override method thatchecks to see if there is a ScriptManager object loaded (similar to what you did when you hostedthe Silverlight application in a Web Part in Chapter 2), and then you assigned some variables usingthe HTMLInputHidden field and added an instance of the Silverlight control within the ChildControlsmethod, which essentially creates an instance of the Silverlight application and renders it as a control,sets the appropriate properties on the control, and then adds it to SharePoint using the Add methodpassing it the Silverlight application (or the custom control that you created earlier in the chapter). List-ing 3-15 provides code samples in C# and VB for the rendering of the custom Silverlight application as acustom field type.

Listing 3-14: Rendering of custom field type

C#using System;using System.Runtime.InteropServices;using Microsoft.SharePoint;using Microsoft.SharePoint.WebControls;using System.Web.UI.SilverlightControls;using System.Web.UI.HtmlControls;using System.Web.UI.WebControls;using System.Web.UI;

namespace SLCustomFieldType{

[CLSCompliant(false)][Guid("a2dcddd4-a4e5-4a5e-9ee1-7b923f98489b")]public class SLSPLikertFieldFieldControl : TextField{

public SLSPLikertFieldFieldControl(){

}

private HtmlInputHidden valueField;

protected override void OnInit(EventArgs e){

Continued

97

Fox c03.tex V3 - 01/30/2009 2:46pm Page 98

Chapter 3: Creating Custom Field Types

Listing 3-14: Rendering of custom field type (continued)

base.OnInit(e);ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);if (scriptManager == null){

scriptManager = new ScriptManager();this.Controls.AddAt(0, scriptManager);

}}

public override object Value{

get{

EnsureChildControls();return valueField.Value;

}set{

EnsureChildControls();valueField.Value = value.ToString();

}}

protected override void CreateChildControls(){

if (this.ControlMode == SPControlMode.Edit || this.ControlMode ==SPControlMode.New)

{valueField = new HtmlInputHidden();valueField.ID = "LikertScaleControl";valueField.Name = "LikertScaleControl";base.Controls.Add(valueField);

System.Web.UI.SilverlightControls.SilverlightsilverlightControl = new System.Web.UI.SilverlightControls.Silverlight();

silverlightControl.ID = "LikerScaleControl";silverlightControl.Source =

"http://stefoxdemo/XAPS/FinalWroxSLAppC3v2.xap";silverlightControl.Width = new System.Web.UI.WebControls.Unit(365);silverlightControl.Height = new

this.Controls.Add(silverlightControl);

}}

}}

VBImports System.Runtime.InteropServicesImports Microsoft.SharePointImports Microsoft.SharePoint.WebControls

98

Fox c03.tex V3 - 01/30/2009 2:46pm Page 99

Chapter 3: Creating Custom Field Types

Imports System.Web.UI.SilverlightControlsImports System.Web.UI.HtmlControlsImports System.Web.UI.WebControlsImports System.Web.UI

Namespace SLCustomFieldType<CLSCompliant(False)><Guid("a2dcddd4-a4e5-4a5e-9ee1-7b923f98489b")>Public Class SLSPLikertFieldFieldControl

Inherits TextField

Public Sub New()End Sub

Private valueField As HtmlInputHidden

Protected Overloads Overrides Sub OnInit(e As EventArgs)MyBase.OnInit(e)Dim scriptManager__1 As ScriptManager =

ScriptManager.GetCurrent(AddressOf Me.Page)If scriptManager__1 Is Nothing Then

scriptManager__1 = New ScriptManager()AddressOf Me.Controls.AddAt(0, scriptManager__1)

End IfEnd Sub

Public Overloads Overrides Property Value() As ObjectGet

EnsureChildControls()Return AddressOf valueField.Value

End GetSet

EnsureChildControls()AddressOf valueField.Value = value.ToString()

End SetEnd Property

Protected Overloads Overrides Sub CreateChildControls()If AddressOf Me.ControlMode = SPControlMode.Edit OrElse

AddressOf Me.ControlMode = SPControlMode.[New] ThenvalueField = New HtmlInputHidden()AddressOf valueField.ID = "LikertScaleControl"AddressOf valueField.Name = "LikertScaleControl"AddressOf MyBase.Controls.Add(valueField)

Dim silverlightControl As NewSystem.Web.UI.SilverlightControls.Silverlight()

silverlightControl.ID = "LikerScaleControl"silverlightControl.Source =

"http://stefoxdemo/XAPS/FinalWroxSLAppC3v2.xap"silverlightControl.Width = New

System.Web.UI.WebControls.Unit(365)silverlightControl.Height = New

Continued

99

Fox c03.tex V3 - 01/30/2009 2:46pm Page 100

Chapter 3: Creating Custom Field Types

Listing 3-14: Rendering of custom field type (continued)

AddressOf Me.Controls.Add(silverlightControl)End If

End Sub

End ClassEnd Namespace

At this point, if you’ve been following along, you should be able to successfully build the applica-tion. There are a couple of things that you might want to do, though, before you go ahead and test theapplication:

❑ Make sure that your SharePoint site is set as the correct server in the Debug tab in your projectproperties — your server URL or http://localhost should be set correctly in the ‘‘Startbrowser with URL’’ field.

❑ Make sure that you set a dependency from the SharePoint custom field type project to the Sil-verlight application, so if you build the SharePoint custom field type, it automatically builds thelatest code from the Silverlight application. To do this, right-click on the SharePoint custom fieldtype project and select ‘‘Project Dependencies.’’ Click on the checkbox beside your Silverlightapplication. (See Figure 3-18.)

Figure 3-18

❑ Right-click on the SharePoint custom field type project, and select Add, New Item. Select theSharePoint category and then select the Module item. The Module item provides a way for youto bundle objects with your SharePoint project via the feature that is created when you deploythe WSP (essentially the standard package of files that SharePoint uses when deploying features)to the SharePoint site. Provide a name for your new Module (e.g., SLCustomFieldCtrl) and thenremove the sample.txt file from the project. What you’ll do is add a link to the Silverlight XAPfile so that it is also packaged and deployed as part of the feature. To do this, right-click on theModule root-level item and select Add, and then select ‘‘Existing Item.’’ Browse to the built XAPfile in your solution folder hierarchy, select it, and then click ‘‘Add as Link.’’ You’ll also needto edit the module.xml file. Listing 3-16 shows you the module.xml file that accompanied our

100

Fox c03.tex V3 - 01/30/2009 2:46pm Page 101

Chapter 3: Creating Custom Field Types

solution file. Essentially, the Module Name attribute must match the name you provided foryour module, and the URL is a folder on your SharePoint site that will be created during deploy-ment. Also, the File Path and URL must point to the additional object you want to bundle withyour feature. In this case, the XAP file is located in the Module folder, so you don’t need anymore information than is included below for these two attributes.

Listing 3-15: Module XML file

<?xml version="1.0" encoding="utf-8"?><Elements Id="8e1ade22-8bde-46d9-b5f0-6fcc9400cb92"xmlns="http://schemas.microsoft.com/sharepoint/">

<Module Name="SLCustomFieldCtrl" Url="XAPS"><File Path="FinalWroxSLAppC3v2.xap" Url="FinalWroxSLAppC3v2.xap" />

</Module></Elements>

At this point, you can test-run the application by right-clicking on the SharePoint custom field typeproject (ours is called SLCustomFieldType) and then clicking Deploy. The custom field type will auto-matically be deployed to your SharePoint site. During this process, Visual Studio generates a field typedefinition file — essentially an XML file that provides key information about the custom field type youjust deployed. This is generated when you first created the SharePoint Field Type project; however,it is not filled in with the correct data that SharePoint needs until you deploy. Listing 3-17 provides asampling of the field type definition file from the sample solution we created.

Listing 3-16: Field type definition file

<?xml version="1.0" encoding="utf-8"?><FieldTypes>

<FieldType><Field Name="TypeName">SLSPLikertFieldField</Field><Field Name="TypeDisplayName">SLSPLikertFieldField</Field><Field Name="TypeShortDescription">SLSPLikertFieldField</Field><Field Name="ParentType">Text</Field><Field Name="UserCreatable">TRUE</Field><Field Name="FieldTypeClass">751ec33e-b741-44e5-a420-c4bf2e6ded6c</Field>

</FieldType></FieldTypes>

If you’ve done everything discussed in this chapter, you should now have deployed a semi-workingSilverlight application that is rendered as a custom field type. Remember that you’ll want to create alist called Survey and then click Settings � Create Column; select the custom field type you just createdand deployed to SharePoint, provide a name for it, and select OK. While we’ve not discussed testing theapplication until now, we recommend that you test as you add on each specific component. That way, ifsomething does fail, it is easier to troubleshoot along the way.

Let’s now move on to the final part of the chapter: integrating the Web Service into your newSilverlight-based custom field type.

Adding the Web ReferenceEarlier in this chapter, you created the Web Service that makes a call into SharePoint and updates a fielditem within a list. The Service itself, at least codewise, is somewhat trivial. The hookup, as you’ve seen,

101

Fox c03.tex V3 - 01/30/2009 2:46pm Page 102

Chapter 3: Creating Custom Field Types

requires a few steps to be completed. That said, remember that you’ll be able to reuse these steps acrossmost service integrations with SharePoint so all of the walk-through in this chapter is not just specificto the development of Silverlight-enabled custom field types. For the remainder of this chapter, you’regoing to take the Service created earlier and integrate it with the SharePoint project you just created. Theeventual goal, then, will be to deploy the solution discussed in this chapter that will drop a Silverlightapplication to your server, register two features [the field control module (with the XAP in it) and thecustom field control that renders the Silverlight application], and then have the Silverlight applicationcall the Web Service to update SharePoint.

Follow these steps:

1. The first thing you’ll want to do is open up the solution file again (ours was calledWroxChapterThreeSLSP.sln).

2. Next right-click on the SharePoint custom field type project, and select Add and then ‘‘NewFolder.’’

3. Give the folder a name (e.g., CustomFieldService), and then right-click and select Add andthen select Class and provide a name for the class (e.g., LikertService).

4. Now copy-and-paste the code from the Web Service class into this class and save it. If you’veforgotten what that code looks like, we’ve added it in Listing 3-18 for your reference. Thereason we’re doing this is to package the service with the solution as well, so all of the codegets deployed alongside the features.

Listing 3-17: Copied Web Service code

using System;using System.Collections.Generic;using System.Data.Linq;using System.Text;using System.Web.Services;using Microsoft.SharePoint;

namespace SLCustomFieldType.CustomFieldService{

[WebService(Namespace = "http://tempuri.org/")]class LikertService{

[WebMethod]public void updateLikertList(string userResponse){

string updateToLikertList = null;

if (userResponse == "Strongly Agree"){

updateToLikertList = "1";}else if (userResponse == "Agree"){

updateToLikertList = "2";}

102

Fox c03.tex V3 - 01/30/2009 2:46pm Page 103

Chapter 3: Creating Custom Field Types

else if (userResponse == "Neutral"){

updateToLikertList = "3";}else if (userResponse == "Disagree"){

updateToLikertList = "4";}else if (userResponse == "Strongly Disagree"){

updateToLikertList = "5";}else{

updateToLikertList = "NA";}

using (SPSite mySPSite = new SPSite(@"http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

mySPWeb.AllowUnsafeUpdates = true;string SPListName = "Survey";SPList SPList = null;foreach (SPList currentSPList in mySPWeb.Lists){

if (currentSPList.Title.Equals(SPListName,StringComparison.InvariantCultureIgnoreCase))

{SPList = currentSPList;break;

}}SPListItem newSPListItem = SPList.Items.Add();newSPListItem["Answer"] = updateToLikertList;newSPListItem.Update();

}}

return;}}

}

5. The next thing you’ll need to do is right-click on the Templates folder (which should onlyhave an XML folder with the field type definition file in it) and select Add � New Folder.

6. Call the new folder LAYOUTS. And then right-click and add one more folder and provide aname for it (e.g., LikertWebService). You’ll use this folder to store the Web Service files.

7. To add them, right-click on the folder and click Add, Existing Item, and then navigate to the_layouts folder and add the *.asmx file, the *disco.aspx file, and the *wsdl.aspx file.

103

Fox c03.tex V3 - 01/30/2009 2:46pm Page 104

Chapter 3: Creating Custom Field Types

Figure 3-19 provides a snapshot of what your solution hierarchy should look like.

Note that you’ve also got your Service added, which is what you’ll finish up with next.

Figure 3-19

To understand what will get deployed to SharePoint, take a look at the WSP view in the SharePointsolution. To open the view, do the following:

1. Click on the WSP tab beside the Solution Explorer tab, or click View, Other Windows, andWSP View. Figure 3-20 shows what will get bundled and deployed (and where it will getdeployed in the case of the folder within the Templates directory) as features within thesolution.

2. At this point, you can add your reference to the Web Service and add the service-callingcode, which will interact with the SharePoint object model. To do this, navigate back to theSolution Explorer view, right-click ‘‘Service Reference,’’ and select ‘‘Add Service Reference.’’Paste the service address into the Address field and click Go. This will load your Servicefrom the address in the Services pane. Expand the Service node to view the object withinit (e.g., ServiceSoap). If you click on the Service, any web methods that were successfullyregistered with the service will appear in the Operations pane. Figure 3-21 shows the factthat in the created service, there is only one method: updateLikertList.

104

Fox c03.tex V3 - 01/30/2009 2:46pm Page 105

Chapter 3: Creating Custom Field Types

Figure 3-20

Figure 3-21

The updateLikertList method, as you’ve seen, accepts a string parameter and makes a call intoSharePoint and updates the SharePoint list. The calling code, then, must pass a string parameter to theweb method. If you remember back to earlier in the chapter, you saw the code from the Page.xaml.csfile, but the service-calling code from the btnEnterResponse_Click event was left out. Listing 3-19shows this code. Of note here is that you first need to create a service proxy, an instance of the serviceif you will. You then need to create an event handler, after which you can call the updateLIkertList(or because this is an asynchronous call, the updateLikertListAsync) method, passing in theuserResponseFromXAML — the class-level string variable that represents the user selection from theselected radio button.

105

Fox c03.tex V3 - 01/30/2009 2:46pm Page 106

Chapter 3: Creating Custom Field Types

Listing 3-18: Service-calling code

C#namespace FinalWroxSLAppC3{

public partial class Page : UserControl{

public Page(){

InitializeComponent();}

string userResponseFromXAML = null;

. . .

private void btnEnterResponse_Click(object sender, RoutedEventArgs e){

FinalWroxSLAppC3v2.MyService.LikertServiceSoapClient myWSProxy =new FinalWroxSLAppC3v2.MyService.LikertServiceSoapClient();

myWSProxy.updateLikertListCompleted += newEventHandler<System.ComponentModel.AsyncCompletedEventArgs>(myWSProxy_updateLikertListCompleted);

myWSProxy.updateLikertListAsync(userResponseFromXAML);}

void myWSProxy_updateLikertListCompleted(object sender,System.ComponentModel.AsyncCompletedEventArgs e)

{MessageBox.Show("The Survey list has been updated.");

}

}}

VBNamespace FinalWroxSLAppC3

Public Partial Class PageInherits UserControlPublic Sub New()

InitializeComponent()End Sub

Private userResponseFromXAML As String = Nothing

Private Sub btnEnterResponse_Click(sender As Object, e AsRoutedEventArgs)

Dim myWSProxy As NewFinalWroxSLAppC3v2.MyService.LikertServiceSoapClient()

myWSProxy.updateLikertListCompleted += NewEventHandler(Of System.ComponentModel.AsyncCompletedEventArgs)(AddressOfmyWSProxy_updateLikertListCompleted)

106

Fox c03.tex V3 - 01/30/2009 2:46pm Page 107

Chapter 3: Creating Custom Field Types

myWSProxy.updateLikertListAsync(userResponseFromXAML)End Sub

Private Sub myWSProxy_updateLikertListCompleted(sender AsObject, e As System.ComponentModel.AsyncCompletedEventArgs)

MessageBox.Show("The Survey list has been updated.")End Sub

End ClassEnd Namespace

Deploying the SolutionWith all of this now done, you can rebuild the entire solution to make sure that everything compiles. Youcan also deploy the solution. The great thing about VSeWSS 1.2 is that it will deploy all of the necessaryfeatures to where you want them on your SharePoint server. After you successfully deploy your solution,navigate to your SharePoint site:

1. Click on the Survey site, click Settings � Create Column, provide a name for your column,and add the custom field type to your list by clicking OK. This will reload the list.

2. Click New on the list, and your custom field type should appear.

Figure 3-22

107

Fox c03.tex V3 - 01/30/2009 2:46pm Page 108

Chapter 3: Creating Custom Field Types

3. Select one of the radio buttons from the Silverlight application, mouse over the Submit tomake sure that the tool tip works, and then click Submit. Assuming that the Web Service callwas successful (if it is, it calls the myWSProxy_updateLikertListCompleted event), a mes-sage box will display a list update message.

4. To test whether the app added updated the field, click OK to exit List Edit mode.Figures 3-22 and 3-23 illustrate the user experience for this custom field type.

Figure 3-23

If your update was successful, you can load the Survey page to see the Answer you submitted (translatedinto numerical value) (see Figure 3-24).

Figure 3-24

And that’s it, you’ve now built your first Silverlight-based custom field type.

108

Fox c03.tex V3 - 01/30/2009 2:46pm Page 109

Chapter 3: Creating Custom Field Types

SummaryOne thing we didn’t cover in this chapter (which will be covered in Chapter 6) is adding an event receiverto retract a specific feature once you’ve deployed it. You can retract it manually, but you need to knowwhat files and folders to delete. Chapter 6 talks more about adding an event receiver to the solution sothat when you retract a feature it performs all of the necessary cleanup for you.

We did, however, cover quite a few other things in this chapter. And while we started by showing you asimple ASP-based custom control, we ended on a fuller examination of creating a Silverlight-based appli-cation or, more accurately, a Silverlight control that is rendered within a custom field type. Rememberthat a lot of what you walked through in this chapter can be applied in many other places — think of itas a design pattern for integrating Silverlight, Web Services, and SharePoint. So, while it may have seemedlike you were going to your elbow to get to your thumbs, the information here can be cross-purposed.

The next few chapters discuss other integrations with SharePoint such as Web Parts, customizations, andbranding. It’s an exciting journey, so stay with us until the end!

Additional ReferencesAdditional SharePoint Developer Reference Materials: http://www.mssharepointdeveloper.com.Custom Field Type Information: http://msdn.microsoft.com/en-us/library.ms44661.aspx.Creating a Custom Web Service for SharePoint: http://msdn.microsoft.com/en-us/library/

ms464040.aspx.Introduction to WCF: http://msdn.microsoft.com/en-us/library/aa480190.apsx.SharePoint Developer Center: http://msdn.microsoft.com/en-us/sharepoint/default.aspx.Silverlight Home Page: http://silverlight.net.

109

Fox c03.tex V3 - 01/30/2009 2:46pm Page 110

Fox c04.tex V3 - 01/30/2009 5:00pm Page 111

Branding yourSharePoint site

SharePoint enables developers and users great flexibility to customize or brand their SharePointsites to match the look and feel they require. Developers create the page templates, list templates,style sheets, and master pages that are used by the end-users at run time to brand the site. In thischapter, you will see various techniques and examples for you to brand your site using Silverlight.This obviously won’t cover all possible places to brand your site with Silverlight, but it should giveyou a good foundation to build other Silverlight-branded sites.

You will explore three basic examples in this chapter. In the first example, you learn how to createcustom Silverlight-enabled site pages. A custom site page is core to building out your SharePointapplications outside of lists and libraries. In the second section, you will learn how to create customSilverlight-enabled SharePoint Lists. SharePoint Lists are a core component to all SharePoint sites.You will see how to customize existing List views and how to create your own custom List views.You will also see how to enable simple Silverlight banner ads in your List view. And finally, wewrap up the chapter with creating custom master pages. A master page controls the look and feelfor all of the site pages.

Let’s get started with building a custom Silverlight-enabled site page.

Custom Site PageThere are two main types of pages in SharePoint — application pages and site pages. Applicationpages are usually .aspx pages that are used in the administrative sections of a SharePoint site. Theapplication pages are deployed to the _Layouts directory or a subfolder under the _Layouts direc-tory. In this chapter, you will focus on creating site pages, which we feel are more applicable tobranding your site. Application pages are conceptually similar to site pages, so most of what youlearn will apply equally to both types of pages.

Fox c04.tex V3 - 01/30/2009 5:00pm Page 112

Chapter 4: Branding your SharePoint site

Site pages are .aspx pages that reside inside the site itself. For example, when you open a site, you seethe default site page, which is default.aspx. The site page is combined with the master page to producethe content page that you see on the site. The site page itself is very simple in that it only contains theASP.NET content controls that are used to insert the content into the corresponding placeholder controlin the master page. You will see later in this chapter how to create your own custom master pages. Fornow, you will just use the default master page.

Adding a Blank Branding SolutionYou will start with a blank branding solution and use this throughout the chapter as you add on newprojects. Add a blank SharePoint project to the solution, and name it BrandingSolution.

You can see in Figure 4-1 that the empty SharePoint project contains no references or files other thanthe AssemblyInfo file and a strong name key file called BrandingSolution.snk. You are able to deploythe project at this point. And even though the project won’t do anything, you should always deployyour SharePoint projects immediately after creating them. This ensures that there are no name conflictswithin SharePoint or other deployment issues, like security; for example, you may not have SharePointpermissions to deploy. This will save you a lot of debugging time later.

Figure 4-1

112

Fox c04.tex V3 - 01/30/2009 5:00pm Page 113

Chapter 4: Branding your SharePoint site

If the project successfully deployed to SharePoint, you will see the assembly in the global assembly cache(GAC) similar to Figure 4-2.

Figure 4-2

Adding a Custom Site PageNow that you have a blank SharePoint project and you have verified that it is deploying correctly, youare ready to add the custom site page. Follow these steps:

1. Add a SharePoint module to the BrandingSolution project, and call it CustomSitePage. Amodule feature is how you deploy files to SharePoint. In this case, the item template createsa module with a sample.txt file. You can delete this file because you do not need it for thisexample.

2. Next, you can add your custom site page to the CustomSitePage module folder. Add a new.aspx file to the folder called CustomSitePage.aspx. There may not be an .aspx template filein the Add New Item dialog. If this is the case, simply add a plaintext file, and rename it to.aspx after it is created. This page is your custom site page that the users will see on the siteafter it is combined with the master page. In order to demonstrate just the basics and keepthings simple, we will start with a blank page.

3. Before you add the code to the .aspx file, you should fix up the feature XML files. As men-tioned earlier in the chapter when you deployed the empty project, it is important to keepyour project in a buildable and deployable state. The SharePoint project files can get out ofhand quickly, so it is a good practice to reduce the number of changes at one time.

If you haven’t done so already, delete the sample.txt file from the module folder. Openthe Module.xml file from the module folder, and edit the XML to look like the code inListing 4-1.

113

Fox c04.tex V3 - 01/30/2009 5:00pm Page 114

Chapter 4: Branding your SharePoint site

Listing 4-1: Update the Module.xml file to include the CustomSitePage

<?xml version="1.0" encoding="utf-8"?><Elements Id="299fe2f7-075f-4934-a465-ec96b762725b"xmlns="http://schemas.microsoft.com/sharepoint/"><Module Name="CustomSitePage"><File Path="CustomSitePage.aspx" Url="CustomSitePage.aspx" />

</Module></Elements>

4. You may also need to delete the sample.txt reference from feature.xml in the WSP Viewer.Open the WSP Viewer window, and edit the feature.xml file from the CustomSitePage fea-ture. Your feature.xml file should look similar to the one in Listing 4-2.

Listing 4-2: CustomSitePage feature manifest file

<?xml version="1.0" encoding="utf-8"?><Feature Id="5e489ed2-2686-46af-a3a0-a301ab4813c5"

Title="CustomSitePage"Scope="Web" Version="1.0.0.0"Hidden="FALSE"DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/">

<ElementManifests><ElementManifest Location="CustomSitePage\Module.xml" />

</ElementManifests></Feature>

5. You now have everything set up correctly to begin to add the code to the custom site page.Open the CustomSitePage.apx, and add the code in Listing 4-3. This code sets the page dec-laration and reference to the master page. Later in the chapter, you will create your ownmaster page, but for now, use the default one that ships with SharePoint.

Listing 4-3: Page declaration for the custom site page

C#<%@ Page Language="C#"masterpagefile="∼masterurl/default.master"title="My Custom Site Page"inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint,Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

%>

VB<%@ Page Language="VB"masterpagefile="∼masterurl/default.master"title="My Custom Site Page"inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint,Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

%>

114

Fox c04.tex V3 - 01/30/2009 5:00pm Page 115

Chapter 4: Branding your SharePoint site

Figure 4-3

6. Next add the ASP content controls, which will be put into the placeholder controls onthe master page. You can use as few or as many controls as you like as long as there is amatching placeholder control in the master page. In the code in Listing 4-4, you will replacethree placeholder controls — PlaceHolderMain, PlaceHolderPageTitleInTitleArea, andPlaceHolderPageImage.

Listing 4-4: Replace three placeholder controls with content

<asp:ContentID="MainContent"ContentPlaceHolderID="PlaceHolderMain"runat="server">

<h1>This is my main content.</h1>

</asp:Content>

<asp:ContentID="TitleArea"ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"

Continued

115

Fox c04.tex V3 - 01/30/2009 5:00pm Page 116

Chapter 4: Branding your SharePoint site

Listing 4-4: Replace three placeholder controls with content (continued)

runat="server">

This is the Title Area.

</asp:Content>

<asp:ContentID="Content1"ContentPlaceHolderID="PlaceHolderPageImage"runat="server">

Page Image

</asp:Content>

7. Deploy and run the solution to see the placeholders that were replaced. Figure 4-3 shows anexample of the custom site page with the replaced content placeholders. Keeping with theprocess of incrementally adding to your SharePoint project, this example does not use anySilverlight. But it does verify that everything is running correctly and that you know exactlywhere to put the Silverlight controls. In the next section, you will create Silverlight controlsto put into the content controls.

Adding Your Own ContentYou can add your own content to any of the content placeholders in the master page. In thisexample, you will override three — PlaceHolderMain, PlaceHolderPageTitleInTitleArea, andPlaceHolderPageImage. You can easily figure out which ones are available by using SharePointDesigner (SPD) to edit the CustomSitePage.aspx. You can see in Figure 4-4 that the SharePoint Designershows you the combined page with the master page. As you hover over a placeholder, you will get atool tip that will allow you to override the placeholder. Once you have finished editing the page in SPD,copy the page into your Visual Studio project. Or just use the Designer as an easy way to discover thecorrect name and location of the placeholder you would like to replace.

You now have a basic custom page working. The next step is to do the following:

1. Insert Silverlight controls into the various placeholder controls.

2. Register the System.Web.Silverlight assembly at the top of your CustomSitePage.aspxusing the code in Listing 4-5.

Listing 4-5: Register the Silverlight assembly in the custom site page

<%@ RegisterAssembly="System.Web.Silverlight"Namespace="System.Web.UI.SilverlightControls"TagPrefix="asp" %>

3. Next you need to create the Silverlight projects to add to the page. This can be done in var-ious ways. For example, you could create one Silverlight project with multiple user con-trols. You can see an example of this technique in Chapter 5. For this example, you are goingto create three separate Silverlight projects. Each project will build a XAP package that isloaded into the various content controls.

116

Fox c04.tex V3 - 01/30/2009 5:00pm Page 117

Chapter 4: Branding your SharePoint site

Figure 4-4

4. Add three Silverlight projects to your branding solution. Name the solutionsPlaceHolderMainControl, PlaceHolderPageImageControl, and PlaceHolderPageTi-tleInTitleAreaControl. Figure 4-5 shows an example of how your Visual Studio solutionstructure will look.

5. Once the projects are created, build the solution so that the XAP package files are created.You will need to reference the XAP files in the BrandingSolution project. Remember thatthe BrandingSolution project is a SharePoint solution project as well. You will add a modulefeature to this project to deploy the XAP files.

6. Make the Silverlight control projects dependent on the BrandingSolution project. This willensure that the Silverlight projects always build before the BrandingSolution project. Youcan set this dependency from the Properties dialog of the Visual Studio solution (Figure 4-6).

7. Add a new SharePoint module project item to the BrandingSolution project. This is theSharePoint feature that you will use to deploy your Silverlight XAP files.

8. Name the module feature PlaceHolderControls. In the previous step, you built all of theprojects in the Visual Studio solution, so now you can add them to the PlaceholderControlsfeature.

9. Right-click on the PlaceHolderControls feature folder, and choose Add � Existing Item. Inthe Add Existing Item dialog browse to the PlaceHolderMainControl.xap file located in thebin/debug directory of the PlaceHolderMainControl project. Since you only want to add a

117

Fox c04.tex V3 - 01/30/2009 5:00pm Page 118

Chapter 4: Branding your SharePoint site

reference to the XAP file, select the file and choose ‘‘Add as Link’’ from the Add split buttonat the bottom right of the Add Existing Item dialog. This will add a reference to the XAP filein the PlaceHolderControl feature. Do this again for the remaining two Silverlight projects,PlaceHolderPageImageControl and PlaceHolderPageTitleInTitleAreaControl.

Figure 4-5

10. You should also remove the default sample.txt file that is created when you add a newSharePoint module. And as you did before, you should add the files to module.xml andfeature.xml. Listings 4-6 and 4-7 show what these files should look like.

The next chapter goes into more detail about how to correctly structure the project to deploythe Silverlight XAP package files.

Listing 4-6: Module.xml file to deploy the XAP files

<?xml version="1.0" encoding="utf-8"?><Elements Id="8c4a1c2b-b02a-4e37-aaa6-ae7127106ca3"

xmlns="http://schemas.microsoft.com/sharepoint/"><Module Name="PlaceHolderControls" Url="XAP_Bin"><File Path="PlaceHolderMainControl.xap"

Url="PlaceHolderMainControl.xap" />

118

Fox c04.tex V3 - 01/30/2009 5:00pm Page 119

Chapter 4: Branding your SharePoint site

<File Path="PlaceHolderPageTitleInTitleAreaControl.xap"Url="PlaceHolderPageTitleInTitleAreaControl.xap" />

<File Path="PlaceHolderPageImageControl.xap"Url="PlaceHolderPageImageControl.xap" />

</Module></Elements>

Figure 4-6

Listing 4-7: Feature.xml to deploy the XAP files

<?xml version="1.0" encoding="utf-8"?><Feature

Id="6170c04a-f881-4da3-92d8-5f0abbe83521"Title="PlaceHolderControls"Scope="Web"Version="1.0.0.0"Hidden="FALSE"DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/"ReceiverClass="BrandingSolution.FeatureReceiver"ReceiverAssembly="BrandingSolution, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=9f4da00116c38ec5"><ElementManifests><ElementManifest Location="PlaceHolderControls\Module.xml" /><ElementFile Location="PlaceHolderControls\PlaceHolderMainControl.xap" /><ElementFile Location="PlaceHolderControls\PlaceHolderPageImageControl.xap" /><ElementFile Location=

"PlaceHolderControls\PlaceHolderPageTitleInTitleAreaControl.xap" /></ElementManifests>

</Feature>

119

Fox c04.tex V3 - 01/30/2009 5:00pm Page 120

Chapter 4: Branding your SharePoint site

One thing to call out in the feature.xml file is the use of a Feature Receiver. A FeatureReceiver allows you to run code during various deployment events. You will see how towrite this in the next chapter. But it’s used here to clean up the XAP files when the featureis uninstalled. You will see throughout the book that this is a recommended practice thatyou should use with all of your SharePoint applications, not just the Silverlight projects.

11. Update each Silverlight control with the code in Listings 4-8, 4-9, and 4-10. This exampleis just to demonstrate how to plug the Silverlight controls into the correct placeholderson the page. In order not to add any more complexity to the example, the XAML code issuper-simple. It displays a gradient background with a text block containing the name of thecontrol.

Listing 4-8: PlaceHolderMainControl page.xaml code

<UserControl x:Class="PlaceHolderMainControl.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="400" Height="300"><Grid x:Name="LayoutRoot">

<Grid.Background><LinearGradientBrush EndPoint="1.0,1.0" StartPoint="0.0,0.0">

<GradientStop Color="#FF000000"/><GradientStop Color="#FFFFFFFF" Offset="1"/>

</LinearGradientBrush></Grid.Background><TextBlock

Margin="0,103,0,115"TextWrapping="Wrap"HorizontalAlignment="Center"FontSize="24"Foreground="#FFFFFFFF"Text="PlaceHolderMainControl.xap"/>

</Grid></UserControl>

Listing 4-9: PlaceHolderPageTitleInTitleAreaControl page.xaml code

<UserControl x:Class="PlaceHolderPageTitleInTitleAreaControl.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="600" Height="75"><Grid x:Name="LayoutRoot">

<Grid.Background><LinearGradientBrush EndPoint="1.0,1.0" StartPoint="0.0,0.0">

<GradientStop Color="#FF000000"/><GradientStop Color="#FFFFFFFF" Offset="1"/>

</LinearGradientBrush></Grid.Background><TextBlock

Margin="0,10,0,10"TextWrapping="Wrap"HorizontalAlignment="Center"FontSize="24"

120

Fox c04.tex V3 - 01/30/2009 5:00pm Page 121

Chapter 4: Branding your SharePoint site

Foreground="#FFFFFFFF"Text="PlaceHolderPageTitleInTitleAreaControl.xap"/>

</Grid></UserControl>

Listing 4-10: PlaceHolderPageImageControl page.xaml code

<UserControl x:Class="PlaceHolderPageImageControl.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="150" Height="75"><Grid x:Name="LayoutRoot">

<Grid.Background><LinearGradientBrush EndPoint="1.0,1.0" StartPoint="0.0,0.0">

<GradientStop Color="#FF000000"/><GradientStop Color="#FFFFFFFF" Offset="1"/>

</LinearGradientBrush></Grid.Background><TextBlock

Margin="0,0,0,0"TextWrapping="Wrap"HorizontalAlignment="Center"FontSize="16"Foreground="#FFFFFFFF"Text="PlaceHolderPageImageControl.xap"/>

</Grid></UserControl>

12. Update the CustomSitePage.aspx page to include the Silverlight controls inside the contentcontrols. Replace the PlaceHolderMain content control with the code in Listing 4-11. As youhave seen before, Silverlight controls require a ScriptManager control on the page. Since thePlaceHolderMain control is the first control you are loading, you can add a ScriptManagercontrol to this content control. Enter the code in Listings 4-12 and 4-13 for the other twoplaceholders.

Listing 4-11: Add a Silverlight control to the PlaceHolderMain content control

<asp:ContentID="MainContent"ContentPlaceHolderID="PlaceHolderMain"runat="server">

<asp:ScriptManagerID="ScriptManager1"runat="server" />

<asp:Silverlight ID="PlaceHolderMainControl" runat="server"Source="∼/Xap_Bin/PlaceHolderMainControl.xap"Width="100%" Height="100%" />

</asp:Content>

121

Fox c04.tex V3 - 01/30/2009 5:00pm Page 122

Chapter 4: Branding your SharePoint site

Listing 4-12: Add a Silverlight control to the PlaceHolderPageTitleInTitleArea contentcontrol

<asp:ContentID="TitleArea"ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"runat="server">

<asp:Silverlight ID="PlaceHolderPageTitleInTitleAreaControl" runat="server"Source="∼/Xap_Bin/PlaceHolderPageTitleInTitleAreaControl.xap"Width="100%" Height="75" />

</asp:Content>

Figure 4-7

Listing 4-13: Add a Silverlight control to the PlaceHolderPageImage content control

<asp:ContentID="Content1"ContentPlaceHolderID="PlaceHolderPageImage"runat="server">

<asp:Silverlight ID="PlaceHolderPageImageControl" runat="server"

122

Fox c04.tex V3 - 01/30/2009 5:00pm Page 123

Chapter 4: Branding your SharePoint site

Source="∼/Xap_Bin/PlaceHolderPageImageControl.xap"Width="150" Height="75" />

</asp:Content>

13. Build and deploy the solution to SharePoint. When you run the CustomSitePage.aspx,you’ll see that the Silverlight controls are now running in the various sections of the page.Figure 4-7 shows where the Silverlight controls should appear.

Create Navigation MenuOnce you create a custom site page, you need a way to reference it. Currently the user must know theURL to the custom site page in order to access it. One way to surface the custom site page is to adda link to it on the top Navigation menu. In this example, you will create a Feature Receiver for theCustomSitePage feature. Add a class to the CustomSitePage feature folder called FeatureReceiver,and add the code in Listing 4-14. This code is just standard SharePoint code to add and remove a menu,so we need not go into great detail about it here. When the feature is activated, a new top-level menuitem called Silverlight is created as well as a child menu item called Custom Silverlight Page with a link tothe CustomSitePage.aspx file. When the feature is deactivated, the menu is cleaned up by removing anymenu item starting with Silverlight. Obviously, this code is not production-ready and you would writemore sophisticated code that checks for other child menu items before deleting the top-level item.

Listing 4-14: Add and remove top Navigation menu item during deployment

C#using System;using System.Collections.Generic;using System.Linq;using System.Text;

using Microsoft.SharePoint;using Microsoft.SharePoint.Administration;using Microsoft.SharePoint.Utilities;using System.Xml.Linq;using System.Collections.Specialized;

using Microsoft.SharePoint.Navigation;

namespace BrandingSolution.CustomSitePage{

class FeatureReceiver : SPFeatureReceiver{

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{//System.Diagnostics.Debugger.Launch();

try{

Continued

123

Fox c04.tex V3 - 01/30/2009 5:00pm Page 124

Chapter 4: Branding your SharePoint site

Listing 4-14: Add and remove top Navigation menu item during deployment (continued)

SPWeb web = properties.Feature.Parent as SPWeb;

if (web != null){

#region Add the site page to the menu//Add top menuSPNavigationNodeCollection TopNavBar =

web.Navigation.TopNavigationBar;SPNavigationNode TopMenu =

new SPNavigationNode("Silverlight", "", false);TopNavBar[0].Children.AddAsLast(TopMenu);//Add menu itemSPNavigationNode PageMenuItem =

new SPNavigationNode("Custom Silverlight Page","CustomSitePage.aspx");

TopMenu.Children.AddAsLast(PageMenuItem);#endregion

}}catch (Exception ex) { }

}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

{//System.Diagnostics.Debugger.Launch();

try{

SPWeb web = properties.Feature.Parent as SPWeb;

if (web != null){

#region Remove the site page from the menu//Add top menuSPNavigationNodeCollection TopNavBar =

web.Navigation.TopNavigationBar[0].Children;for(int i = TopNavBar.Count -1; i>=0;i--){

SPNavigationNode TopMenu = TopNavBar[i];if (TopMenu.Title.StartsWith("Silverlight"))

TopNavBar.Delete(TopMenu);}#endregion

}}catch (Exception ex) { }

}

124

Fox c04.tex V3 - 01/30/2009 5:00pm Page 125

Chapter 4: Branding your SharePoint site

public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }

public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }

}}

VBImports SystemImports System.Collections.GenericImports System.LinqImports System.Text

Imports Microsoft.SharePointImports Microsoft.SharePoint.AdministrationImports Microsoft.SharePoint.UtilitiesImports System.Xml.LinqImports System.Collections.Specialized

Imports Microsoft.SharePoint.Navigation

Namespace BrandingSolution.CustomSitePage

Class FeatureReceiverInherits SPFeatureReceiver

Public Overrides Sub FeatureActivated( _ByVal properties As _Microsoft.SharePoint.SPFeatureReceiverProperties)‘System.Diagnostics.Debugger.Launch();

TryDim web As SPWeb = TryCast( _

properties.Feature.Parent, SPWeb)

If web IsNot Nothing Then‘#Region "Add the site page to the menu"‘Add top menuDim TopNavBar As SPNavigationNodeCollection = _

web.Navigation.TopNavigationBarDim TopMenu As New SPNavigationNode(_

"Silverlight", "", False)TopNavBar(0).Children.AddAsLast(TopMenu)‘Add menu itemDim PageMenuItem As New SPNavigationNode( _

"Custom Silverlight Page", _"CustomSitePage.aspx")

‘#End Region

TopMenu.Children.AddAsLast(PageMenuItem)End If

Catch ex As Exception

Continued

125

Fox c04.tex V3 - 01/30/2009 5:00pm Page 126

Chapter 4: Branding your SharePoint site

Listing 4-14: Add and remove top Navigation menu item during deployment (continued)

End Try

End Sub

Public Overrides Sub FeatureDeactivating( _ByVal properties As _Microsoft.SharePoint.SPFeatureReceiverProperties)‘System.Diagnostics.Debugger.Launch();

TryDim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)

If web IsNot Nothing Then‘#Region "Remove the site page from the menu"‘Add top menuDim TopNavBar As SPNavigationNodeCollection = _

web.Navigation.TopNavigationBar(0).ChildrenFor i As Integer = TopNavBar.Count - 1 To 0 Step -1

Dim TopMenu As SPNavigationNode = TopNavBar(i)If TopMenu.Title.StartsWith("Silverlight") Then

TopNavBar.Delete(TopMenu)End If‘#End Region

NextEnd If

Catch ex As ExceptionEnd Try

End Sub

Public Overrides Sub FeatureInstalled( _ByVal properties As _Microsoft.SharePoint.SPFeatureReceiverProperties)

End Sub

Public Overrides Sub FeatureUninstalling(_ByVal properties As _Microsoft.SharePoint.SPFeatureReceiverProperties)

End SubEnd Class

End Namespace

You must add a reference to the Feature Receiver in the feature.xml using the WSP Viewer. The completefeature.xml file for the CustomSitePage feature should look like Listing 4-15.

Listing 4-15: CustomSitePage feature.xml referencing the Feature Receiver

<?xml version="1.0" encoding="utf-8"?><Feature

126

Fox c04.tex V3 - 01/30/2009 5:00pm Page 127

Chapter 4: Branding your SharePoint site

Id="5e489ed2-2686-46af-a3a0-a301ab4813c5"Title="CustomSitePage"Scope="Web"Version="1.0.0.0"Hidden="FALSE"DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/"ReceiverClass="BrandingSolution.CustomSitePage.FeatureReceiver"ReceiverAssembly="BrandingSolution, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=9f4da00116c38ec5"><ElementManifests><ElementManifest Location="CustomSitePage\Module.xml" /><ElementFile Location="CustomSitePage\CustomSitePage.aspx" />

</ElementManifests></Feature>

Now that you have the Feature Receiver in place, you can see in Figure 4-8 that a top-level menu itemhas been created.

Figure 4-8

127

Fox c04.tex V3 - 01/30/2009 5:00pm Page 128

Chapter 4: Branding your SharePoint site

Custom List PageIn this section, you will learn how to customize a list by creating custom views for the list. A SharePointlist contains four pre-defined views for viewing and editing the data in the list — AllItems.aspx, Disp-Form.aspx, EditForm.aspx, and NewForm.aspx. The default view is a file called AllItems.aspx. This isthe normal grid view you see when you create a list. You can see these files using SharePoint Designer.Figure 4-8 shows the list forms using SharePoint Designer.

In Figure 4-9 you can see on the left in the folder view the four site pages that make up a defaultSharePoint List. Viewing the properties of the list allow you to change the pages that map to the differentviews. Keep in mind that everything that you can see or do in SharePoint Designer can also be doneprogrammatically. You will use Visual Studio to create a custom list with custom views. Visual Studiois always the best option as it creates a manageable and deployable SharePoint Solution Package file(WSP). But SharePoint Designer is a great tool for discovering SharePoint features and debugging thework that you do in your Visual Studio projects.

Figure 4-9

You can see from Figure 4-9 that the list site pages such as the AllItems.aspx page are just standard sitepages like those you created earlier in this chapter. You will be able to build on what you did beforeto create the custom list views. In the default AllItems.aspx page, there is a PlaceHolderMain contentplaceholder control. In this case, SharePoint puts a WebPart Zone and a Web Part called ListViewWebPart.

128

Fox c04.tex V3 - 01/30/2009 5:00pm Page 129

Chapter 4: Branding your SharePoint site

The ListViewWebPart is a control that displays the list data in a grid format. All of the parameters toinitialize this Web Part are also contained in the page itself. This includes all of the CAML queries tospecify the data and columns to display. All of this initialization data in the page makes the page appearmore complex and confusing than it really is.

Adding a Feature to the ProjectLet’s start by adding a new feature to the BrandingSolution project that you have used throughout thischapter:

1. Add a new SharePoint List Definition called SilverlightList.

2. Select ‘‘Custom List’’ from the List Definitions Settings Wizard dialog that will open. Leaveall other options unselected and click OK to create the List Definition feature. Your VisualStudio solution should look similar to Figure 4-10.

Figure 4-10

You can see from Figure 4-10 that the custom list definition creates a feature with the fourdefault site pages — AllItems.aspx, DispForm.aspx, EditForm.aspx, and NewForm.aspx.The feature also contains a schema.xml file, which is the List Definition file that describesthe list.

3. One last thing you should do to make the list look more professional is to edit the List prop-erties in the ListDefinition.xml file. For example, you can edit the display name, description,and icon image similar to Listing 4-16.

Listing 4-16: You can optionally edit the List properties

<?xml version="1.0" encoding="utf-8" ?><Elements Id="d05952c4-c7bf-4ee4-ad05-c1562a92970f"

xmlns="http://schemas.microsoft.com/sharepoint/"><ListTemplate Name="SilverlightList"

DisplayName="Custom Silverlight List"

Continued

129

Fox c04.tex V3 - 01/30/2009 5:00pm Page 130

Chapter 4: Branding your SharePoint site

Listing 4-16: You can optionally edit the List properties (continued)

Description="A custom Silverlight enabled List"BaseType="0"Type="100"OnQuickLaunch="TRUE"SecurityBits="11"Sequence="410"Image="/_layouts/images/ITDISC.gif" />

</Elements>

4. Build and deploy the project to verify that everything is set up and working correctly beforeyou start modifying the List Definition. You will see the Custom Silverlight List in the Createadministration page. Figure 4-11 shows the Custom Silverlight List. You can see how thedisplay name, description, and icon image are displayed.

Figure 4-11

Customizing the List with SilverlightNow that you have verified that everything is stable and working, you can begin to customize the listwith Silverlight. In this first example, you will customize one of the existing pages, in this case, theAllItems.aspx page.

130

Fox c04.tex V3 - 01/30/2009 5:00pm Page 131

Chapter 4: Branding your SharePoint site

1. Open the AllItems.aspx page in the Visual Studio Editor, and locate the PlaceHolderMaincontent control. You will notice that this is the same as when you created your own customsite page previously in the chapter. The only difference is that SharePoint has already addedthe content, a WebPart Zone called Main. This is the location where the ListViewPart willbe inserted when an instance of the site is created. For now, you are going to add your Sil-verlight control in this region above the WebPart Zone. This is an easy and useful techniqueto insert headers or banner ads that are list-specific.

2. Add the Silverlight namespace registration to the top of the page, using the code inListing 4-17.

Listing 4-17: Register the Silverlight namespace at the top of the page

<%@ RegisterAssembly="System.Web.Silverlight"Namespace="System.Web.UI.SilverlightControls"TagPrefix="asp" %>

3. Add the ScriptManager and the Silverlight control to the content control. Listing 4-18 showshow to add the code above the WebPart Zone. For this example, add a new Silverlightproject to the solution called BannerAd. This project creates a 728 × 90 Silverlight bannerad. You will see how to create this project later in the chapter. You could also use any ofthe existing Silverlight controls here as well. The banner ad is used to demonstrate a moreconcrete scenario.

Listing 4-18: Add a Silverlight control above the WebPart Zone

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server"><asp:ScriptManagerID="ScriptManager1"runat="server" />

<asp:SilverlightID="BannerAd"runat="server"Source="∼/Xap_Bin/BannerAd.xap"Width="728" Height="90" />

<WebPartPages:WebPartZone

runat="server"

FrameType="None"

ID="Main"

Title="loc:Main" /></asp:Content>

4. To add a little context around the code, Listing 4-19 shows the complete AllItems.aspx code.The default format of the code is that each node is on a single line. This makes the code alittle difficult to read. You can see that the code we added has been formatted with each nodeand each attribute on a separate line. We find this a little easier to read, especially in a bookformat.

131

Fox c04.tex V3 - 01/30/2009 5:00pm Page 132

Chapter 4: Branding your SharePoint site

Listing 4-19: AllItems.aspx code to insert a Silverlight control into the maincontent area

<%@ RegisterAssembly="System.Web.Silverlight"Namespace="System.Web.UI.SilverlightControls"TagPrefix="asp" %>

<%@ Page language="C#" MasterPageFile="∼masterurl/default.master"Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,

Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"Assembly="Microsoft.SharePoint, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"Assembly="Microsoft.SharePoint, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Import Namespace="Microsoft.SharePoint" %>

<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"Assembly="Microsoft.SharePoint, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle"runat="server">

<SharePoint:ListProperty Property="Title" runat="server"/></asp:Content><asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server"><SharePoint:ListProperty Property="Title" runat="server"/></asp:Content><asp:content contentplaceholderid="PlaceHolderAdditionalPageHead" runat="server"><SharePoint:RssLink runat="server" /></asp:content><asp:Content ContentPlaceHolderId="PlaceHolderSearchArea" runat="server"><SharePoint:DelegateControl runat="server"

ControlId="SmallSearchInputBox"/></asp:Content><asp:Content ContentPlaceHolderId="PlaceHolderPageImage"]runat="server">

<SharePoint:ViewIcon Width="145" Height="54" runat="server" /></asp:Content><asp:Content ContentPlaceHolderId="PlaceHolderLeftActions" runat="server"><SharePoint:ModifySettingsLink runat="server" /></asp:Content><asp:Content ContentPlaceHolderId ="PlaceHolderBodyLeftBorder" runat="server"><div height=100% class="ms-pagemargin"><IMG SRC="/_layouts/images/blank.gif"

width=6 height=1 alt=""></div></asp:Content>

132

Fox c04.tex V3 - 01/30/2009 5:00pm Page 133

Chapter 4: Branding your SharePoint site

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server"><asp:ScriptManagerID="ScriptManager1"runat="server" />

<asp:SilverlightID="BannerAd"runat="server"Source="∼/Xap_Bin/BannerAd.xap"Width="728" Height="90" />

<WebPartPages:WebPartZone

runat="server"

FrameType="None"

ID="Main"

Title="loc:Main" /></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderBodyAreaClass" runat="server"><style type="text/css">.ms-bodyareaframe {padding: 0px;}</style></asp:Content><asp:Content ContentPlaceHolderId="PlaceHolderPageDescription" runat="server"><SharePoint:ListProperty CssClass="ms-listdescription"Property="Description" runat="server"/>

</asp:Content><asp:Content ContentPlaceHolderId="PlaceHolderCalendarNavigator" runat="server">

<SharePoint:SPCalendarNavigator id="CalendarNavigatorId" runat="server"/></asp:Content>

5. Build and deploy the solution. Using the SharePoint Create administration page, create anew Custom Silverlight List called MyCustomList. Figure 4-12 shows the banner ad abovethe list grid.

Creating a New Custom List ViewYou saw in the last section how to modify the existing site page; now you will create a new view. Theeasiest way to do this is to copy the existing AllItems.aspx to use as a starting point. This will be mucheasier and more error-free than creating the page from scratch. Create a copy of the AllItems.aspx page,and name it SLCustomView.

1. Once you have a new site page as your view, you must add a new View node to theschema.xml file. Open the schema.xml file and add the view definition from Listing 4-20.

133

Fox c04.tex V3 - 01/30/2009 5:00pm Page 134

Chapter 4: Branding your SharePoint site

Listing 4-20: Add a new custom view definition to the schema.xml

<View BaseViewID="2" Type="HTML"WebPartZoneID="Main"DisplayName="Custom Silverlight View"DefaultView="False"ImageUrl="/_layouts/images/categories.png"Url="SLCustomView.aspx">

</View>

Figure 4-12

You can see in Figure 4-13 that there are already two views be default when you createthe List Definition. For each view you want to add, you must increment the BaseViewIDattribute. The URL path points to the custom view file, in this case, the SLCustomView.aspx.

2. The last thing left to do is to customize the page. Open the SLCustomView.aspx page, andreplace the PlaceHolderMain content control with the code from Listing 4-21. In this code,you add another Silverlight control to the page. This control will replace the list grid WebPart. Now in this example, you have two controls running in the same list. And as you willsee in Chapter 7, these controls could even communicate with each other by passing databack and forth.

134

Fox c04.tex V3 - 01/30/2009 5:00pm Page 135

Chapter 4: Branding your SharePoint site

Figure 4-13

Listing 4-21: Add another Silverlight control to the main content area

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server"><asp:ScriptManagerID="ScriptManager1"runat="server" />

<asp:SilverlightID="BannerAd"runat="server"Source="∼/Xap_Bin/BannerAd.xap"Width="728" Height="90" />

<asp:SilverlightID="PlaceHolderMainControl"runat="server"Source="∼/Xap_Bin/PlaceHolderMainControl.xap"Width="100%" Height="100%" />

<WebPartPages:WebPartZoneContinued

135

Fox c04.tex V3 - 01/30/2009 5:00pm Page 136

Chapter 4: Branding your SharePoint site

Listing 4-21: Add another Silverlight control to the main content area (continued)

runat="server"

FrameType="None"

ID="Main"

Title="loc:Main" /></asp:Content>

Figure 4-14 shows what the new list will look like. You can see that the customized defaultview is still the same, but now there is a new item in the dropdown menu called Custom Sil-verlight View, which points to the new view you just created.

Figure 4-14

3. Clicking on the ‘‘Custom Silverlight View’’ menu item will open the view. Figure 4-15 showsthe custom view that you added. One caveat to this example is that the view dropdownmenu is part of the list grid Web Part. So you will need to implement the view-switchingfunctionality yourself.

136

Fox c04.tex V3 - 01/30/2009 5:00pm Page 137

Chapter 4: Branding your SharePoint site

Figure 4-15

You have seen in this section how to create and customize SharePoint Lists. You can incrementally addSilverlight controls into existing list views, or you can totally take over the entire list view and customizeevery aspect of it. In the next section, you will see how to customize the SharePoint master pages tofurther brand your site.

Customizing the Master PageMaster Pages in SharePoint can get a little complicated. The purpose of this section is not to teach youeverything about SharePoint master pages — there are entire books dedicated to the topic — but instead,how to create your own custom master page that can be used to host your Silverlight content.

SharePoint master pages are simply ASP.NET 2.0 master pages. A master page defines several place-holder controls. These controls are merged at run time with the corresponding content controls that arewithin the content pages. You created a content page with content controls earlier in this chapter. At thattime, you were using the built-in default master page. Now you will create your own master page. Thereal trick to creating master pages is that SharePoint requires several mandatory placeholder controls.This ensures that the master page you create will be compatible with other SharePoint content pages.

137

Fox c04.tex V3 - 01/30/2009 5:00pm Page 138

Chapter 4: Branding your SharePoint site

Creating a Basic Master PageThe easiest way to create this basic or minimal master page as it is called in Help docu-mentation and around the Web is to find an existing one as a starting point. Start with theMiniMaster.master found in the MSDN documentation site. You can find this sample athttp://msdn.microsoft.com/en-us/library/aa660698.aspx. This is a basic page with no for-matting. There are many other good minimal master pages out there that you should use when youget ready to do this on your production site. But for now, this simplicity will allow you to focus on theSilverlight integration.

Follow these steps:

1. Start by adding a new page to your BrandingSolution project called MiniMaster.master.

2. Put the MiniMaster.master in the CustomSitePage feature folder. This will deploy the cus-tom master page in the same directory as the CustomSitePage.aspx.

3. Add the code in Listing 4-22 to the MiniMaster.master file.

Listing 4-22: Minimal master page used as a starting point

<%-- Identifies this page as a .master page written inMicrosoft Visual C# and registers tag prefixes,namespaces, assemblies, and controls. --%><%@ Master language="C#" %><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">

<%@ Import Namespace="Microsoft.SharePoint" %><%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls"Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"Assembly="Microsoft.SharePoint, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"Assembly="Microsoft.SharePoint, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="PublishingWebControls"Namespace="Microsoft.SharePoint.Publishing.WebControls"Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="PublishingNavigation"Namespace="Microsoft.SharePoint.Publishing.Navigation"Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register TagPrefix="wssuc" TagName="Welcome"src="∼/_controltemplates/Welcome.ascx" %>

<%@ Register TagPrefix="wssuc" TagName="DesignModeConsole"src="∼/_controltemplates/DesignModeConsole.ascx" %>

<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu"src="∼/_controltemplates/VariationsLabelMenu.ascx" %><%@ Register Tagprefix="PublishingConsole" TagName="Console"src="∼/_controltemplates/PublishingConsole.ascx" %>

<%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu"

138

Fox c04.tex V3 - 01/30/2009 5:00pm Page 139

Chapter 4: Branding your SharePoint site

src="∼/_controltemplates/PublishingActionMenu.ascx" %><%-- Uses the Microsoft Office namespace and schema. --%><html>

<WebPartPages:SPWebPartManager ID="SPWebPartManager1" runat="server"/><SharePoint:RobotsMetaTag ID="RobotsMetaTag1" runat="server"/>

<%-- The head section includes a content placeholder for thepage title and links to CSS and ECMAScript (JScript, JavaScript)files that run on the server. --%>

<head id="Head1" runat="server"><asp:ContentPlaceHolder runat="server" id="head">

<title><asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server" />

</title></asp:ContentPlaceHolder><Sharepoint:CssLink ID="CssLink1" runat="server"/><asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server" />

</head>

<%-- When loading the body of the .master page,SharePoint Server 2007 also loads the SpBodyOnLoadWrapper class.This class handles .js calls for the master page. --%>

<body onload="javascript:_spBodyOnLoadWrapper();"><%-- The SPWebPartManager manages all of the Web part controls,

functionality, and events that occur on a Web page. --%><form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">

<wssuc:Welcome id="explitLogout" runat="server"/><PublishingSiteAction:SiteActionMenu runat="server"/><PublishingWebControls:AuthoringContainer id="authoringcontrols"

runat="server"><PublishingConsole:Console runat="server" />

</PublishingWebControls:AuthoringContainer><%-- The PlaceHolderMain content placeholder defines where to

place the page content for all the content from the page layout.The page layout can overwrite any content placeholder from the master page.Example: The PlaceHolderLeftNavBar can overwrite the left navigation bar. --%>

<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server" />

<asp:Panel ID="HiddenPlaceHolderControls" visible="false" runat="server"><%-- These ContentPlaceHolders ensure all default

SharePoint Server pages render with this master page. If the system master page isset to any default master page, the only content placeholders requiredare those thatare overridden by your page layouts. --%>

<asp:ContentPlaceHolderid="PlaceHolderSearchArea" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderTitleBreadcrumb" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderPageTitleInTitleArea" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderLeftNavBar" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderPageImage" runat="server"/>

Continued

139

Fox c04.tex V3 - 01/30/2009 5:00pm Page 140

Chapter 4: Branding your SharePoint site

Listing 4-22: Minimal master page used as a starting point (continued)

<asp:ContentPlaceHolderid="PlaceHolderBodyLeftBorder" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderNavSpacer" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderTitleLeftBorder" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderTitleAreaSeparator" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderMiniConsole" runat="server"/>

<asp:ContentPlaceHolderid="PlaceHolderCalendarNavigator" runat ="server" />

<asp:ContentPlaceHolderid="PlaceHolderLeftActions" runat ="server"/>

<asp:ContentPlaceHolderid="PlaceHolderPageDescription" runat ="server"/>

<asp:ContentPlaceHolderid="PlaceHolderBodyAreaClass" runat ="server"/>

<asp:ContentPlaceHolderid="PlaceHolderTitleAreaClass" runat ="server"/>

<asp:ContentPlaceHolderid="PlaceHolderBodyRightMargin" runat="server" />

</asp:Panel></form>

</body></html>

4. Update the element manifest file to include the MiniMaster.master. Listing 4-23 shows theupdated Module.xml file.

Listing 4-23: Updated element file that includes the minimal master file

<?xml version="1.0" encoding="utf-8"?><Elements Id="299fe2f7-075f-4934-a465-ec96b762725b"xmlns="http://schemas.microsoft.com/sharepoint/"><Module Name="CustomSitePage"><File Path="CustomSitePage.aspx" Url="CustomSitePage.aspx" />

</Module><Module Name="MiniMaster"><File Path="MiniMaster.master" Url="MiniMaster.master" />

</Module></Elements>

5. Update the feature manifest file to include the MiniMaster.master. Listing 4-24 shows theupdated Feature.xml file.

Listing 4-24: Updated feature file that includes the minimal master file

<?xml version="1.0" encoding="utf-8"?><Feature

Id="5e489ed2-2686-46af-a3a0-a301ab4813c5"Title="CustomSitePage"Scope="Web"

140

Fox c04.tex V3 - 01/30/2009 5:00pm Page 141

Chapter 4: Branding your SharePoint site

Version="1.0.0.0"Hidden="FALSE"DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/"ReceiverClass="BrandingSolution.CustomSitePage.FeatureReceiver"ReceiverAssembly="BrandingSolution, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=9f4da00116c38ec5"><ElementManifests><ElementManifest Location="CustomSitePage\Module.xml" /><ElementFile Location="CustomSitePage\CustomSitePage.aspx" /><ElementFile Location="CustomSitePage\MiniMaster.master" />

</ElementManifests></Feature>

6. Next, you need to update the CustomSitePage.aspx to point to the new MiniMaster.masterfile. Open the CustomSitePage.aspx file, and change the masterpagefile attribute toMiniMaster.master, similar to Listing 4-25.

Listing 4-25: Update the masterpagefile attribute to reference the custom masterpage

<%@ Page Language="C#"masterpagefile="MiniMaster.master"title="My Custom Site Page"inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

%>

7. Before making any other changes, you have the minimal workings of a custom masterpage and you should verify that it works. Build and deploy the solution. Open theCustomSitePage.aspx, and your page should now look similar to Figure 4-16.

Customizing the PageThat is interesting, but now what you really want to do is to customize the page with Silverlight. Oneof the first items you can move to the master page is the ScriptManager control. Remember that theSilverlight controls require an instance of the ScriptManager control on the page. In Listing 4-11, whenyou created the CustomSitePage file, you placed the ScriptManager control in the MainContent contentcontrol. You can also see in Listings 4-12 and 4-13 that you didn’t include the ScriptManager control.This is because, for this simple example, you assumed that it was already added to the MainContentcontrol. Although this works for this simple example, it is clearly not a best practice for production code.A better approach may be to put the ScriptManager control in the master page. Let’s go ahead and movethe ScriptManager control from the CustomSitePage.aspx to the MiniMaster.master page. Listing 4-26shows the ScriptManager control in the MiniMaster.master file just after the <form> tag.

Listing 4-26: Insert the ScriptManager control in the master page

<body onload="javascript:_spBodyOnLoadWrapper();"><%-- The SPWebPartManager manages all of the Web part controls,

functionality, and events that occur on a Web page. --%><form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">

<asp:ScriptManager ID="ScriptManager1" runat="server" />

141

Fox c04.tex V3 - 01/30/2009 5:00pm Page 142

Chapter 4: Branding your SharePoint site

Figure 4-16

Once you deploy and run the solution, you will see that it runs exactly as before; the only difference isthat the ScriptManager is now loaded in the master page.

You can also put your Silverlight controls directly into the master page. This will allow your control toload no matter which content page is loaded. For example, you could make a banner ad show throughoutthe site by putting it directly into the master page:

1. First, in order to put Silverlight controls directly into the master page, you will need to reg-ister the SilverlightControls namespace. Add the code in Listing 4-27 near the top of theMiniMaster.master page with the other registered namespaces.

Listing 4-27: Register the Silverlight namespace in the master page

<%@ RegisterAssembly="System.Web.Silverlight"Namespace="System.Web.UI.SilverlightControls"TagPrefix="asp" %>

142

Fox c04.tex V3 - 01/30/2009 5:00pm Page 143

Chapter 4: Branding your SharePoint site

2. Let’s go ahead and put the banner ad control you created earlier at the top of the master page(see Listing 4-28).

Listing 4-28: Insert a banner ad at the top of the master page

<body onload="javascript:_spBodyOnLoadWrapper();"><%-- The SPWebPartManager manages all of the Web part controls,

functionality, and events that occur on a Web page. --%><form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">

<asp:ScriptManager ID="ScriptManager1" runat="server" />

<asp:SilverlightID="BannerAd"runat="server"Source="∼/Xap_Bin/BannerAd.xap"Width="728" Height="90" />

3. Deploy and run the solution. You can see in Figure 4-17 that the banner ad appears above allother content on the page. Now no matter which page is loaded, the banner ad will automat-ically appear.

Figure 4-17

143

Fox c04.tex V3 - 01/30/2009 5:00pm Page 144

Chapter 4: Branding your SharePoint site

SummaryYou have seen that you can create your own custom site pages and insert Silverlight content into thesepages. You have seen how to customize SharePoint lists and views. You can now insert Silverlight contentinto existing list views and into custom views as well. And finally, you have learned how to create custommaster pages and how to insert Silverlight content directly into the master pages.

We understand that this only scratches the surface of what could be done to customize and brand theSharePoint experience with Silverlight. But we hope that this gives you the foundation to expand andexplore all that SharePoint has to offer concerning customization. The next wave of SharePoint innovationwill come from enriching the user experience with Silverlight.

144

Fox c05.tex V3 - 01/30/2009 5:03pm Page 145

Custom Web Parts

SharePoint uses a modular approach to building pages for a site. The unit of modularity inSharePoint is the Web Part. A Web Part is a container of functionality and user interface. Web Partsenable you to add and remove units of functionality and move them around the page without anyprogramming. A SharePoint Web Part page consists of areas where Web Parts can be added, calledWeb Part Zones. SharePoint ships with several page templates with zones pre-defined. It also shipswith several pre-built Web Parts; one of these is the Content Editor Web Part, which you can useto host your Silverlight applications. You can also build your own custom Web Parts to host yourSilverlight applications and any other functionality you may need.

In this chapter, you will see how to create Silverlight-enabled Web Parts using Visual Studio 2008and Windows SharePoint Services 3.0 Tools: Visual Studio Extensions Version 1.2 (WssVse). Youwill see how to take advantage of the WssVse tools to create WSP packages and set-up files, whichwill make it easy to deploy and roll back your Silverlight Web Parts. As you will see, this willenable you to have the great development experience to which you as a Visual Studio developer areaccustomed. If you have read other Silverlight Web Part tutorials from around the Web, you mayhave been concerned with the number of manual steps involved with building and deploying yourSilverlight Web Part. You will see that with WssVse, it is as simple as [F5] to run.

Creating a Silverlight ControlThe first thing you need to do is create a simple Silverlight control that you can use for the nexttwo chapters. In this case, you will create a very simple control that has a textbox and a button. Youcould also use one of the controls you created in one of the previous chapters or download one ofthe samples from http://silverlight.net/. The example uses the most basic control possible sothat you can focus on the interactions with SharePoint. In this case, we will not get into the XAMLvery much but focus on using the visual designers or Visual Studio and Expression Blend to domost of the work.

Fox c05.tex V3 - 01/30/2009 5:03pm Page 146

Chapter 5: Custom Web Parts

Creating a New Silverlight ProjectStart by opening Visual Studio 2008 Professional with WssVSe. SharePoint development requires thatyou develop directly on the server. Windows Server 2008 has UAC security on by default. This meansthat in order to deploy your solution to the SharePoint site, you will need to run Visual Studio as anAdministrator.

1. From the Start menu, right-click on the Microsoft Visual Studio 2008 program icon, choose‘‘Run as Administrator,’’ and click Continue at the Confirmation prompt.

2. You want to build a blank solution so that we can add additional projects throughout thischapter. Choose File � New Project to open the New Project dialog.

3. Select the Blank Solution template from the Other Project Types–Visual Studio Solutionsnode.

4. Name the solution CustomWebParts, and set the location to be C:\Book. You can chooseanother location and name if you wish, but you will need to change these through the codeexamples as well. Now that you have a blank solution, you can add the Silverlight project.

5. From the solutions Context menu, choose Add � New Project. Select the Silverlight Applica-tion template from the Silverlight node. Set the project name to SilverlightControl, and leavethe location set at its default, C:\Book\CustomWebParts.

6. When you create a new Silverlight application, the template will prompt you to choose thetype of host to run the application in. There are two choices: Add a new web site project,or dynamically create an HTML test page. In this case, we want to keep things simple, sochoose the second option, ‘‘Automatically generate a test page to host Silverlight at buildtime.’’

When you build and run the application, the project system will generate an HTML page calledTestPage.html in the build output location, in this case, bin\debug, that will be used to host the Silverlightcontrol. You are going to use SharePoint Web Parts to host your control, so this option is good.

Editing the New ControlNow you have created a new Silverlight project and are ready to edit the control. You will use the Expres-sion Blend tool to edit the design of the page. For very simple cases, you could edit the XAML directly inthe tool, but as designs get larger and more complex, this is not practical, and using a tool like ExpressionBlend is the way to go. So even though this is a very simple example that could be created by hand, it isbest to learn the tool and get in the habit of letting the tools do the hard work. Open the Page.xaml filein Expression Blend by choosing ‘‘Open in Expression Blend’’ from the Page.xaml Context menu. At thispoint, if you have been following along exactly, you will be prompted to save the project first: ChooseOK to save. Expression Blend opens and loads the SilverlightControl project and displays the page.xamlin the design surface. Now follow these steps:

1. The first thing you want to do is set the size of the control. Select the UserControl node onthe left in the Objects and Timeline panel.

2. Now select the Properties tab on the right. In the Layout panel, set the Width property equalto 300 and the Height property equal to 200.

146

Fox c05.tex V3 - 01/30/2009 5:03pm Page 147

Chapter 5: Custom Web Parts

3. Even though this is a very simple control, Blend makes it very easy to add a little style. Forexample, you can set the background to a nice gradient color. To do so:

3a. Select the LayoutRoot node on the left in the Objects and Timeline panel, selectthe Properties tab on the right, and click the Gradient brush tab under the Brushespanel. It is the third one after No Brush and Solid Color Brush, located just under theOpacityMask property.

3b. You can play around with these settings to create some cool effects. In this case, thedefault is a black-to-white gradient. Near the bottom of the Brushes panel is a gra-dient bar that shows you a sample of the gradient. There are two stop tags underthe bar. You can drag these around and change the colors as well. We actually justdragged the left one to the right and the right one to the left to swap the gradient tobe a white-to-black one.

3c. You can also change the direction of the gradient. By default, it is horizontal; youcan change this to be diagonal. Click on the Brush Transform tool on the left sidein the toolbox. This tool allows you to change the direction and other aspects of thegradient.

After selecting the Brush Transform, you will see a faint blue arrow on the designsurface. Drag the ends of the arrow around to create a diagonal gradient. Feel free atthis point to explore other aspects of Expression Blend.

4. As mentioned before, you are ready to add the Text Box and Button to the control. Just likewith Windows Forms development, there are controls in the toolbox for each of these. Selectthe TextBox control in the toolbox on the left — it is near the bottom. Now click and drag onthe design surface to ‘‘draw’’ the toolbox. Repeat the same process for the Button. When youare finished you should have something that resembles Figure 5-1.

5. Save the control by pressing Ctrl-S or File � Save from the main menu.

6. You are done with Blend for now, so close Blend by clicking on the in the upper-rightcorner.

7. Switch focus back to Visual Studio. The first thing you see is that Visual Studio is promptingyou to reload the Page.xaml file. It has detected that you changed the file using Blend, so itwants to make sure that this is what you intended to do. Click Yes to reload. Even thoughyou said yes to reload, the Visual Studio XAML Designer is not showing you the updateddesign. You need to click on the yellow warning bar at the top of the Design window torefresh the visual designer. Although the recommended way is to use the visual designers,there may be times when it is faster to just edit the XAML directly. For example, change thetext displayed in the textbox. In the XAML Editor of Visual Studio, find the TextBox nodenear the bottom of the code, and set the Text property equal to ‘‘Simple Silverlight Control.’’Listing 5-1 is the complete XAML if you simply want to quickly re-create the Silverlightcontrol.

Listing 5-1: The XAML for the simple Silverlight control

<UserControl x:Class="SilverlightControl.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="300" Height="200">

Continued

147

Fox c05.tex V3 - 01/30/2009 5:03pm Page 148

Chapter 5: Custom Web Parts

Listing 5-1: The XAML for the simple Silverlight control (continued)

<Grid x:Name="LayoutRoot"><Grid.Background>

<LinearGradientBrush EndPoint="1,1" StartPoint="0,0"><GradientStop Color="#FF070707" Offset="1"/><GradientStop Color="#FFFCFCFC"/>

</LinearGradientBrush></Grid.Background><TextBox Height="54" Margin="8,8,8,0"

VerticalAlignment="Top"Text="NEW Simple Silverlight Control"TextWrapping="Wrap"/>

<Button Height="63" HorizontalAlignment="Stretch"Margin="8,0,8,12" VerticalAlignment="Bottom"Content="Button"/>

</Grid></UserControl>

You will see that the Designer updates as you type, and you should see something similar toFigure 5-2 when you are finished.

Figure 5-1

148

Fox c05.tex V3 - 01/30/2009 5:03pm Page 149

Chapter 5: Custom Web Parts

Figure 5-2

8. You can now build and run the Silverlight control. Press [F5] to launch the test page to ver-ify that the control is working. Close Internet Explorer when you are finished testing yourcontrol.

If you examine the build output location, in this case bin\debug, you will see the SilverlightControl.xappackage file.

You will use this control throughout the rest of the chapter. Next you will use this control in yourSharePoint site.

Content Editor Web PartSharePoint provides several Web Parts out-of-the-box. One of these is the Content Editor Web Part, whichis installed with the installation of SharePoint. It is designed to allow you, as an end-user, to quickly addrich HTML content to a SharePoint site. It also provides an opportunity to inject your newly createdSilverlight control from the last section. The Web Part contains two ways to enter content:

❑ Through a rich text editor

❑ By entering the HTML code directly. This is the one you will use to enter the code directly intothe Web Part.

149

Fox c05.tex V3 - 01/30/2009 5:03pm Page 150

Chapter 5: Custom Web Parts

Getting Your Application to RunThe Content Editor Web Part is a quick and easy way to get your Silverlight application running withinSharePoint. This technique requires no Visual Studio programming and can be done with no other mod-ifications to the SharePoint site or configuration:

1. Publish Your Silverlight Application to the SharePoint Server — Create a folder to holdthe Silverlight application. Browse to the root folder of your SharePoint site. In the defaultinstallation, this will be C:\inetpub\wwwroot\wss\VirtualDirectories\80. Create a subfoldercalled XAP_Bin. Again, you can use any name you like, but you will need to remember tochange the paths in the code examples. To publish the Silverlight application, simply copythe SilverlightControl.xap file that you created in the previous section; this will be locatedin the build output folder, \bin\debug by default.

2. Display the Application on the Page — For this, you will use the Content Editor Web Part.Open the SharePoint page you wish to add the Silverlight application to, and choose EditPage under the Site Actions menu, which is located in the upper-right side of the page. Thisputs the page in Edit mode. Once in Edit mode, you can add, delete, or modify the WebParts. Click on the ‘‘Add a Web Part’’ button located at the top of each Web Part Zone. Thiswill open the Add Web Parts dialog. The Web Parts dialog displays all of the installed WebParts. They are grouped into different categories such as Business Data, Filters, and Miscel-laneous. The Content Editor Web Part is located in the Miscellaneous group. Scroll down tothe Miscellaneous group, select the ‘‘Content Editor Web Part,’’ and click on the Add button.This will add the Content Editor Web Part to the page.

3. Modify the HTML Source — Click ‘‘Modify Shared Web Part’’ from the Web Part’s Editmenu. The Content Editor panel opens on the right, giving you the option to use the RichText Editor or the Source Editor, as shown in Figure 5-3. Click on the ‘‘Source Editor’’ buttonto enter the source code to display your Silverlight application.

The Source Editor dialog is just a textbox that allows you to write your code. As you cansee in Figure 5-4, unlike real code editors, there is no IntelliSense, color coding, or errorchecking. So the best thing to do is to use an external editor, like Visual Studio or SharePointDesigner, to create the code and then just copy-and-paste it to this Source Editor dialog.

3a. The first HTML tag to add is the object tag. This is the standard way to use the Sil-verlight plug-in control. Change the width and height properties to 300 and 200,respectively, to match the size of the SilverlightControl application you created ear-lier.

3b. Next add a param node to set the source location of the XAP file. Enter the path rela-tive to the root of the SharePoint site, in this case, /XAP_Bin/silverlightcontrol.xap.

Listing 5-2 shows you the complete code. Enter it into the Source Editor dialog.

Listing 5-2: Display Silverlight application in SharePoint

<objectdata="data:application/x-silverlight,"type="application/x-silverlight-2-b2"width="300" height="200">

<param

150

Fox c05.tex V3 - 01/30/2009 5:03pm Page 151

Chapter 5: Custom Web Parts

name="source"value="/XAP_Bin/silverlightcontrol.xap"/>

</object>

Figure 5-3

4. Save and Close — Click on the Save button to save and close the Editor dialog. You will nowsee the Silverlight application running inside a Web Part on your SharePoint site. Figure 5-5shows the Silverlight control running.

Adding a Silverlight Plug-InAt this point you could click the ‘‘Exit Edit Mode’’ link in the upper-right side of the page under the ‘‘SiteActions’’ button, but there is one more thing you should probably add. Silverlight is a new technology,and as such, the penetration rate for the Silverlight plug-in is still relatively low. It is therefore importantto have a good experience for those who come to the site without the plug-in. What you will do is adda couple of lines to the HTML source to display a Silverlight icon and a link to install the Silverlightplug-in. Add the code in Listing 5-3 to your object tag by clicking on the ‘‘Source Editor’’ button again.Also at the bottom of Listing 5-3, you can see that we have added a place for you to enter any JavaScriptyour Silverlight application may need to call. For example, if you look at the TestPage.html code, youwill see that it adds JavaScript code to handle the OnError function.

151

Fox c05.tex V3 - 01/30/2009 5:03pm Page 152

Chapter 5: Custom Web Parts

Figure 5-4

Listing 5-3: Add support for people without the Silverlight plug-in

<objectdata="data:application/x-silverlight,"type="application/x-silverlight-2-b2"width="300" height="200">

<paramname="source"value="/XAP_Bin/silverlightcontrol.xap"/>

<!-- Silverlight Not Installed--><a href="http://go.microsoft.com/fwlink/?LinkID=115261"style="text-decoration: none;"><img src="http://go.microsoft.com/fwlink/?LinkId=108181"alt="Get Microsoft Silverlight"style="border-style: none"/></a>

</object>

<script type="text/javascript">

</script>

That’s it. You can now exit the Edit mode and see your Silverlight application working.

152

Fox c05.tex V3 - 01/30/2009 5:03pm Page 153

Chapter 5: Custom Web Parts

Figure 5-5

JavaScript OnlyThere may be times when hard-coding the object tag in the source editor does not work for you. Inthis case, you could create the same results using only JavaScript. Listing 5-4 demonstrates dynamicallycreating the object tag inside a Div tag.

Listing 5-4: Dynamically create object tag using JavaScript

<div id="silverlightDIV" />

<script type="text/javascript">var slDIV = document.getElementById(’SilverlightDIV’);slDIV.appendChild(slDIV);slDIV.innerHTML = ‘<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="300" height="200"><param name="source" value=" /XAP_Bin/silverlightcontrol.xap "/></object>’;</script>

153

Fox c05.tex V3 - 01/30/2009 5:03pm Page 154

Chapter 5: Custom Web Parts

Silverlight StreamingAnother approach would be to use Silverlight Streaming services. Although a detailed walk-through isout of the scope of this book, you could use the streaming services to host the XAP file. This is a greatsolution if you don’t have access to the site to copy your XAP file to. In this scenario, you create an onlineaccount on the http://Silverlight.live.com site and upload your XAP file. Once that is done, you canaccess that XAP file from anywhere on the Internet. Listing 5-5 shows the code to enter into the ContentEditor Web Part to display the Silverlight application from the Web.

Listing 5-5: Load the Silverlight control inside an iframe from the Silverlightstreaming server

<iframe src="http://silverlight.services.live.com/invoke/77777/SilverlightControl/iframe.html"scrolling="no" frameborder="0"style="width:300px; height:200px"></iframe>In the next section you will learn how to create your own customWeb Parts to give you the ultimate control over all aspects of theexperience.

Customizing Web PartIn the previous section, you saw how easy it was to use an existing Web Part to host your Silverlightapplication. In this section, you will create your own custom Web Part using Visual Studio and VseWSS.

Starting a New Web Part ProjectStart by opening Visual Studio as an Administrator. Open the existing project that you created in theprevious section called CustomWebParts. This solution contains the Silverlight project you created inthe previous section. You will now add a new Web Part project to the solution:

1. Choose Add�New Project from the solution Context menu.

2. In the Add New Project dialog, choose SharePoint from the project types, and select the WebPart project template.

3. Change the project name field to SLWebPart, and click OK to add the new project to yoursolution.

By default, the Web Part project template creates a Web Part called WebPart1. All of the files that makeup the Web Part are contained in a folder. You can see this structure in Figure 5-6.

SharePoint Solution FeaturesThis folder represents a SharePoint solution feature. Although this section doesn’t go into details aboutevery aspect of SharePoint solutions and features, it shows you all of the interesting areas to make devel-oping Silverlight Web Parts as seamless as possible. SharePoint provides a packaging mechanism calleda solution to deploy code to a SharePoint site. The solution package contains one or more SharePoint fea-tures. A feature is a unit of functionality that can be configured in SharePoint. The Web Part project creates

154

Fox c05.tex V3 - 01/30/2009 5:03pm Page 155

Chapter 5: Custom Web Parts

a SharePoint solution package; this is a zip archive with the .wsp extension, once you deploy the project.Each Web Part you add to the project is a feature. There are a few files involved in the definition of afeature. For example, there is a feature XML file that references several element files. This file is namedafter the name of the feature, in this case, Webpart1.xml. When Visual Studio creates the Web Part project,it sets all of these files up correctly. But if you rename, move, delete, or add files after the creation, it isyour responsibility to fix all of the feature XML files. This can be a challenging task to get right. So thebest approach is to simply delete the WebPart1 folder and add a new Web Part with the correct name:

1. Delete the WebPart1 folder. Now you can add a new Web Part project item. From theProject’s context menu, choose Add�New Item.

2. From the Add New Item dialog, select SharePoint from the categories on the left, and thenselect Web Part from the templates on the right.

3. Set the name field to SLWebPart, and click Add to create a new Web Part in the project.

Figure 5-6

Displaying the Silverlight Control and Adding ReferencesYou now have a clean Web Part project with user code. This is the starting point for every Web Partproject. At this point, you could build and deploy the project without any error, but it wouldn’t be very

155

Fox c05.tex V3 - 01/30/2009 5:03pm Page 156

Chapter 5: Custom Web Parts

interesting because it is empty. Let’s add some code to display your Silverlight control. Before you startwith the code, you need to add a couple of references:

1. Right-click on the References folder in the project, and choose ‘‘Add Reference.’’

2. From the .NET tab of the Add References dialog, select the System.Web.Extensions andSystem.Web.Silverlight assemblies. Figure 5-7 shows the references you need to add.Click OK to add the references.

Figure 5-7

3. Open the SLWebPart.cs file, and add the statement in Listing 5-6 to the top of the code.

Listing 5-6: Using statement for Silverlight

using System.Web.UI.SilverlightControls;

4. The WebPart class contains many methods and properties. In this case, you want to overridethe OnLoad method. By overriding the OnLoad method, you can run your code when theWeb Part is loaded by SharePoint. The Silverlight ASP.NET control depends on theScriptManager control. So you need to add a ScriptManager control. There can only be oneScriptManager per page. Since this is a Web Part page, there is a good chance that anotherWeb Part may have been loaded first and has already added a ScriptManager to the page.You will need to add a check for an existing ScriptManager and only add a new one ifanother is not present. Listing 5-7 shows the complete Onload method; add this code to yourSLWebPart.cs file or your SLWebPart.vb file.

Listing 5-7: Add a ScriptManager to the OnLoad method

C#protected override void OnLoad(EventArgs e){

base.OnLoad(e);

#region ScriptManager

156

Fox c05.tex V3 - 01/30/2009 5:03pm Page 157

Chapter 5: Custom Web Parts

ScriptManager scriptManager =ScriptManager.GetCurrent(this.Page);

if (scriptManager == null){

scriptManager = new ScriptManager();Controls.AddAt(0, scriptManager);

}#endregion

}Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)

MyBase.OnLoad(e)

VB‘#Region "ScriptManager"Dim currentScriptManager As ScriptManager = _

ScriptManager.GetCurrent(Me.Page)If currentScriptManager Is Nothing Then

currentScriptManager = New ScriptManager()Controls.AddAt(0, currentScriptManager)

End If‘#End Region

End Sub

5. You can now create the actual Silverlight control itself. The WebParts class provides variousmethods to do this. The one you are going to use is CreateChildControls. This methodis called when SharePoint is ready for you to add to the controls collection. You need toset a few properties on the Silverlight control before you add it to the Controls collection.The first is the ID property; set this to SLWebPartID. This ID can really be anything youlike. Most likely you will not need to use it. The next and most important property isthe Source property. This is the URL to the Silverlight control. You can use a relative oran absolute path. In this case, you will use a path relative to the site root; set it equal to∼/XAP_Bin/SilverlightControl.xap. This URL points to the XAP file that you deployed inthe first section of this chapter.

6. Finally, the width property can be set to 100 percent using the Percentage method of theUnit class.

7. Once all of the properties of the Silverlight control are set, you can add it to the Controlscollection using the Add method. Add the code in Listing 5-8 to your SLWebPart.cs file or toyour SLWebPart.vb file.

Listing 5-8: Add the Silverlight control

C#protected override void CreateChildControls(){

base.CreateChildControls();

Silverlight ctrl = new Silverlight();ctrl.ID = "SLWebPartID";ctrl.Source = "∼/XAP_Bin/SilverlightControl.xap";ctrl.Width = Unit.Percentage(100);

Continued

157

Fox c05.tex V3 - 01/30/2009 5:03pm Page 158

Chapter 5: Custom Web Parts

Listing 5-8: Add the Silverlight control (continued)

Controls.Add(ctrl);}

VBProtected Overloads Overrides Sub CreateChildControls()

MyBase.CreateChildControls()

Dim ctrl As New Silverlight()ctrl.ID = "SLWebPartID"ctrl.Source = "∼/XAP_Bin/SilverlightControl.xap"ctrl.Width = Unit.Percentage(100)Controls.Add(ctrl)

End Sub

8. You have completed all of the code required to display the Silverlight control. Choose Buildfrom the SLWebPart project’s Context menu. This will build the project and confirm thatthere are no code problems.

9. With a successful build, you are ready to deploy the Web Part. Choose Deploy from theSLWebPart project’s Context menu. This will build (if necessary); create the WSP SharePointsolution package; and create a set-up batch file to deploy, install, and activate the solution.Choosing Deploy from Visual Studio will do all of these steps for you automatically. But ifyou look in the Bin/debug output folder, you will find the WSP file and the set-up file. Thisis useful to give to your production SharePoint administrator when you are ready to deployinto the test or production environment. You can watch the progress of this process in thestatus bar of Visual Studio.

If you get any deployment errors, make sure that your feature names are unique. You mayget this error if you cut-and-paste code between projects, such as the code from one chapterto the next. The solution is to uninstall any previous code that may be using the samefeature names.

Running the SolutionOne last caveat before you test your Web Part is to verify that you have your SharePoint site configuredfor Silverlight. This was discussed in previous chapters. In the source code download for the book, wehave created a Visual Studio solution that will set everything up correctly just by deploying the solution.

Once the deployment is complete, do the following:

1. Open Internet Explorer and browse to your SharePoint site.

2. Set the page in Edit mode by choosing Edit Page from the ‘‘Site Actions’’ menu in theupper-right corner of the page.

3. Once the page is in Edit mode, you can click on the ‘‘Add a Web Part’’ button at the top ofthe center Web Part Zone. This will open the Web Part Gallery. Browse down the list to theMiscellaneous group, and select ‘‘SLWebPart Web Part’’ from the list. Click Add to addthe SLWebPart to the page.

4. Exit from Edit mode. If you have been following along with this chapter, you will see thatyou now have two Silverlight controls on the page — the new custom Web Part and the Con-tent Editor Web Part. Figure 5-8 shows the two Web Parts.

158

Fox c05.tex V3 - 01/30/2009 5:03pm Page 159

Chapter 5: Custom Web Parts

Figure 5-8

Figure 5-8 shows that the custom Web Part and Content Editor Web Part offer the same end-user experi-ence. For this simple example that is true, but as you dig deeper into the inner workings of Web Parts, itwill become clear that custom Web Parts offer the best integrated experience.

Deploying the Silverlight ApplicationAt this point, both Web Parts are using the Silverlight application that you copied to the XAP_Bin folder.But this is not what you really want to do while developing. You want to have a single solution thatbuilds and deploys not only the Web Part but the Silverlight application as well. Let’s take a look at howto deploy our Silverlight application with the Web Part. In Visual Studio development, you can referenceanother project in the solution so that when you build the first project, the referenced project gets builtas well. While this works well for referencing the build output, which is a DLL file, this is not what youneed for your Web Part, because you need to reference the XAP file not the DLL. You still need VisualStudio to build the Silverlight application before building the Web Part. Visual Studio allows you to mapdependencies between projects. This is exactly what you want. Visual Studio will build the dependentSilverlight project before the Web Part. To deploy, follow these steps:

1. Close the browser and return the Visual Studio solution.

159

Fox c05.tex V3 - 01/30/2009 5:03pm Page 160

Chapter 5: Custom Web Parts

2. Choose Properties from the solution’s Context menu. In the solution’s Property page dia-log, select Project Dependencies under the Common Properties node. On the right, select theSLWebPart project, and then check the SilverlightControl under the ‘‘Depends on’’ listbox. Click OK to set the dependency and close the Properties dialog.

3. The next step is to get the Web Part project to deploy the XAP file when the project isdeployed. To do this, you will add a new feature to the Web Part project. This way bothfeatures will be deployed when the solution is deployed. Select Add�New Item to openthe New Item dialog. Select SharePoint from the categories on the left, and then select theModule template. Modules are a SharePoint feature for deploying files to the SharePointserver, which is exactly what you want to do with the Silverlight XAP file. Set the nameproperty equal to SilverlightControl, and click Add to add the module to the project. Theproject template includes a test file called sample.txt by default.

4. Go ahead and delete sample.txt as it is not needed. Instead, you want to add your XAP in theproject, but the catch is that you don’t want to copy the XAP to the project. You only want areference to it so that when it is rebuilt, you have the correct version. To add a link to theXAP file, choose Add � Existing Item from the SilverlightControl folder.

5. In the Add Existing Item dialog, browse to the SilverlightControl.xap file located in the Sil-verlightControl project. The XAP file is the one in the bin/debug folder. Now the trick is thatthe Add button at the bottom of the dialog is a split button. This means that the button hassome options. On the Add button, click the little down arrow to the right and choose ‘‘AddAs Link.’’ Figure 5-9 shows what this looks like.

Figure 5-9

Figure 5-10 shows the SLWebPart project with the two features — the Web Part and the Sil-verlight application.

6. The last step is to fix up the Module.xml file. The Module.xml file contains the elements thatmake up the feature. In this case, the file includes the sample.txt file that you deleted. Unfor-tunately, Visual Studio doesn’t fix this automatically. Open the Module.xml file, and enter

160

Fox c05.tex V3 - 01/30/2009 5:03pm Page 161

Chapter 5: Custom Web Parts

the XML in Listing 5-9. This module file will copy the SilverlightControl.xap to the XAP_Binfolder on the SharePoint site. If the folder does not exist, it will be created. You should notcopy the Elements ID attribute as this is the unique ID of your feature.

Figure 5-10

Listing 5-9: The Module.xml file describes where to deploy the file

<?xml version="1.0" encoding="utf-8"?><Elements Id="45d12bfd-c8e6-4abf-8f56-10226897d1f3"

xmlns="http://schemas.microsoft.com/sharepoint/">

<Module Name="SilverlightControl" Url="XAP_Bin"><File Path="SilverlightControl.xap" Url="SilverlightControl.xap" />

</Module>

</Elements

You can now build and deploy the SLWebPart project. Open the site in Internet Explorer to verify thatit is working. What you will see is that everything is working as before. The only difference now is thatwhen you deploy this project to production, there are no manual steps involved.

161

Fox c05.tex V3 - 01/30/2009 5:03pm Page 162

Chapter 5: Custom Web Parts

Uninstalling and Updating the SolutionVisual Studio creates a batch file called setup.bat in the build output directory, bin/debug. This can be runby administrators to install and uninstall the solution. To install the solution, simply run the setup.batfile from a command window with Administrator rights. To uninstall the solution, run the setup.bat filewith the /uninstall parameter. To get help on all of the parameters, use the /help switch.

There are a couple of caveats to your solution that are addressed in the next chapter. They are mentionedhere so that you can be aware of them:

❑ One of the first things to understand is that, by design, the SharePoint solutions don’t removeor overwrite files deployed in the module. This means that you will need to delete the XAP filemanually in the XAP_Bin directory using SharePoint Designer. You will only need to do this ifyou are updating the Silverlight control.

❑ The second issue is that even though the solution removes the Web Part code, it does not removethe .wp file. This leaves the Web Part visible in the gallery, but it will fail if you add it to a page,because the code has been removed. You need to delete the Web Part from the Web Part Gallerymanually; to do this, browse to the Web Part Gallery under Site Actions�Site Settings menu.You only need to do this if you are updating the Web Part properties that you will see in the nextsection. If you are just changing the code of the Web Part, you will not need to do this as the newcode will run.

These two issues can be a little frustrating if you are not aware of them. In the next chapter, you willwrite the code to address these two issues by deleting these items when the solution is uninstalled.

Render ContentsAnother way to inject Silverlight into your Web Part is to override the RenderContents method. Themethod is called by SharePoint when it is creating the contents inside of the Web Part. You can usethe passed HTMLTextWriter variable to write raw HTML into the Web Part. In the example shownin Listing 5-10, you can see that you can add code before or after the HTML that is created using theCreateChildControls method. You could even use the write method to inject the code needed to dis-play the Silverlight control from the Silverlight Streaming service.

Listing 5-10: Use RenderContents to inject HTML directly into the Web Part

C#protected override void RenderContents(HtmlTextWriter writer){

writer.Write("Before Render base Contents<br/>");

base.RenderContents(writer);

writer.Write("<br/>After Render base Contents<p/>");

writer.Write("Render Silverlight Streaming Control in an iframe<br/>");String SilverLightStream = @"<iframe

src=""http://silverlight.services.live.com/invoke/77777/SilverlightControl/iframe.html"" scrolling=""no""frameborder=""0"" style=""width:300px; height:200px""></iframe>";

writer.Write(SilverLightStream);

162

Fox c05.tex V3 - 01/30/2009 5:03pm Page 163

Chapter 5: Custom Web Parts

}

VBProtected Overloads Overrides Sub RenderContents(

ByVal writer As HtmlTextWriter)writer.Write("Before Render base Contents<br/>")

MyBase.RenderContents(writer)

writer.Write("<br/>After Render base Contents<p/>")

writer.Write("Render Silverlight Streaming Control in an iframe<br/>")Dim SilverLightStream As String = "<iframe

src=""http://silverlight.services.live.com/invoke/77777/SilverlightControl/iframe.html"" scrolling=""no""frameborder=""0"" style=""width:300px; height:200px""></iframe>"

writer.Write(SilverLightStream)End Sub

In Figure 5-11 you can see that you now have two Silverlight controls rendering inside the same WebPart. You can also see how the before and after statements wrap the Silverlight control you addedusing the CreateChildControls method.

Figure 5-11

163

Fox c05.tex V3 - 01/30/2009 5:03pm Page 164

Chapter 5: Custom Web Parts

You have completed all of the required steps to run your Silverlight application in SharePoint. But as aprofession developer, you want to completely and seamlessly integrate into the SharePoint environment.This will require you to set some properties of the project.

Web Part Gallery CategoryThe Web Part Gallery displays the Web Parts in a categorized view. As you have seen, if you don’t set thecategory, then your Web Part will end up in the miscellaneous category. The Group property determinesthe category to display the Web Part in. There are really no rules to this. Whatever text you enter as theproperty value will be the name of the category. Figure 5-12 shows the custom category called SilverlightWeb Parts. If there is an existing category with this name, then your Web Part will be placed under thatcategory; if not, a new category will be created. There is also another property called QuickAddGroups.The Quick Add Groups are used to display your Web Part in the list of suggested Web Parts for that WebPart Zone. The values match the names of the Web Part Zones and are separated with a semicolon (;)and a pound sign (#). You can find the Web Part Zone names by looking at the title of the Add Web Partdialog. Add the properties in Listing 5-11 to your SLWebPart.xml file.

Figure 5-12

164

Fox c05.tex V3 - 01/30/2009 5:03pm Page 165

Chapter 5: Custom Web Parts

Listing 5-11: Set the properties to display the Web Part correctly in the gallery

<?xml version="1.0" encoding="utf-8"?><Elements Id="313d2b4c-6a87-46f3-a935-524ac9966168"xmlns="http://schemas.microsoft.com/sharepoint/" ><Module Name="WebParts" List="113" Url="_catalogs/wp"><File Path="SLWebPart.webpart"

Url="SLWebPart.webpart"Type="GhostableInLibrary">

<Property Name="Group" Value="Silverlight Web Parts" /><Property Name="QuickAddGroups" Value="Middle Left;#" />

</File></Module>

</Elements>

Web Part PropertiesWeb Parts also have properties for common items such as the title and description. You can set these inthe SLWebPart.webpart file. This is an XML file that defines the Web Part. Change your file to match thecode in Listing 5-12.

You should not change the type name GUID value. This GUID is unique to your project and used byVisual Studio to substitute the fully qualified assembly name when it builds the project.

The Title and Description files are obvious, so they won’t be discussed in this section; but wedo want to point out that you can change the icons that appear in the Web Part and in the WebPart Gallery. The example in this section uses one of the built-in icons. You can browse theseicons, which are located by default in the C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\TEMPLATE\IMAGES folder. This path appears on your site to be /_lay-outs/images/. You can also add your own icons to this list. And although it’s now shown for thisexample, you would also want to include the icon in your project as a module feature. The icons must by16 × 16 pixel icons. Figure 5-12 shows the CatalogIconImageUrl icon in the Web Part Gallery. Figure 5-13shows the TitleIconImageUrl icon in the Web Part title bar.

Two other properties not shown in this example are HelpUrl and TitleUrl. The HelpUrl adds a helpVerb to your Web Part Context menu that links to a page on your site. You will see in the next sectionhow to add your own custom Verbs to the context menu. The TitleUrl makes the title of your Web Parta hyperlink that links to the page on your site specified by the property value.

These are only some of the common properties and are by no means complete. You should see the MSDNdocumentation for all of the properties. One other tip is to make sure that you put the property valueson one line in your XML file with no leading or trailing spaces. SharePoint doesn’t trim the leading andtraining spaces and in some cases won’t work correctly. Listing 5-12 has been formatted to fit the formatof this book.

Listing 5-12: Common Web Part properties

<?xml version="1.0" encoding="utf-8"?><webParts>

<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">Continued

165

Fox c05.tex V3 - 01/30/2009 5:03pm Page 166

Chapter 5: Custom Web Parts

Listing 5-12: Common Web Part properties (continued)

<metaData><!--The following Guid is used as a reference to the web part class,and it will be automatically replaced with actual type name atdeployment time.--><type name="f9b09c1f-93d9-464f-97b3-4cd45f4cc61c" /><importErrorMessage>

Cannot import WebPart1 Web Part.</importErrorMessage>

</metaData><data>

<properties><property name="Title" type="string">

Silverlight Sample Web Part</property><property name="Description" type="string">

Silverlight Sample Web Part for the book</property><property name="CatalogIconImageUrl" type="string">

/_layouts/images/ ADDTOFAVORITES.GIF</property><property name="TitleIconImageUrl" type="string">

/_layouts/images/SPHOMESM.GIF</property>

</properties></data>

</webPart></webParts>

DebuggingDebugging your Silverlight Web Part requires a little manual setup in Visual Studio. There are twodifferent pieces to debug — the Web Part and the Silverlight application. This requires that you attach totwo separate processes:

❑ To debug your Web Part, you need to attach to the SharePoint process, which is called thew3wp.exe:

1. Open the CustomWebParts solution that you have been building in this chapter.

2. Open the SLWebPart.ce file and set a breakpoint.

❑ You also need to attach to the SharePoint worker process:

1. Select Debug � Attach to Process from the Visual Studio menu, and select the w3wp.exefrom the list of available processes. You will need to check the Show processes in all ses-sions to see the w3wp.exe process. You may also see more than one. Instead of trying toidentify the correct process, we have found that it is easy to just open the Windows Task

166

Fox c05.tex V3 - 01/30/2009 5:03pm Page 167

Chapter 5: Custom Web Parts

Manager and end all the w3wp.exe processes. SharePoint will automatically start a newworker process as soon as you hit the site again.

Figure 5-13

2. Press [F5] in Internet Explorer to refresh the page and start a new worker process.

3. Now switch back to Visual Studio and click on the Refresh button. You should now seeonly one w3wp.exe; select it and click Attach.

You can also debug the Silverlight control at the same time, giving you the ability to step through yourcode end-to-end:

1. With the Attach to Process dialog still open, find the iexplore.exe process that matches theinstances with your SharePoint site open. You can identify the correct instance to attach tofrom the title.

2. Refreshing the web page will cause the breakpoints to be hit. For example, if you set a break-point in the OnLoad method of the Web Part, this will break on this line before the Silverlight

167

Fox c05.tex V3 - 01/30/2009 5:03pm Page 168

Chapter 5: Custom Web Parts

application. Also this example has two different instances of the same Silverlight control,so the Visual Studio debugger will stop on the breakpoint once for each instance. From thispoint, you can debug both the Web Part and the Silverlight control as you would any .NETapplication.

SummaryYou have seen in this chapter how you have a few options for how you integrate Silverlight into yourSharePoint Web Parts. You can start with a relatively easy non-developer approach of using the ContentEditor Web Part that is built into SharePoint. This chapter also showed you how to build your owncustom Web Parts using Visual Studio and the Visual Studio Extensions for SharePoint. You have seenhow you can build a robust, automated developer experience in Visual Studio giving you [F5] build anddeployment of your Web Parts and Silverlight applications. Finally, you saw that debugging SilverlightWeb Parts is only slightly more difficult than a standard Silverlight application.

In the next chapter, you will build on these concepts to further extend your custom Web Parts withfeatures like custom properties, custom Silverlight editors, custom Verbs, connected Web Parts, andconnected Silverlight controls.

168

Fox c06.tex V3 - 01/30/2009 5:24pm Page 169

Advanced Custom WebParts

In the last chapter, you learned various techniques for creating basic Silverlight Web Parts. Thischapter builds on the Web Parts created in the previous chapter, adding more advanced features.You saw in the last chapter how to build Web Parts using Visual Studio, which made building anddeploying them to SharePoint easy. You will complete this Visual Studio project by adding codeto clean up the SharePoint files once a feature has been uninstalled. You will learn how to debugthe stsadm.exe process, which is used to install and uninstall SharePoint features. The follow-ing various advanced features of Web Parts and Silverlight allow you to create professional andwell-integrated Web Part experiences using Silverlight:

❑ Sometimes your Silverlight application needs to use JavaScript to communicate withSharePoint and the web browser. In this chapter, you see how to embed JavaScript filesinto your Web Parts.

❑ In SharePoint, Web Parts contain a Context menu with menu items called Verbs. In thischapter, you see how to create your own Verbs and learn how Verbs can be created to callclient-side script and server-side methods.

❑ Another great feature of SharePoint is the ability to edit the properties of a Web Part fromthe SharePoint site. This chapter shows you how to create custom properties that willappear inside the Web Part Editor pane.

❑ In addition to adding properties to the Editor, you can also create your own custom editor.In this chapter, you learn how to create a custom editor that uses Silverlight as the editor.

❑ SharePoint also supports several different display modes, such as the Browse mode, Designmode, and Edit mode. This chapter shows you how it is possible to detect the display modeand change the behavior and screens in your Silverlight application based on the currentdisplay mode. This will allow you to create very rich Silverlight applications that are easyto code and maintain in a single XAP package.

Fox c06.tex V3 - 01/30/2009 5:24pm Page 170

Chapter 6: Advanced Custom Web Parts

Cleaning up Files and Web Parts uponUninstall

You have seen how to use the power of Visual Studio and SharePoint solutions to deploy your SilverlightWeb Part. There are a couple of issues that you need to understand in order to make developing withSharePoint a pleasant experience. The solution you developed in Chapter 5 contained two basic pieces;the Web Part and the Silverlight control. Both of these get deployed to SharePoint using a feature, morespecifically as a module and file element. The problem lies in the fact that by design SharePoint willnot remove files deployed using a module or file element. In your specific solution, this means that theSLWebPart.webpart file and the SilverlightControl.xap file are not removed. In the case of the SLWeb-Part.webpart, the side effect is that the assembly has been removed but the Web Part still appears in theWeb Part Gallery. If a user adds this Web Part to a page, it will fail. The orphaned SilverlightControl.xapfile only has the effect of taking up hard drive space. The other aspect to this SharePoint behavior is thatnot only will it not remove the files upon uninstall, but it also will not overwrite existing files. Whenyou make changes to your SLWebPart.webpart file or to your Silverlight control, the changes will not bedeployed. This can be very frustrating and time-consuming to debug until you understand what isgoing on.

Using Feature ReceiversThe answer is to use a Feature Receiver. A Feature Receiver is how you can run custom code during theinstallation or uninstallation of a feature. You will see how to create a Feature Receiver that will cleanup files deployed with the solution. Open the CustomWebParts project that you created in Chapter 5 ordownload the Chapter 6 code from the book. Remember to open Visual Studio as an Administrator. Adda new class to the SLWebPart project called FeatureReceiver. You can name this class anything youlike. Feature Receivers are mapped to features in the feature’s XML, so you could create unique FeatureReceivers for each feature or, as you will do for this example, use the same Feature Receiver for all of thefeatures in the SLWebPart project.

Adding a Feature ReceiverFirst, add the references in Listing 6-1 to the top of your class file.

Listing 6-1: FeatureReceiver references

VBusing Microsoft.SharePoint;using Microsoft.SharePoint.Administration;using Microsoft.SharePoint.Utilities;using System.Xml.Linq;

C#Imports Microsoft.SharePointImports Microsoft.SharePoint.AdministrationImports Microsoft.SharePoint.Utilities

Imports System.Xml.Linq

The SharePoint references used in the using statements have already been added to the project. But youwill be using LINQ to XML in your code, so you will need to add a reference to the System.Core.dll.

170

Fox c06.tex V3 - 01/30/2009 5:24pm Page 171

Chapter 6: Advanced Custom Web Parts

A Feature Receiver inherits from the Microsoft.SharePoint.SPFeatureReceiver abstract class. Addthis to your class, and from the Context menu choose Refactor � Implement Abstract Class. Commentout all of the not-implemented exceptions. Listing 6-2 shows what your code will look like at this point.

Listing 6-2: Minimal Feature Receiver

C#using System;using System.Collections.Generic;using System.Linq;using System.Text;

using Microsoft.SharePoint;using Microsoft.SharePoint.Administration;using Microsoft.SharePoint.Utilities;

using System.Xml.Linq;

namespace SLWebPart{

class FeatureReceiver:SPFeatureReceiver{

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{//throw new NotImplementedException();

}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

{//throw new NotImplementedException();

}

public override void FeatureInstalled(SPFeatureReceiverProperties properties)

{//throw new NotImplementedException();

}

public override void FeatureUninstalling(SPFeatureReceiverProperties properties)

{//throw new NotImplementedException();

}}

}

VBImports Microsoft.SharePointImports Microsoft.SharePoint.Administration

Continued

171

Fox c06.tex V3 - 01/30/2009 5:24pm Page 172

Chapter 6: Advanced Custom Web Parts

Listing 6-2: Minimal Feature Receiver (continued)

Imports Microsoft.SharePoint.Utilities

Imports System.Xml.Linq

Friend Class FeatureReceiverInherits SPFeatureReceiver

Public Overrides Sub FeatureActivated(ByVal properties AsMicrosoft.SharePoint.SPFeatureReceiverProperties)

End Sub

Public Overrides Sub FeatureDeactivating(ByVal properties AsMicrosoft.SharePoint.SPFeatureReceiverProperties)

End Sub

Public Overrides Sub FeatureInstalled(ByVal properties AsMicrosoft.SharePoint.SPFeatureReceiverProperties)

End Sub

Public Overrides Sub FeatureUninstalling(ByVal properties AsMicrosoft.SharePoint.SPFeatureReceiverProperties)

End SubEnd Class

The Feature Receiver defines two pairs of operations: activated and deactivated and installed and unin-stalling. You want to remove the files installed by the feature when it is uninstalled, so you will add yourcode to the FeatureUninstalling method. This code is interesting because once you understand whatthis code is doing, you will be able to apply these techniques to many SharePoint deployment issues.

Deleting Feature Installed FilesThe task is to delete the files that have been installed by the feature. But how do you know what thesefiles are? They are defined in the element XML files, which, in turn, are referenced by the feature XMLfiles. You need to parse these files to extract the paths to the files and then get a reference to them fromthe SPWeb object, following these steps:

1. Use the Properties parameter passed to the FeatureUninstalling method to get a referenceto the feature definition and the solution definition that contains the feature.

C#SPFeatureDefinition definition = properties.Definition;SPSolution solution = SPFarm.Local.Solutions[definition.SolutionId];

VBDim definition As SPFeatureDefinition = properties.DefinitionDim solution As SPSolution = SPFarm.Local.Solutions(definition.SolutionId)

172

Fox c06.tex V3 - 01/30/2009 5:24pm Page 173

Chapter 6: Advanced Custom Web Parts

2. Next you need a reference to the SPWeb that the feature is installed in. In the other methodsin the Feature Receiver you can use this code.

C#SPWeb site = properties.Feature.Parent as SPWeb;SPWebApplication webApp = site.Site.WebApplication;

VBDim site1 As SPWeb = TryCast(properties.Feature.Parent, SPWeb)Dim webApp1 As SPWebApplication = site1.Site.WebApplication

3. But this code does not work in the FeatureUninstalling method. This is because theFeature property of the properties object is always null. It’s not clear why this is, but it maybe because the feature has already been uninstalled and thus is null. You can work aroundthis to get to the SPWeb using a different technique, as shown in the following code:

C#foreach (SPWebApplication webApp in solution.DeployedWebApplications){

foreach (SPSite site in webApp.Sites){

SPWeb web = site.RootWeb;

. . .

}}

VBFor Each webApp As SPWebApplication In solution.DeployedWebApplications

For Each site As SPSite In webApp.SitesDim web As SPWeb = site.RootWeb. . .

Next siteNext webApp

4. Once you have a reference to the SPWeb object, you can get the XML for the feature.C#

XDocument featureXml = XDocument.Parse(definition.GetXmlDefinition(web.Locale).OuterXml);

VBDim featureXml As XDocument = XDocument.Parse(definition.GetXmlDefinition(web.Locale).OuterXml)

The feature XML looks like this. The path to the element file is contained in the locationattribute of the ElementManifest node.

<?xml version="1.0" encoding="utf-8"?><Feature Id="60a202c2-ac0c-46f8-8263-87d914285a3f" Title="SLWebPart" Scope="Site"

Version="1.0.0.0" Hidden="FALSE" DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/"ReceiverClass="SLWebPart.FeatureReceiver"ReceiverAssembly="SLWebPart, Version=1.0.0.0, Culture=neutral,

PublicKeyToken=9f4da00116c38ec5">

173

Fox c06.tex V3 - 01/30/2009 5:24pm Page 174

Chapter 6: Advanced Custom Web Parts

<ElementManifests><ElementManifest Location="SLWebPart\SLWebPart.xml" /><ElementFile Location="SLWebPart\SLWebPart.webpart" />

</ElementManifests></Feature>

5. LINQ to XML makes it easy to parse this file to extract the location and to build the absolutepath to the file in SharePoint.

C#var location = from em in

featureXml.Descendants(ns + "ElementManifest")select (string)em.Attribute("Location").Value;

string elementXmlPath = System.IO.Path.Combine(

definition.RootDirectory,location.ElementAtOrDefault(0)

);

//get the elements fileXDocument elementXml = XDocument.Load(elementXmlPath);

VBDim location = _

From em In featureXml.Descendants(ns &"ElementManifest") _

Select CStr(em.Attribute("Location").Value)

Dim elementXmlPath As String =System.IO.Path.Combine (definition.RootDirectory,

location.ElementAtOrDefault(0))

‘get the elements fileDim elementXml As XDocument = XDocument.Load(elementXmlPath)

The element XML file looks like this when viewed in the WSP Viewer tool. This is a littlemore complicated because the path is stored in the URL attribute of the Module node, and thefilename itself is in the URL attribute of the File node.

<?xml version="1.0" encoding="utf-8"?><Elements Id="313d2b4c-6a87-46f3-a935-524ac9966168"

xmlns="http://schemas.microsoft.com/sharepoint/" ><Module Name="WebParts" List="113" Url="_catalogs/wp"><File Path="SLWebPart.webpart"

Url="SLWebPart.webpart"Type="GhostableInLibrary">

<Property Name="Group" Value="Silverlight Web Parts" /><Property Name="QuickAddGroups" Value="Default;#" />

</File></Module>

</Elements>

6. Again, use LINQ to XML to extract the location and build the absolute path to the file inSharePoint. Combine all of the various file path parts to ultimately build the absolute pathto the file in SharePoint.

174

Fox c06.tex V3 - 01/30/2009 5:24pm Page 175

Chapter 6: Advanced Custom Web Parts

C#var FileElements = from ef in

elementXml.Descendants(ns + "File")select ef;

XElement fileElement = FileElements.ElementAtOrDefault(0);string BaseUrl = fileElement.Parent.Attribute("Url").Value;string FileName = fileElement.Attribute("Url").Value;string RelativePath = SPUrlUtility.CombineUrl(BaseUrl,

FileName);string AbsolutePath = SPUrlUtility.CombineUrl(web.Url,

RelativePath);

VBDim FileElements = _

From ef InelementXml.Descendants(ns & "File") _

Select ef

Dim fileElement As XElement =FileElements.ElementAtOrDefault(0)

Dim BaseUrl As String =fileElement.Parent.Attribute("Url").Value

Dim FileName As String =fileElement.Attribute("Url").Value

Dim RelativePath As String =SPUrlUtility.CombineUrl(BaseUrl, FileName)

Dim AbsolutePath As String =SPUrlUtility.CombineUrl(web.Url, RelativePath)

7. The last thing to do is to get a reference to the file from the SPWeb object and call the deletemethod to remove the file.

C#SPFile wpFile = web.GetFile(AbsolutePath);wpFile.Delete();

VB

Dim wpFile As SPFile = web.GetFile(AbsolutePath)wpFile.Delete()

Listing 6-3 shows you the entire method

Listing 6-3: Remove feature files upon uninstall

C#public override void FeatureUninstalling(

SPFeatureReceiverProperties properties){

Continued

175

Fox c06.tex V3 - 01/30/2009 5:24pm Page 176

Chapter 6: Advanced Custom Web Parts

Listing 6-3: Remove feature files upon uninstall (continued)

System.Diagnostics.Debugger.Launch();

SPFeatureDefinition definition = properties.Definition;SPSolution solution = SPFarm.Local.Solutions[definition.SolutionId];

// Feature is always nullSPWeb site1 = properties.Feature.Parent as SPWeb;SPWebApplication webApp1 = site1.Site.WebApplication;

foreach (SPWebApplication webApp in solution.DeployedWebApplications){

foreach (SPSite site in webApp.Sites){

SPWeb web = site.RootWeb;

// Get the Feature xmlXDocument featureXml = XDocument.Parse(

definition.GetXmlDefinition(web.Locale).OuterXml);

XNamespace ns = "http://schemas.microsoft.com/sharepoint/";

// Query feature manifest for the element manifest locationvar location = from em in

featureXml.Descendants(ns + "ElementManifest")select (string)em.Attribute("Location").Value;

string elementXmlPath = System.IO.Path.Combine(

definition.RootDirectory,location.ElementAtOrDefault(0)

);

//get the elements fileXDocument elementXml = XDocument.Load(elementXmlPath);

// Query element manifest for the element manifest locationvar FileElements = from ef in

elementXml.Descendants(ns + "File")select ef;

// Build the Absolute path to the fileXElement fileElement = FileElements.ElementAtOrDefault(0);string BaseUrl = fileElement.Parent.Attribute("Url").Value;string FileName = fileElement.Attribute("Url").Value;string RelativePath =

SPUrlUtility.CombineUrl(BaseUrl, FileName);string AbsolutePath =

SPUrlUtility.CombineUrl(web.Url, RelativePath);

// Get a reference to the file and delete itSPFile wpFile = web.GetFile(AbsolutePath);wpFile.Delete();

}

176

Fox c06.tex V3 - 01/30/2009 5:24pm Page 177

Chapter 6: Advanced Custom Web Parts

VBPublic Overrides Sub FeatureUninstalling(

ByVal properties As SPFeatureReceiverProperties)‘System.Diagnostics.Debugger.Launch()

Dim definition As SPFeatureDefinition = properties.DefinitionDim solution As SPSolution = SPFarm.Local.Solutions(definition.SolutionId)

‘Feature is always null, I guess since it has already been uninstalled?‘Dim site1 As SPWeb = TryCast(properties.Feature.Parent, SPWeb)‘Dim webApp1 As SPWebApplication = site1.Site.WebApplication

For Each webApp As SPWebApplication In solution.DeployedWebApplicationsFor Each site As SPSite In webApp.Sites

Dim web As SPWeb = site.RootWeb

Dim featureXml As XDocument = XDocument.Parse(definition.GetXmlDefinition(web.Locale).OuterXml)

Dim ns As XNamespace = "http://schemas.microsoft.com/sharepoint/"

‘// Query feature manifest for the element manifest locationDim location = _From em In featureXml.Descendants(ns + "ElementManifest") _Select CStr(em.Attribute("Location").Value)

Dim elementXmlPath As String =System.IO.Path.Combine(definition.RootDirectory,location.ElementAtOrDefault(0))

‘get the elements fileDim elementXml As XDocument = XDocument.Load(elementXmlPath)

‘ Query element manifest for the element manifest locationDim FileElements = _From ef In elementXml.Descendants(ns + "File") _Select ef

Dim fileElement As XElement = fileElements.ElementAtOrDefault(0)Dim BaseUrl As String = fileElement.Parent.Attribute("Url").ValueDim FileName As String = fileElement.Attribute("Url").ValueDim RelativePath As String =

SPUrlUtility.CombineUrl(BaseUrl, FileName)Dim AbsolutePath As String =

SPUrlUtility.CombineUrl(web.Url, RelativePath)

Dim wpFile As SPFile = web.GetFile(AbsolutePath)wpFile.Delete()

Next siteNext webApp

End Sub

This code is very generic and can be used in all of your SharePoint projects. This code assumes that thereis only one element file per feature and only one file per element. You would need to add code to iteratethrough multiple ElementManifest nodes and multiple File nodes.

177

Fox c06.tex V3 - 01/30/2009 5:24pm Page 178

Chapter 6: Advanced Custom Web Parts

Registering the FeatureThe last step is to register the Feature Receiver in the feature.xml file. You can open the feature.xmlfile from the WSP Viewer. This is a special viewer added when you installed the VseWss extensions toVisual Studio.

1. Open the WSP Viewer from the main menu, View � Other Windows � WSP View. The WSPViewer shows you a hierarchical view of your SharePoint solution. Some of the files in thisview can be seen in your project via the solution explorer, but some, such as the feature.xml,can only be seen with the WSP Viewer.

2. Expand each feature folder, and edit the feature.xml. You will need to add two attributes tothe Feature node, ReceiverClass and ReceiverAssembly:

❑ The ReceiverClass is the namespace and name of the class that inherits fromSPFeatureReceiver.

❑ The ReceiverAssembly is the fully qualified name to the assembly containing the Fea-ture Receiver.

3. Listing 6-4 shows an example of the SLWebPart feature.xml file. Add the same two attributesto all of the features in your project that you want to attach the Feature Receiver to; in thisexample, the only other feature is the Silverlight control.

Listing 6-4: Registering the FeatureReceiver class

<?xml version="1.0" encoding="utf-8"?><Feature Id="60a202c2-ac0c-46f8-8263-87d914285a3f" Title="SLWebPart" Scope="Site"

Version="1.0.0.0" Hidden="FALSE" DefaultResourceFile="core"xmlns="http://schemas.microsoft.com/sharepoint/"ReceiverClass="SLWebPart.FeatureReceiver"ReceiverAssembly="SLWebPart, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=9f4da00116c38ec5">

<ElementManifests><ElementManifest Location="SLWebPart\SLWebPart.xml" /><ElementFile Location="SLWebPart\SLWebPart.webpart" />

</ElementManifests></Feature>

Debugging Feature ReceiversDebugging SharePoint features can be a challenge. Debugging Feature Receivers presents a difficultchallenge because the code does not run under the SharePoint process, w3wp.exe, as you learned inChapter 5. Instead, the code runs under the stsadm.exe process. stsadm.exe is the command-lineadministration tool for SharePoint. Visual Studio automatically builds a setup.bat file to install anduninstall the solution package, the WSP file. The problem is that you need to attach the Visual Studiodebugger to the stsadm.exe process. But if you ran the set-up project and tried to switch back to VisualStudio to attach the debugger, the process would be finished already. The way around this problem is

178

Fox c06.tex V3 - 01/30/2009 5:24pm Page 179

Chapter 6: Advanced Custom Web Parts

to have your code call the Visual Studio debugger. You can see in Listing 6-3 that we have included theSystem.Diagnostics.Debugger.Launch();.

Now when you deploy the solution, you will break on this line. But to make this all work correctly, it isbest if you start from the command prompt and not from Visual Studio. This is because you want to usethe Visual Studio instance that already has your project loaded to debug with. This mode of debuggingis an advanced technique that should be clearer as you continue to walk through these steps:

1. Start the solution uninstall process from the command window, making sure that you arerunning as an administrator.

2. Change directory to the bin/debug folder of the project, and run the setup/uninstall com-mand. As the process starts, you will get a dialog prompting you to debug the application orcancel debugging. This occurs when System.Diagnostics.Debugger.Launch(); is hit in thecode. Figure 6-1 shows the Visual Studio Just-In-Time Debugger dialog.

Figure 6-1

3. The dialog tells you in what process the exception occurred, in this case, the stsadm.exeand the process ID. You have the option to debug or cancel. Click Yes, debug stsadm.exeto debug.

4. This will cause a User Account Control dialog to appear, asking you to allow or cancel theoperation. Click Allow to continue.

5. Figure 6-2 shows the debugger dialog to select the debugger to use. You have two options:to pick an existing instance of Visual Studio or start a new instance. You want to choosethe existing instance where your CustomWebParts solution is running. This is why it is bestto start from a command line; otherwise, your only choice would have been to start a newinstance. With your CustomWebParts solution selected, click Yes to start debugging.

6. You will receive one last warning dialog before you can begin debugging. You can see inFigure 6-3 that this dialog warns you that there is no source code available to debug for thecurrent location. Click OK to clear this dialog.

7. After you click OK on this dialog, you are taken to Visual Studio, but you do not see wherethe breakpoint is. You will need to press [F10] to step to the next line in the debugger, whichwill be the System.Diagnostics.Debugger.Launch(); line. You can see in Figure 6-3 thatyou are now stopped on a breakpoint in your FeatureUninstalling method and can con-tinue to debug as you normally do in Visual Studio from this point forward.

179

Fox c06.tex V3 - 01/30/2009 5:24pm Page 180

Chapter 6: Advanced Custom Web Parts

Figure 6-2

Figure 6-3

Be aware that you will not be able to use Edit and Continue to edit the code on the fly inthe debugger.

You will need to repeat this process for each feature that you have added the Feature Receiver to. Duringthis debugging cycle, you will need to switch back and forth between building, installing, and unin-stalling the solution. Sometimes you might see a compiler warning stating, ‘‘The language-neutralsolution package was not found.’’ This is caused by a Visual Studio caching bug, so simply restartVisual Studio to fix the problem.

Customizing Web PartsThere are many ways to extend and customize SharePoint Web Parts. In this section, you will seesome useful extensibility techniques that will help you create fantastic Silverlight Web Partexperiences.

180

Fox c06.tex V3 - 01/30/2009 5:24pm Page 181

Chapter 6: Advanced Custom Web Parts

Using Custom Embedded JavaScript FilesThe Silverlight control runs in the client’s browser process. Silverlight can communicate with the browserthrough an HTML bridge built into the Silverlight control. The HTML bridge allows Silverlight to callJavaScript, and it allows JavaScript to call Silverlight. You’ll see how this interaction works in more detailin Chapter 7. As part of your Silverlight application, you may need helper functions written in JavaScript.You could simply use the RenderContents method to write the JavaScript code into the page. But thisbecomes very difficult to write and to debug. A better solution would be to embed a .js file into the WebPart. This will allow you to write and debug the JavaScript code more easily:

1. Add a new project item to the SLWebPart project.

2. Select ‘‘Jscript file’’ under the Web node. Name the file Silverlight.js. The filename is notimportant; you could use any valid name.

3. Once the file is added to the project, select the file in the solution explorer, and set the BuildAction property to ‘‘Embedded Resource.’’ This will embed the file into the SLWebPart.dll.

4. Next you need to write code to extract the Silverlight.js file. Add the code inListing 6-5 to the OnLoad event in the SLWebPart.cs file. This code will get a referenceto the ClientScriptManager object from the web page that the Web Part is on. Onceyou have this object, you can call the GetWebResourceUrl to get a URL to the embeddedSilverlight.js file. Then you can register the JavaScript file in the page.

Listing 6-5: Extract and register the JavaScript file

VB#region Embedded JS File//Get a ClientScriptManager reference from the Page class.

ClientScriptManager clientScriptManager = Page.ClientScript;//Get the URL to the js filestring scriptURL = clientScriptManager.GetWebResourceUrl(

this.GetType()," SLWebPart.Silverlight.js");

//Register the js fileclientScriptManager.RegisterClientScriptInclude(this.GetType(),

"SLWebPartsSilverlight", scriptURL);#endregion

C#‘#Region "Embedded JS File"‘Get a ClientScriptManager reference from the Page class.Dim clientScriptManager As ClientScriptManager = Page.ClientScript‘Get the URL to the js fileDim scriptURL As String =

clientScriptManager.GetWebResourceUrl(Me.GetType(),"SLWebPart.Silverlight.js")

‘Register the js fileclientScriptManager.RegisterClientScriptInclude(Me.GetType(),

"SLWebPartSilverlight", scriptURL)‘#End Region

181

Fox c06.tex V3 - 01/30/2009 5:24pm Page 182

Chapter 6: Advanced Custom Web Parts

5. To create a simple test, add the code in Listing 6-6 to the Silverlight.js file. Remember thatthis is a simple test for you to understand how it works. You will see an example of how tocall this in the next section.

Listing 6-6: A simple test function in the embedded JavaScript file

function TestAlert(){

alert("WebPart JS file alert TEST");}

6. The last step is to register the Silverlight.js file as a web resource for the Web Part assembly.Add the code in Listing 6-7 to the AssemblyInfo.cs file located in the Properties folder ofyour SLWebPart project.

Listing 6-7: Register the embedded JavaScript file as a web resource

C#//Set the Embedded js file[assembly: System.Web.UI.WebResource("SLWebPart.Silverlight.js","text/javascript")]

VB’Set the Embedded js file<Assembly: System.Web.UI.WebResource(

Using Customized VerbsWeb Parts contains a menu in the upper-right corner of the title bar. You can customize the menu andadd new menu items called Verbs. The Verbs can be used to call server-side functions and client-sideJavaScript functions. Figure 6-4 shows two custom Verbs, My Client Verb and My Server Verb, whichhave been added to the Web Part.

You must override the WebPartVerbCollection to insert your custom menu items. Create a newWebPartVerb object. There are three overloads for creating a WebPartVerb, one for a client-side clickevent handler, one for a server-side click event handler, and one that fires both a server-side and aclient-side click event handler.

❑ Client-Side Event — The client-side click event handler is a string for the JavaScript. Forexample, to call an inline JavaScript function, you would use the following code:

C#WebPartVerb InlineVerb = new WebPartVerb ("InlineVerb", "javascript:alert(\"Inline Verb Clicked\")");

VBDim InlineVerb As New WebPartVerb("InlineVerb",

"javascript:alert(""Inline Verb Clicked"")")

❑ To call a JavaScript method already on the page, such as calling the TestAlert method from theembedded file that you created in the last section, you would using the following code:

C#WebPartVerb ClientVerb = new WebPartVerb("ClientVerb","javascript:TestAlert()");

182

Fox c06.tex V3 - 01/30/2009 5:24pm Page 183

Chapter 6: Advanced Custom Web Parts

VBDim ClientVerb As New WebPartVerb("ClientVerb","javascript:TestAlert()")

Figure 6-4

❑ Server-Side Event — Calling a server-side click event handler requires you to create acallback method. The callback must have the WebPartVerbsEventHandler signature, which isWebPartVerbsEventHandler (Object sender, WebPartVerbsEventArgs e).

C#WebPartVerb ServerVerb = new WebPartVerb(

"ServerVerb", ServerSideWebPartEventHandler);

public void ServerSideWebPartEventHandler(Object sender, WebPartEventArgs e)

{this.Title = "Server Side Verb Click";

}

VBServerVerb = New WebPartVerb("ServerVerb", AddressOf ServerSideWebPartEventHandler)

Public Sub ServerSideWebPartEventHandler(

183

Fox c06.tex V3 - 01/30/2009 5:24pm Page 184

Chapter 6: Advanced Custom Web Parts

ByVal sender As Object, ByVal e As WebPartEventArgs)

Me.Title = "Server Verb Clicked"

End Sub

❑ Client-Side and Server-Side Events — The last constructor of the WebPartVerb calls both theclient-side click event handler and then the server-side click event handler. This is useful inyour Silverlight Web Parts because a server-side click event will cause a postback to the server.But by calling the client first, you can save the current state of your Silverlight application beforethe postback occurs.

The complete code for creating a client-side Verb and a server-side Verb is given in Listing 6-8.

Listing 6-8: Create custom server-side and client-side Verbs

C#public override WebPartVerbCollection Verbs{

get{

//create a client side verb eventWebPartVerb ClientVerb;ClientVerb = new WebPartVerb("ClientVerb",

"javascript:TestAlert()");ClientVerb.Description = "This is a client side verb";ClientVerb.Text = "My Client Verb";//C:\Program Files\Common Files\

microsoft shared\Web Server// Extensions\12\TEMPLATE\IMAGES

ClientVerb.ImageUrl = /_layouts/images/ADDTOFAVORITES.GIF";

//create a server side verb eventWebPartVerb ServerVerb;ServerVerb = new WebPartVerb(

"ServerVerb", ServerSideWebPartEventHandler);ServerVerb.Description = "This is a Server side verb";ServerVerb.Text = "My Server Verb";//C:\Program Files\Common Files\

microsoft shared\Web Server// Extensions\12\TEMPLATE\IMAGES

ServerVerb.ImageUrl = "/_layouts/images/warn16.GIF";

//Create an array so we can combine the//custom verbs with the existing verbs

WebPartVerb[] customVerbsArray =new WebPartVerb[]

{ ClientVerb, ServerVerb };

//combine the custom verbs with the existing verbsWebPartVerbCollection customVerbsCollection =

new WebPartVerbCollection(base.Verbs, customVerbsArray);//return the new custom verbs collection

184

Fox c06.tex V3 - 01/30/2009 5:24pm Page 185

Chapter 6: Advanced Custom Web Parts

return customVerbsCollection;}

}

public void ServerSideWebPartEventHandler(Object sender, WebPartEventArgs e)

{this.Title = "Server Side Verb Click";

}

VBPublic Overrides ReadOnly Property Verbs() As WebPartVerbCollection

Get

‘create a client side verb eventDim ClientVerb As WebPartVerbClientVerb = New WebPartVerb("ClientVerb", "javascript:TestAlert()")ClientVerb.Description = "This is a client side verb"ClientVerb.Text = "My Client Verb"‘C:\Program Files\Common Files\

microsoft shared\Web Server Extensions\12\TEMPLATE\IMAGESClientVerb.ImageUrl = "/_layouts/images/ADDTOFAVORITES.GIF" ‘info icon

‘create a server side verb eventDim ServerVerb As WebPartVerbServerVerb = New WebPartVerb(

"ServerVerb", AddressOf ServerSideWebPartEventHandler)ServerVerb.Description = "This is a Server side verb"ServerVerb.Text = "My Server Verb"‘C:\Program Files\Common Files\

microsoft shared\Web Server Extensions\12\TEMPLATE\IMAGESServerVerb.ImageUrl = "/_layouts/images/warn16.GIF" ‘warning icon

‘Create an array so we can combine the‘custom verbs with the existing verbsDim customVerbsArray() As WebPartVerb = {ClientVerb, ServerVerb}

‘combine the custom verbs with the existing verbsDim customVerbsCollection As NewWebPartVerbCollection(MyBase.Verbs, customVerbsArray)‘return the new custom verbs collectionReturn customVerbsCollection

End GetEnd Property

Public Sub ServerSideWebPartEventHandler(ByVal sender As Object, ByVal e As WebPartEventArgs)

Me.Title = "Server Verb Clicked"

End Sub

185

Fox c06.tex V3 - 01/30/2009 5:24pm Page 186

Chapter 6: Advanced Custom Web Parts

Editing Custom Web Part PropertiesWeb Parts can contain properties that are editable at run time. You can edit the Web Part while the pageis in Edit mode or Run mode. Select the ‘‘Modify Shared Web Part’’ Verb from the Web Part menu whilein Run mode, as shown in Figure 6-5, to open the Web Part Editor.

Figure 6-5

The Web Part Editor opens on the right and enables you to modify the properties of the Web Part. Youcan see in Figure 6-6 that the properties are grouped into three categories:

❑ Appearance — This category is the only group expanded by default. The editor enables you toset properties such as the Title, Height, and Width.

❑ Advanced — Here, you can also modify some of the properties discussed in Chapter 5, like theHelp URL, Title URL, and icons for the Web Part and Web Part Gallery.

❑ Layout — The Layout section allows you to set the visibility and zone the Web Part belongs to.

You can also add your own custom properties that will appear in the editor. For example, let’s add acustom property to display the path to the XAP file. Add the code in Listing 6-9 to your SLWebPart.csfile. In this code, you create a local string field to hold the URL to the XAP file, called xapUrl and apublic Read and Write string property called XapUrl. This is just a standard .Net property. Add the

186

Fox c06.tex V3 - 01/30/2009 5:24pm Page 187

Chapter 6: Advanced Custom Web Parts

Personalizable and WebBrowsable attributes to the property to make it appear in the Web Part Editor.You can also optionally add the WebDescription and WebDisplayName to give it a friendly name anddescription in the Editor; otherwise, the Property name will be used. And finally, the Category attributewill group the property under this name; otherwise, the Miscellaneous category will be used.

Figure 6-6

Listing 6-9: Add a custom Web Part property

C##region Custom Properties

private string xapUrl;

//WebPart Editor Property[Personalizable(PersonalizationScope.Shared),WebBrowsable(true),WebDescription("The URL to the XAP package"),WebDisplayName("XAP package Url."),System.ComponentModel.Category("Configuration")]

Continued

187

Fox c06.tex V3 - 01/30/2009 5:24pm Page 188

Chapter 6: Advanced Custom Web Parts

Listing 6-9: Add a custom Web Part property (continued)

public string XapUrl{

get { return xapUrl; }set { xapUrl = value; }

}

#endregion

VB#Region "Custom Properties"

Private _xapUrl As String = "∼/XAP_Bin/SilverlightControl.xap"

‘WebPart Editor Property<Personalizable(PersonalizationScope.Shared), WebBrowsable(True),

WebDescription("The URL to the XAP package"),WebDisplayName("XAP package Url."),

System.ComponentModel.Category("Configuration")> _Public Property XapUrl() As String

GetReturn _xapUrl

End GetSet(ByVal value As String)

_xapUrl = valueEnd Set

End Property

#End Region

Add the code to hook up the property you created with the Silverlight control. Initialize the property inthe OnLoad event.

XapUrl = "∼/XAP_Bin/SilverlightControl.xap";

Change the source property of the Silverlight control to use the new XapUrl (see Listing 6-10).

Listing 6-10: Create the Silverlight control

C#protected override void CreateChildControls(){

base.CreateChildControls();

Silverlight ctrl = new Silverlight();ctrl.ID = "SLWebPartID";ctrl.Source = XapUrl;

ctrl.Width = Unit.Percentage(100);Controls.Add(ctrl);

}

VBProtected Overrides Sub CreateChildControls()

188

Fox c06.tex V3 - 01/30/2009 5:24pm Page 189

Chapter 6: Advanced Custom Web Parts

MyBase.CreateChildControls()

Dim ctrl As New Silverlight()ctrl.ID = "SLWebPartID"ctrl.Source = XapUrlctrl.Width = Unit.Percentage(100)Controls.Add(ctrl)End Sub

When you deploy and edit the Web Part, you will see the custom property at the bottom of the Editorpane. Figure 6-7 shows your custom Web Part property in the Configuration category that you created.

Figure 6-7

Using Custom Web Part EditorYou saw in the previous section that you can create your own custom properties that can appear in theWeb Part Editor pane. This works for simple properties, but if you have more complex properties, youwill want to create your own custom Web Part Editor. You will see that you not only can create acustom Web Part Editor, but you can make this editor be a Silverlight Editor.

Start by adding a new class called SLEditorPart under the SLWebPart folder in your SLWebPart project.Add the code in Listing 6-11 to the SLEditorPart.cs file.

189

Fox c06.tex V3 - 01/30/2009 5:24pm Page 190

Chapter 6: Advanced Custom Web Parts

Listing 6-11: Using statements for the custom Silverlight Web Part Editor

C#using System;using System.Collections.Generic;using System.Linq;using System.Text;

using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;

using System.Web.UI.SilverlightControls;

namespace SLWebPart{

public class SLEditorPart:EditorPart{

//the ID of the editor part has to be unique for// each instance of your webpart.public SLEditorPart(string webPartID){

this.ID = "SLEditorPart" + webPartID;}

protected override void OnLoad(EventArgs e){

base.OnLoad(e);

#region ScriptManagerScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);if (scriptManager == null){

scriptManager = new ScriptManager();Controls.AddAt(0, scriptManager);

}#endregion

}

protected override void CreateChildControls(){

base.CreateChildControls();

Silverlight ctrl = new Silverlight();ctrl.ID = "SLWebPartID";ctrl.Source = "∼/XAP_Bin/SilverlightControl.xap";ctrl.Width = Unit.Percentage(100);Controls.Add(ctrl);

}

public override void SyncChanges()

190

Fox c06.tex V3 - 01/30/2009 5:24pm Page 191

Chapter 6: Advanced Custom Web Parts

{

}

public override bool ApplyChanges(){

SLWebPart part = (SLWebPart)WebPartToEdit;part.Title = "Updated";return true;

}}

}

VBImports SystemImports System.Collections.GenericImports System.LinqImports System.Text

Imports System.Web.UIImports System.Web.UI.WebControlsImports System.Web.UI.WebControls.WebParts

Imports System.Web.UI.SilverlightControlsImports System.Web.UI.HtmlControls

Public Class SLEditorPartInherits EditorPartPublic Rating As HiddenFieldPrivate RatingValue As String = "1"

‘the ID of the editor part has to be unique for each instance of your webpart.Public Sub New(ByVal webPartID As String)

Me.ID = "SLEditorPart" & webPartIDEnd Sub

Protected Overrides Sub OnLoad(ByVal e As EventArgs)MyBase.OnLoad(e)

‘#Region "ScriptManager"Dim scriptManager As ScriptManager = scriptManager.GetCurrent(Me.Page)If scriptManager Is Nothing Then

scriptManager = New ScriptManager()Controls.AddAt(0, scriptManager)

End If‘#End Region

End Sub

Protected Overrides Sub CreateChildControls()MyBase.CreateChildControls()

Continued

191

Fox c06.tex V3 - 01/30/2009 5:24pm Page 192

Chapter 6: Advanced Custom Web Parts

Listing 6-11: Using statements for the custom Silverlight Web Part Editor (continued)

‘TODO: rEMOVE AFTER test‘Rating = 3;

‘hidden field to hold the value from the Silverlight slider controlRating = New HiddenField()Rating.ID = "RatingId"Rating.Value = RatingValueMyBase.Controls.Add(Rating)

Dim ctrl As New Silverlight()ctrl.ID = "SLWebPartID"ctrl.Source = "∼/XAP_Bin/SilverlightControl.xap"ctrl.Width = Unit.Pixel(230)ctrl.Height = Unit.Pixel(300)‘comma delimited key=value pairsctrl.InitParameters = String.Format("DisplayMode={0},RatingControlId={1}",

"Editor", Rating.ClientID)

Controls.Add(ctrl)End Sub

‘get values from Web PartPublic Overrides Sub SyncChanges()

‘SLWebPart part = (SLWebPart)WebPartToEdit;‘RatingValue = part.RatingXX.ToString();

End Sub

‘Update Web Part valuesPublic Overrides Function ApplyChanges() As Boolean

‘SLWebPart part = (SLWebPart)WebPartToEdit;‘part.Rating = Rating;Return True

End FunctionEnd Class

The code in Listing 6-11 inherits from the System.Web.UI.WebControls.WebParts.EditorPart. This isvery similar to the standard Web Part class except that it has two additional methods — SyncChanges andApplyChanges. In the same way that .NET properties use a special variable called value to pass the Prop-erty value to the set method of a property, the SyncChanges and ApplyChanges use the WebPartToEditvariable.

❑ SyncChanges — This is called by SharePoint when your Editor part is loaded. The method isused to pass data from the Web Part being edited to the Editor part. Use this method to updateproperties in the Editor part.

❑ ApplyChanges — This method is called when you apply the changes from the Web Part Editor.This is triggered by the user clicking on the Apply button at the bottom of the Editor pane. Youcan see in Listing 6-11 that the ApplyChanges sets the title property of the Web Part being edited.You will see in the Data Connectivity chapter (Chapter 7) how to connect these two methodswith the real data from the Silverlight control.

192

Fox c06.tex V3 - 01/30/2009 5:24pm Page 193

Chapter 6: Advanced Custom Web Parts

The only other change from a standard Web Part is the fact that the editor must have a unique ID. Onetechnique to generate a unique ID is to pass the ID of the Web Part being edited to the constructor of theEditor part.

Creating Editor PartsYou have now created the Silverlight Web Part Editor and need to add it to the collection of editorsfor your Web Part. To do this, override the CreateEditorParts. Add the code in Listing 6-12 to yourSLWebPart.cs class. The first thing to do is create a list of EditorPart objects and add a new instance toyour custom editor, SLEditorPart. Remember that to create a unique instance of the editor, pass the IDof the Web Part to the constructor. Next create a new EditorPartCollection and add your EditorPartlist to the constructor. You can add as many editors as you like to your list. This is a good technique tobuild custom editors using a more compartmentalized approach.

Listing 6-12: Add the custom Web Part Editor to the collection

C##region Use Custom Editorpublic override EditorPartCollection CreateEditorParts(){

//return base.CreateEditorParts();

List<EditorPart> customEditorPartCollection = new List<EditorPart>();customEditorPartCollection.Add(new SLEditorPart(this.ID));EditorPartCollection editorPartCollection =

new EditorPartCollection(customEditorPartCollection);return editorPartCollection;

}#endregion

VB#Region "Use Custom Editor"

Public Overrides Function CreateEditorParts() As EditorPartCollection‘return base.CreateEditorParts();

Dim customEditorPartCollection As List(Of EditorPart) =New List(Of EditorPart)()customEditorPartCollection.Add(New SLEditorPart(Me.ID))Dim editorPartCollection As

New EditorPartCollection(customEditorPartCollection)Return editorPartCollection

End Function#End Region

Display ModeSharePoint has several different modes to use while displaying your Web Parts. There are three modesthat are important when developing Web Parts:

193

Fox c06.tex V3 - 01/30/2009 5:24pm Page 194

Chapter 6: Advanced Custom Web Parts

❑ Browse Mode — This mode occurs when the user is using the site. This is the most usedmode.

❑ Design Mode — This mode occurs when the user clicks the Edit Page menu item under theSite Actions menu. The Design mode allows the user to add and remove Web Parts and tomove the Web Parts around to different zones or reorder the Web Parts within the samezone.

❑ Edit Mode — This mode occurs when the user selects the ‘‘Modify Shared Web Part’’ Verb fromthe Web Part’s Context menu.

Once you know what mode you are in, you can customize your Web Part UI, which, in the case of thisbook, is the Silverlight control. For example, if you are in Design mode, you could disable fields thatshouldn’t be changed while the Web Part is being moved. You could display special instructions tothe user on where the control can be used. Maybe the control does or doesn’t work in a certain zone. Thescenario we find most interesting is in Edit mode. Imagine making the entire Web Part become the editor,or working closely with the custom editor for a very rich editing experience. Let’s take a look at a simpleexample of changing the Silverlight UI based on the Display mode you are in.

The first thing is to determine the Display mode. Add the code in Listing 6-13 to the top of yourCreateChildControls method of your SLWebPart class.

Listing 6-13: Determine the Display mode

C##region Set Display Modestring DisplayMode = "Unknown";

if (this.WebPartManager.DisplayMode ==WebPartManager.BrowseDisplayMode)

DisplayMode = "Browse";else if (this.WebPartManager.DisplayMode ==

WebPartManager.EditDisplayMode)DisplayMode = "Edit";

else if (this.WebPartManager.DisplayMode ==WebPartManager.DesignDisplayMode)

DisplayMode = "Design";#endregion

VB’ #Region "Set Display Mode"Dim DisplayMode As String = "Unknown"

If Me.WebPartManager.DisplayMode Is WebPartManager.BrowseDisplayMode ThenDisplayMode = "Browse"

ElseIf Me.WebPartManager.DisplayMode Is WebPartManager.EditDisplayMode ThenDisplayMode = "Edit"

ElseIf Me.WebPartManager.DisplayMode Is WebPartManager.DesignDisplayMode ThenDisplayMode = "Design"

End If’ #End Region

Once you have determined the Display mode, you can pass this information to the Silverlight con-trol using the InitParameters property. (You will see the InitParameters property in more detail in

194

Fox c06.tex V3 - 01/30/2009 5:24pm Page 195

Chapter 6: Advanced Custom Web Parts

Chapter 7.) The InitParameters is a string formatted as a comma-separated list of key/value pairs.These will be parsed by the Silverlight control on the client and passed to the Startup method. List-ing 6-14 shows the code for the InitParameters property in the CreateChildControls method. In thisexample, we use the Format method to insert the parameter values.

Listing 6-14: Pass the Display mode to the Silverlight control

C#ctrl.InitParameters = string.Format("DisplayMode={0}", DisplayMode);

VBctrl.InitParameters = String.Format("DisplayMode={0}", DisplayMode)

Display Dynamic Silverlight UI Based on Web Part DisplayMode

In the previous section, you added the code in the Web Part to determine the Display mode and passthat to your Silverlight control. Now in this section, you will add the code to switch the UI based onthe current mode. Start by modifying the existing SilverlightControl project. You will create a new Usercontrol for each mode. Add three new Silverlight User controls to your SilverlightControl project. Namethe controls BrowseMode.xaml, DesignMode.xaml, and EditMode.xaml. All three controls are nearly identicalexcept for the TextBlock called ModeLabel. The ModeLabel control has the name of each mode. Add thecode in Listing 6-15 to all of the controls you just created, changing the ModeLabel as appropriate.

Listing 6-15: Custom UI for the Display modes

<UserControl x:Class="SilverlightControl.BrowseMode"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="400" Height="300"><Grid x:Name="LayoutRoot" >

<Grid.Background><LinearGradientBrush EndPoint="1,1" StartPoint="0,0">

<GradientStop Color="#FF070707" Offset="1"/><GradientStop Color="#FFFCFCFC"/>

</LinearGradientBrush></Grid.Background><TextBlock Height="52" Margin="95.949,0,67.051,32.5"

VerticalAlignment="Bottom" FontSize="24"TextWrapping="Wrap" Foreground="#FFFFFFFF"RenderTransformOrigin="0.5,0.5"x:Name="ModeLabel">

<TextBlock.RenderTransform><TransformGroup>

<ScaleTransform ScaleX="1.75" ScaleY="2.5"/><SkewTransform/><RotateTransform/><TranslateTransform/>

</TransformGroup></TextBlock.RenderTransform>

<Run FontFamily="Segoe UI" FontSize="30"Continued

195

Fox c06.tex V3 - 01/30/2009 5:24pm Page 196

Chapter 6: Advanced Custom Web Parts

Listing 6-15: Custom UI for the Display modes (continued)

FontWeight="Bold" Text="Browse Mode"/>

</TextBlock><TextBlock Height="89" HorizontalAlignment="Left"

Margin="28,37,0,0" VerticalAlignment="Top"Width="59" Text="5" TextWrapping="Wrap"x:Name="RatingLabel" FontFamily="Verdana"FontSize="72" FontWeight="Bold"RenderTransformOrigin="0.5,0.5">

<TextBlock.RenderTransform><TransformGroup>

<ScaleTransform ScaleX="1.75" ScaleY="2.55"/><SkewTransform/><RotateTransform/><TranslateTransform X="0"/>

</TransformGroup></TextBlock.RenderTransform>

</TextBlock><Slider Margin="131,37,39,148" Maximum="5" Minimum="1"

SmallChange="0.5" Value="1" FontSize="48"RenderTransformOrigin="0.5,0.5"x:Name="RatingSlider">

<Slider.RenderTransform><TransformGroup>

<ScaleTransform ScaleY="3.8" ScaleX="0.95"/><SkewTransform/><RotateTransform/><TranslateTransform/>

</TransformGroup></Slider.RenderTransform>

</Slider></Grid>

</UserControl>

Figure 6-8 shows an example of the design for the BrowseMode.xaml page. Again, all of the pages are thesame except for the text at the bottom. The design also has a Slider control that will be used in the DataConnectivity chapter (Chapter 7) to demonstrate editing the Web Parts and passing values around. Fornow, you can just ignore the Slider control.

You must also add the code in Listing 6-16 to each of the three controls. This code updates the rating textwith the Slider value. Again, you can ignore this code for now.

Listing 6-16: Code-behind to update Slider control values

C#using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;

196

Fox c06.tex V3 - 01/30/2009 5:24pm Page 197

Chapter 6: Advanced Custom Web Parts

using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;

using System.Windows.Browser;

namespace SilverlightControl{

public partial class BrowseMode : UserControl{

public BrowseMode(){

InitializeComponent();RatingSlider.ValueChanged += new

RoutedPropertyChangedEventHandler<double>(RatingSlider_ValueChanged);

}

void RatingSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){

//Update the LabelRatingLabel.Text = RatingSlider.Value.ToString();

}

}}

VBPartial Public Class BrowseMode

Inherits UserControl

Public Sub NewInitializeComponent()AddHandler RatingSlider.ValueChanged, AddressOf RatingSlider_ValueChanged‘Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value = DirectCast(Integer.Parse(

App.RatingControl.GetAttribute("value")), Integer)End Sub

Sub RatingSlider_ValueChanged(ByVal sender As Object, ByVal e As

RoutedPropertyChangedEventArgs(Of Double))‘Update the LabelRatingLabel.Text = RatingSlider.Value.ToString()‘Update the Hidden HTML Control ValueIf App.RatingControl IsNot Nothing Then

App.RatingControl.SetAttribute("value", RatingSlider.Value.ToString())End If

End Sub

End Class

197

Fox c06.tex V3 - 01/30/2009 5:24pm Page 198

Chapter 6: Advanced Custom Web Parts

Figure 6-8

Now that you have all of the UI controls for each Display mode, you can select which one gets displayed.The entry point for a Silverlight application is the App.xaml file. Add the code in Listing 6-17 to yourApp.xaml.cs file’s Application_Startup method.

Listing 6-17: Switch the UI based on the Display mode

C#private void Application_Startup(object sender, StartupEventArgs e){

UIElement StartPage;if (e.InitParams.ContainsKey("DisplayMode")){

switch (e.InitParams["DisplayMode"]){

case "Browse":

198

Fox c06.tex V3 - 01/30/2009 5:24pm Page 199

Chapter 6: Advanced Custom Web Parts

StartPage = new BrowseMode();break;

case "Edit":StartPage = new EditMode();break;

case "Design":StartPage = new DesignMode();break;

case "Editor":StartPage = new RatingEditor();break;

default:StartPage = new BrowseMode();break;

}}else{

StartPage = new BrowseMode();}

this.RootVisual = StartPage;}

VBPrivate Sub Application_Startup(

ByVal o As Object, ByVal e As StartupEventArgs)Handles Me.Startup‘get a reference to the RatingControlIf e.InitParams.ContainsKey("RatingControlId") Then

App.RatingControl = _HtmlPage.Document.GetElementById(e.InitParams("RatingControlId"))

End If

Dim StartPage As UIElementIf e.InitParams.ContainsKey("DisplayMode") Then

Select Case e.InitParams("DisplayMode")Case "Browse"

StartPage = New BrowseMode()Case "Edit"

StartPage = New EditMode()Case "Design"

StartPage = New DesignMode()Case "Editor"

StartPage = New RatingEditor()Case Else

StartPage = New BrowseMode()End Select

Continued

199

Fox c06.tex V3 - 01/30/2009 5:24pm Page 200

Chapter 6: Advanced Custom Web Parts

Listing 6-17: Switch the UI based on the Display mode (continued)

ElseStartPage = New BrowseMode()

End If

Me.RootVisual = StartPage

End Sub

This code is a switch that creates a new instance of the correct page and sets the visual root to this page.You can also see that we have added a fourth display mode, Editor mode. You can create this pageexactly like the other three. We actually tweak the layout of the EditorMode.xaml file just a little totake into account the smaller display area of the editor Web Part. This is not really a Display mode, butbecause you create the Silverlight Editor part from a separate class, you can ‘‘create’’ your own custom

Figure 6-9

200

Fox c06.tex V3 - 01/30/2009 5:24pm Page 201

Chapter 6: Advanced Custom Web Parts

modes. In this case, Listing 6-18 shows that you can just pass the string ‘‘Editor’’ to the InitParamatersin the SLEditorPart class. This enables you to have all of your UI in a single XAP file, including runtime, design time, and custom editors.

Listing 6-18: Custom editor Display mode

C#ctrl.InitParameters = string.Format("DisplayMode={0}", "Editor);

VBctrl.InitParameters = String.Format("DisplayMode={0}", "Editor)

After you deploy the changes to your SharePoint site, you will see the various display modes similar toFigures 6-9, 6-10, and 6-11.

Figure 6-10

201

Fox c06.tex V3 - 01/30/2009 5:24pm Page 202

Chapter 6: Advanced Custom Web Parts

Figure 6-11

SummaryIn the last two chapters, you have seen how to create Web Parts that support Silverlight. As you haveprogressed through the chapters, you have incrementally added more and more advanced functionalityto your Silverlight Web Parts. You have learned how to create complete Silverlight Web Part solutionsin Visual Studio that support [F5] deployment. You have learned how to debug all aspects of your WebParts from the SharePoint Web Part to the Silverlight client. You have seen how easy it is to debug yourWeb Parts end-to-end. You have learned how to debug Feature Receivers in the stsadm.exe processduring installation and uninstallation. This will allow you to create professional and maintainable WebParts for your production SharePoint server farms.

You have also learned how to make your Silverlight Web Parts behave as if they were integrated intoSharePoint. You have learned how to customize the Web Part Gallery and various aspects of the WebPart container itself such as the Title and Description. You have learned how to create custom menuitems, called Verbs, and how to have them call client and server methods.

202

Fox c06.tex V3 - 01/30/2009 5:24pm Page 203

Chapter 6: Advanced Custom Web Parts

You have seen how to create your own customer Silverlight Editor parts and integrate the display modeinto your Web Part design.

Although you have learned a lot about creating Silverlight Web Parts, these two chapters by no meanscover all aspects of Web Part development with Silverlight. In fact, entire books have been written aboutWeb Parts by themselves. But we hope that these chapters have introduced you to the various partsand techniques for developing great Silverlight Web Parts. You should now have a solid foundation forbuilding professional production-ready Web Parts using Silverlight.

As mentioned in the chapter, there is more to learn about connecting data in your Web Parts. In Chapter 7,you will explore some more Web Part features such as connecting Web Parts and passing data betweenWeb Parts and the Silverlight applications inside the Web Parts.

203

Fox c06.tex V3 - 01/30/2009 5:24pm Page 204

Fox c07.tex V3 - 01/30/2009 3:26pm Page 205

Data Connectivity

Silverlight and SharePoint provide a powerful platform with the ability to connect with the datastored in SharePoint and a rich user experience. SharePoint has various ways to access the data inthe SharePoint store. The first way is using the SharePoint object model, which provides a managedAPI that allows you to manipulate all aspects of SharePoint from the data to the site itself. Youcan access the API from components that run on the server, such as the web pages, Web Parts,and custom Web Services. The other way to access SharePoint is via the native SharePoint WebServices. SharePoint provides a number of services out-of-the-box for manipulating many aspectsof the SharePoint site and data. Typically the Web Services are used by clients that are runningoutside of the server. Understanding these two methods, the API and the Web Services, is the keyto understanding how to integrate Silverlight. See Figure 7-1 for details.

Another option is for the Silverlight controls to communicate between themselves and the pagethey are hosted on. This enables the controls to work together in a more loosely coupled manner.For example, you could have a master and detail relationship between controls. Different detailcontrols could be plugged into the page and communicate with the master control. This is thefoundation to building powerful composite applications in SharePoint.

First let’s take a look at the various push techniques to send data down to the Silverlight controlupon start-up.

Initialization ParametersInitialization parameters are the easiest way to get data into the Silverlight control. This featureis built into the Silverlight control. The Silverlight ASP.NET control has a property calledInitParameters, which is a comma-delimited string of key and value pairs. You can thenretrieve these parameters in the Silverlight control using the StartupEventArgs.InitParamsproperty in the Application.Startup event. You have seen this used in Chapters 5and 6 to pass the display mode. For example, to pass the display mode of Browse, setInitParameters = "DisplayMode=browse". In Listing 7-1, you are passing three parameters tothe Silverlight control: DisplayMode, RatingControlId, and RatingValuesID. This code runs onthe server in the ASP.NET or Web Part page. It is also useful for you to use as the string formatfunction to replace the parameter values in the correct places. As the number of parameters grows,this becomes more important to manage the list.

Fox c07.tex V3 - 01/30/2009 3:26pm Page 206

Chapter 7: Data Connectivity

SharePoint Store

SharePoint API

WebPart

AJAX/ScriptManager/

JavaScript BridgeSilverlight Control

WebPart

Isolated Storage

Custom Web Service SharePoint Web Service

Process Boundary

Figure 7-1

Listing 7-1: Pass parameters to the Silverlight control

C#Silverlight ctrl = new Silverlight();ctrl.ID = "SLWebPartID";ctrl.Source = XapUrl;ctrl.Width = Unit.Percentage(100);ctrl.Height = Unit.Pixel(300);//comma delimited key=value pairs

206

Fox c07.tex V3 - 01/30/2009 3:26pm Page 207

Chapter 7: Data Connectivity

ctrl.InitParameters =string.Format("DisplayMode={0},RatingControlId={1},

RatingValuesID={2}",DisplayMode, Rating.ClientID, RatingValuesID);

Controls.Add(ctrl);

VBDim ctrl As Silverlight = New Silverlight()ctrl.ID = "SLWebPartID"ctrl.Source = XapUrlctrl.Width = Unit.Percentage(100)ctrl.Height = Unit.Pixel(300)‘comma delimited key=value pairsctrl.InitParameters =

String.Format("DisplayMode={0},RatingControlId={1},RatingValuesID={2}", DisplayMode, Rating.ClientID,RatingValuesID)

Controls.Add(ctrl)

Retrieving the InitParametersListing 7-1 shows how to pass the parameters from the server. Now you will see how to consumethose values on the client. You can verify that the values are correct by looking at the source code ofthe web page in Internet Explorer. Listing 7-20 shows what this will look like. The Silverlight plug-inwill automatically convert the string of key and value pairs into a Dictionary object property calledInitParams. The InitParams property is on the StartupEventArgs object. The StartupEventArgsobject is passed as a parameter in the Application_Startup method of the App class, which islocated in the App.xaml.cs file. You should first use the ContainsKey method of the Dictionaryclass to determine if there is a valid parameter in the Dictionary. Once you are certain that the keyexists, you can set the name of the parameter as the key to the dictionary item’s value. Listing 7-2shows how to extract the values passed in from the code in Listing 7-1. Some of the code has beentaken out to show just the parameter logic. You will see more of this code later in the chapter. Oneway to use the passed parameter is as a switch. In this case, depending on the display mode passed,different user controls are shown as the root. You can see this in action in Chapters 5 and 6.

Listing 7-2: Retrieve the InitParams from the Application_Startup event

C#private void Application_Startup(object sender, StartupEventArgs e){

//get a reference to the RatingControlstring RatingControlID = "RatingControlId";if (e.InitParams.ContainsKey(RatingControlID))

. . .

//get a reference to the RatingValues XML Data Islandstring RatingValuesID = "RatingValuesID";if (e.InitParams.ContainsKey(RatingValuesID)){

Continued

207

Fox c07.tex V3 - 01/30/2009 3:26pm Page 208

Chapter 7: Data Connectivity

Listing 7-2: Retrieve the InitParams from the Application Startup event (continued)

. . .

}

UIElement StartPage;if (e.InitParams.ContainsKey("DisplayMode")){

switch (e.InitParams["DisplayMode"]){

case "Browse":StartPage = new BrowseMode();break;

case "Edit":StartPage = new EditMode();break;

case "Design":StartPage = new DesignMode();break;

case "Editor":StartPage = new RatingEditor();break;

default:StartPage = new BrowseMode();break;

}}else{

StartPage = new BrowseMode();}

this.RootVisual = StartPage;}

VBPrivate Sub Application_Startup(

ByVal o As Object, ByVal e As StartupEventArgs)Handles Me.Startup‘get a reference to the RatingControlIf e.InitParams.ContainsKey("RatingControlId") Then

. . .

End If

‘get a reference to the RatingValues XML Data IslandDim RatingValuesID As String = "RatingValuesID"If e.InitParams.ContainsKey(RatingValuesID) Then

. . .

End If

Dim StartPage As UIElementIf e.InitParams.ContainsKey("DisplayMode") Then

Select Case e.InitParams("DisplayMode")Case "Browse"

208

Fox c07.tex V3 - 01/30/2009 3:26pm Page 209

Chapter 7: Data Connectivity

StartPage = New BrowseMode()Case "Edit"

StartPage = New EditMode()Case "Design"

StartPage = New DesignMode()Case "Editor"

StartPage = New RatingEditor()Case Else

StartPage = New BrowseMode()End Select

ElseStartPage = New BrowseMode()

End If

Me.RootVisual = StartPage

End Sub

You can also see these values in the debugger. Set a breakpoint on the Application_Startup event.Open the QuickWatch debug window for the e parameter. This will be a common debugging taskas you start to use the InitParameters feature. You can see in Figure 7-2 that the InitParametersproperty of the e parameter passed contains three keys and values.

Figure 7-2209

Fox c07.tex V3 - 01/30/2009 3:26pm Page 210

Chapter 7: Data Connectivity

This method of passing parameters to the Silverlight control is good for small numbers of set-up andconfiguration parameters but is not recommended for passing large blocks of data. This is not goodsoftware design and also will slow the loading of the Silverlight control as it needs to download andparse the parameters prior to showing any user interface. It is also important to remember that thisis a one-way process, and the values are not sent back to the server in any way. You will see in thenext technique how this could be done.

Using Hidden FieldSilverlight is very good at interacting with the document object model of the browser that the con-trol is hosted on. This opens up several different places to store data for use in your Silverlightapplication. One place is in a hidden HTML input field. In this simple example (Listing 7-3), theRatingId is set to a value of 4. ASP.NET and SharePoint manage postback communications usingform fields. Silverlight can take advantage of this fact by using the browser bridge to read and writeto the form fields. Using these two concepts together, you can achieve an easy two-way communi-cation between Silverlight and SharePoint. In this section, you will see how to do this.

Listing 7-3: Hidden input control

<input type="hidden" name="RatingId" value="4" />

You can read this value when the usercontrol is created and set the initial state of the slider control(Listing 7-4).

Listing 7-4: Read the hidden input field

RatingSlider.Value =(int)int.Parse(HtmlPage.Document.GetElementById("RatingId"));

But while this code works when you are creating the HTML directly, it gets a little more com-plicated when generating the code from the Web Part. ASP.Net provides a server control calledHiddenField. The HiddenField control will output an input tag similar to the one in Listing 7-3.Create a HiddenField, and set the ID and Value properties in your Web Part. Listing 7-5 shows theserver control code that runs in the CreateChildControls method.

Listing 7-5: Create the HiddenField control

C#//hidden field to hold the value from the Silverlight slider controlRating = new HiddenField();Rating.ID = "RatingId";Rating.Value = "4";

Controls.Add(Rating);

VB‘hidden field to hold the value from the Silverlight slider controlRating = New HiddenField()Rating.ID = "RatingId"Rating.Value = "4"

Controls.Add(Rating)

210

Fox c07.tex V3 - 01/30/2009 3:26pm Page 211

Chapter 7: Data Connectivity

The problem with this code is that the server control generates a unique ID for each HiddenFieldcreated. So you actually get an input field generated that looks like the one in Listing 7-6. It isimportant to note that since this field is generated in the HTML page, it is visible to anyone viewingthe source code of the web page. Because of this, you should not use HiddenField to store sensitiveinformation.

Listing 7-6: The HiddenField control generates unique IDs

<input type="hidden"name="ctl00$m$g_805e723e_0b57_4c35_b893_c203905bc5c5$RatingId"id="ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_RatingId" value="4" />

In order to read this value in Silverlight, you need to know the control’s ID. Because it is generated,you will need to tell Silverlight what the generated ID value is. You can do this by passing the IDvalue to Silverlight using InitParameters. The HiddenField class has a property called ClientIDand retrieves the generated control ID. Pass the ClientID value down to Silverlight as a parametercalled RatingControlId using the code in Listing 7-7.

Listing 7-7: Pass the generated RatingControlID down to Silverlight

C#ctrl.InitParameters =

string.Format("DisplayMode={0},RatingControlId={1},RatingValuesID={2}",DisplayMode, Rating.ClientID, RatingValuesID);

VBctrl.InitParameters = String.Format("DisplayMode={0}, RatingControlId={1},RatingValuesID={2}", DisplayMode, Rating.ClientID, RatingValuesID)

Retrieve the RatingControlId parameter in the Application_Startup event. You will need touse this value later to set the slider controls value, but you can’t do this until the control is created.There are various ways that you could code this — for example, you could assign the e.InitParamsdictionary object to a local variable in the App class. You could parse out the individual dictionaryitems and store them as separate variables in the App class. In this case, the choice was made toparse out the individual values that will be needed later and retrieve the reference to the input box.The RatingControl field is also static, just to make it easy to retrieve later. Listing 7-8 shows theApplication_Startup code to retrieve the hidden field.

Listing 7-8: Retrieve the HTMLElement reference to the hidden field

C#public static HtmlElement RatingControl = null;

private void Application_Startup(object sender, StartupEventArgs e){

//get a reference to the RatingControlstring RatingControlID = "RatingControlId";if (e.InitParams.ContainsKey(RatingControlID))

App.RatingControl =HtmlPage.Document.GetElementById(

Continued

211

Fox c07.tex V3 - 01/30/2009 3:26pm Page 212

Chapter 7: Data Connectivity

Listing 7-8: Retrieve the HTMLElement reference to the hidden field (continued)

e.InitParams[RatingControlID]);

. . .

}

VBPrivate Sub Application_Startup(

ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup‘get a reference to the RatingControlIf e.InitParams.ContainsKey("RatingControlId") Then

App.RatingControl = _HtmlPage.Document.GetElementById(e.InitParams("RatingControlId"))

End If. . .

End Sub

The last thing to do is to set the slider controls value in the constructor of the user control where itis being used. Again, this can be done at any time — you are just setting it in the constructor as aconvenience. Listing 7-9 shows how to retrieve the hidden field from the static RatingControl fieldyou created in Listing 7-8.

Listing 7-9: Set the slider control from the hidden field

C#//Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value = (int)int.Parse(

App.RatingControl.GetAttribute("value"));

VB‘Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value = CInt(Integer.Parse(

App.RatingControl.GetAttribute("value"))

In this simple example, it would have been easier just to pass the value down in theInitParameters, but this technique offers one major benefit: It allows you to update thevalue and retrieve this value back on the server during a postback. Use the SetAttribute methodof the HTMLElement class to update the value property. Listing 7-10 shows how to update the valueproperty with the slider control’s value.

Listing 7-10: Update the value of the hidden field

C#App.RatingControl.SetAttribute("value", RatingSlider.Value.ToString());

VBApp.RatingControl.SetAttribute("value", RatingSlider.Value.ToString())

You verify that this is working by using the server Verb event handler that you created in Chapter 6.Listing 7-11 shows the server Verb event handler setting the title of the Web Part with the value fromthe hidden field called rating, which you created in Listing 7-5.

212

Fox c07.tex V3 - 01/30/2009 3:26pm Page 213

Chapter 7: Data Connectivity

Listing 7-11: Set the Web Part title upon postback

C#public void ServerSideWebPartEventHandler(

Object sender, WebPartEventArgs e){

this.Title = "Server Verb Clicked. Rating="+ Rating.Value;

}

VBPublic Sub ServerSideWebPartEventHandler(

ByVal sender As Object, ByVal e As WebPartEventArgs)

Me.Title = "Server Verb Clicked. Rating=" + Rating.Value

End Sub

In Figure 7-3 you can see that the slider value is 2. Click on the Web Part Verb ‘‘My Server Verb’’ tocause a postback to the server.

Figure 7-3

213

Fox c07.tex V3 - 01/30/2009 3:26pm Page 214

Chapter 7: Data Connectivity

After the postback, the Web Part title is updated from the hidden field value that was set inside theSilverlight control. Figure 7-4 shows the updated Web Part title.

Figure 7-4

You have seen that hidden fields can be used to round-trip data with the server. But what if youwant to round-trip data that is persisted across browser sessions? In the next section, you will seeanother technique for consuming data in your Silverlight application.

Using HTML CookiesHidden fields are a great way to round-trip your data to and from the server. But in order to usethat data across multiple browser sessions, you will need to use HTML cookies. Just like withthe HiddenField, you create the cookie in the Web Part on the server. In the following code example,you will pass the background color down to the Silverlight control as a cookie. Listing 7-12 showsthe code to add a cookie called BGColor to the Cookies collection. Unlike the HiddenField, you donot need to pass the ID to Silverlight because the field ID is not changed or dynamicallygenerated.

214

Fox c07.tex V3 - 01/30/2009 3:26pm Page 215

Chapter 7: Data Connectivity

Listing 7-12: Add a new cookie to the Cookies collection on the server

C#System.Drawing.Color BGC = System.Drawing.Color.Blue;//Convert the color to a HEX color valuestring BackgroundColor = "#" + BGC.ToArgb().ToString("X6");//Add the cookieSystem.Web.HttpCookie BGColorCookie = new

System.Web.HttpCookie("BGColor");BGColorCookie.Value = BackgroundColor.ToString();BGColorCookie.Expires = DateTime.Now.AddDays(1);

Context.Response.Cookies.Add(BGColorCookie);

VB‘CookiesDim BGC As System.Drawing.Color = System.Drawing.Color.Blue‘Convert the color to a HEX color valueDim BackgroundColor As String = "#" + BGC.ToArgb().ToString("X6")

‘Add the cookieDim BGColorCookie As New System.Web.HttpCookie("BGColor")BGColorCookie.Value = BackgroundColor.ToString()BGColorCookie.Expires = DateTime.Now.AddDays(1)

Context.Response.Cookies.Add(BGColorCookie)

In this example, you are setting the background to blue using a named color value of theSystem.Drawing.Color class. You need to convert this color object to an HTML color string thatcan be saved in a cookie. The HTML color format consists of a # sign followed by hexadecimal(Hex) values for the alpha channel: red color, green color, and blue color. For example, blue wouldbe #FF0000FF. The ToString method provides an overload, using the value X6, that will convertthe value to Hex. The X specifies to convert to Hex, and the case of the X will be the same caseas the output string. The number 6 in X6 specifies the minimum number of digits. If there are lessthan six digits, then zeros will be padded to the left. One thing to keep in mind is that this is just asimple example and six digits would only give you rgb and not the alpha channel for argb, whichwould be eight digits. You will see why this is important when you create the Silverlight clientcode. In this code using the Color class, you will always get eight digits.

Now that you have added the background color in the cookie, you want to add code to Silverlightto retrieve this value and set the background color. The first thing to do to make the sample a littleeasier to code is to name the item that you want to set the color on. In this case, the backgroundis actually a gradient background. This means that the background transitions between two ormore colors — only two in this example. Listing 7-13 shows how to set the name of one of theGradientStop objects to StopColor. This will make the StopColor object appear to IntelliSense inyour code-behind. You may need to build the project once before it appears.

Listing 7-13: Set the Name property of the GradientStop

<UserControl x:Class="SilverlightControl.BrowseMode"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

Continued

215

Fox c07.tex V3 - 01/30/2009 3:26pm Page 216

Chapter 7: Data Connectivity

Listing 7-13: Set the Name property of the GradientStop (continued)

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="400" Height="300"><Grid x:Name="LayoutRoot" >

<Grid.Background><LinearGradientBrush EndPoint="1,1" StartPoint="0,0">

<GradientStop Color="#FF000000" Offset="1"/>

<GradientStop x:Name="StopColor" Color="#FFFF0000"/></LinearGradientBrush>

</Grid.Background>

In the XAML you can see that the value of StopColor is set to #FFFF0000, which is red. Unfortu-nately, you can’t programmatically set the color of the GradientStop.color property using thesame string value. You will need to convert the HTML color string that you added to the cookieback to a Color object. In the full .NET Framework, there are converter classes that will do thisfor you. In Silverlight you need to write the converter yourself. The code is straightforward, andListing 7-14 shows one way this could be done.

Listing 7-14: Convert an HTML color string to a System.Windows.Media.Color object

C#public Color ColorFromString(string colorString){

//Assumes format "#FFFF0000"byte alpha, red, green, blue;int StartIndex = 1; //skip the #string value;

value = colorString.Substring(StartIndex, 2);alpha = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);red = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);green = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);blue = Convert.ToByte(value, 16);

return Color.FromArgb(alpha, red, green, blue);}

VBPublic Function ColorFromString(ByVal colorString As String) As Color

216

Fox c07.tex V3 - 01/30/2009 3:26pm Page 217

Chapter 7: Data Connectivity

‘Assumes format "#FFFF0000"Dim alpha As ByteDim red As ByteDim green As ByteDim blue As Byte‘skip the #Dim StartIndex As Integer = 1

Dim colorValue As String = ""

colorValue = colorString.Substring(StartIndex, 2)alpha = Convert.ToByte(colorValue, 16)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)red = Convert.ToByte(colorValue, 16)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)green = Convert.ToByte(colorValue, 16)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)blue = Convert.ToByte(colorValue, 16)

Return Color.FromArgb(alpha, red, green, blue)End Function

The color converter code just parses the color string and converts each Hex value back to a byte foreach argb value. You can then use the FromArgb method of the Color class to create a new Colorobject. As mentioned before, this code assumes that you are passing a string of argb format witheight characters. In order to handle the case with no alpha channel or other edge cases, you wouldneed to add those checks to this code.

The cookies are stored as a ‘‘;’’ (semicolon) delimited string of key and value pairs. This means thatyou need to do a little work to extract the individual cookie values from the collection. Listing 7-15shows how to check for a single cookie and return its value.

Listing 7-15: Return the cookie value

C#private static string GetCookie(string CookieName){

//return a ; delimeted string or Key and value pairsstring CookiesString = (string)HtmlPage.Document.Cookies;//Convert to array

Continued

217

Fox c07.tex V3 - 01/30/2009 3:26pm Page 218

Chapter 7: Data Connectivity

Listing 7-15: Return the cookie value (continued)

string[] CookiesArray = (string[])CookiesString.Split(’;’);//Convert Array to DictionaryDictionary<string, string> CookiesDictionary =

CookiesArray.ToDictionary(x => x.Split(’=’)[0], x => x.Split(’=’)[1]);

if(CookiesDictionary.ContainsKey(CookieName))return CookiesDictionary[CookieName];

elsethrow new System.Collections.Generic.KeyNotFoundException(

"The Cookie does not exist");}

VBPrivate Shared Function GetCookie(ByVal CookieName As String) As String

‘return a ; delimeted string or Key and value pairsDim CookiesString As String =_

DirectCast(HtmlPage.Document.Cookies, String)‘Convert to arrayDim CookiesArray As String() =

DirectCast(CookiesString.Split(";"c), String())‘Convert Array to DictionaryDim CookiesDictionary As Dictionary(Of String, String) = _CookiesArray.ToDictionary(Function(x As String) x.Split("=")(0), _

Function(x As String) x.Split("=")(1))

If CookiesDictionary.ContainsKey(CookieName) ThenReturn CookiesDictionary(CookieName)

ElseThrow New System.Collections.Generic.KeyNotFoundException(

"The Cookie does not exist")End If

End Function

The GetCookie method converts the cookies string into a Dictionary collection. First, get the cook-ies string by calling the Cookies property of the Document object. Next, use the Split method toconvert the cookies string into an array of key and value pairs. Once you have this as an array, youcan use the ToDictionary method of the array to convert the array to a Dictionary object. TheToDictionary method has several overloads. You will use one of these to specify how to set the keyand the value. The parameters are Lambda expressions. You can think of Lambdas as mini-inlinefunctions. To specify the key, use the expression x => x.Split(’=’)[0]. The left side of the => isthe value that will be set as the key. The right side of the equation uses the split method to extract thekey value pair from x, which is the whole value. This is a little complicated when you see these forthe first time. For example, the BGColor value in the cookies array would be ‘‘BGColor=#FF0000FF",which is what you set it to in Listing 7-16. So the x.Split(’=’)[0] returns ‘‘BGColor", and thex.Split(’=’)[1] returns ‘‘#FF0000FF". After this, you have a Dictionary object and can look upthe value of any cookie in the Cookies collection.

All that remains is to make the call to set the StopColor color property. You can call this at any time.In this example, you call it in the constructor of the user control.

218

Fox c07.tex V3 - 01/30/2009 3:26pm Page 219

Chapter 7: Data Connectivity

Listing 7-16: Set the background color from the cookie

C#StopColor.Color = ColorFromString(GetCookie("BGColor"));

VBStopColor.Color = ColorFromString(GetCookie("BGColor"))

You can see the cookie values in the debugger in Figure 7-5. This is helpful to debug cookie issues.

Figure 7-5

You can also see the cookie values directly in Internet Explorer (IE). Open the Internet ExplorerDeveloper toolbar. You can find and install the toolbar by searching the Microsoft Download Centerfor ‘‘Internet Explorer Developer Toolbar.’’ Select Cache � View Cookie Information from the IEDeveloper Toolbar. A new browser window like the one in Figure 7-6 will open and display all ofthe cookie values. The Developer toolbar is also useful to clear the cookies. You can use this to testand debug your code under various scenarios.

219

Fox c07.tex V3 - 01/30/2009 3:26pm Page 220

Chapter 7: Data Connectivity

Figure 7-6

XML Data IslandYet another approach is to use an XML Data Island. XML Data Islands allow you to put an XML docu-ment inside your HTML page. This approach works well when you have a large amount of structureddata. The XML data is available to the Silverlight control and to the HTML page as well. The downsideto this approach is that XML Data Islands are only supported in Internet Explorer.

Creating the Server ControlJust like all of the other examples, you start by creating the server control in the Web Part. For the XMLData Island, you simply use a Literal control to hold the XML document as a string. Add the code inListing 7-17 to your CreateChildControls method in the Web Part.

Listing 7-17: Add a Literal control to write the XML Data Island

C#//XML Data Islandstring RatingValuesID = "RatingValues";

220

Fox c07.tex V3 - 01/30/2009 3:26pm Page 221

Chapter 7: Data Connectivity

base.Controls.Add(CreateXMLDataIsland(RatingValuesID));

VB‘XML Data IslandDim RatingValuesID As String = "RatingValues"Controls.Add(CreateXMLDataIsland(RatingValuesID))

Listing 7-17 calls the CreateXMLDataIsland method, which does all the work. In this example, you willadd an XML Data Island to hold the string names of the various rating values. Listing 7-18 shows anexample of the XML that you want to insert into the Literal control. The XML must have a root tag calledXML and an ID. The ID is how the data is referenced in the DOM.

Listing 7-18: A sample XML Data Island

<XML id="RatingValues"><RATINGS>

<RATING value="1">Strongly Agree</RATING><RATING value="2">Agree</RATING><RATING value="3">Disagree</RATING><RATING value="4">Strongly Disagree</RATING><RATING value="5">Not Applicable</RATING>

</RATINGS></XML>

Add a new function to the Web Part class called CreateXMLDataIsland, which takes the ID name of theXML as a parameter and returns a new Literal control. In this example, you will use LINQ for XML tocreate the XML document, but in a real application, you might build the XML from a SQL database or aWeb Service call. Enter the code in Listing 7-19 to your Web Part class.

Listing 7-19: Use LINQ for XML to build the XML Data Island Literal control

C#private LiteralControl CreateXMLDataIsland(String ControlID){

//<XML id="RatingValues">// <RATINGS>// <RATING value="1">Strongly Agree</RATING>// <RATING value="2">Agree</RATING>// <RATING value="3">Disagree</RATING>// <RATING value="4">Strongly Disagree</RATING>// <RATING value="5">Not Applicable</RATING>// </RATINGS>//</XML>

//Build the XML using LinqXElement xmlDataIsland =

new XElement("XML",new XAttribute("id", ControlID),

new XElement("RATINGS",new XElement("RATING",

new XAttribute("value", "1"),

Continued

221

Fox c07.tex V3 - 01/30/2009 3:26pm Page 222

Chapter 7: Data Connectivity

Listing 7-19: Use LINQ for XML to build the XML Data Island Literal control (continued)

"Strongly Agree"),new XElement("RATING",

new XAttribute("value", "2"),"Agree"),

new XElement("RATING",new XAttribute("value", "3"),"Disagree"),

new XElement("RATING",new XAttribute("value", "4"),"Strongly Disagree"),

new XElement("RATING",new XAttribute("value", "5"),"Not Applicable")

));

return new LiteralControl(xmlDataIsland.ToString());}

VBPrivate Function CreateXMLDataIsland(ByVal ControlID As String)

As LiteralControl‘<XML id="RatingValues">‘ <RATINGS>‘ <RATING value="1">Strongly Agree</RATING>‘ <RATING value="2">Agree</RATING>‘ <RATING value="3">Disagree</RATING>‘ <RATING value="4">Strongly Disagree</RATING>‘ <RATING value="5">Not Applicable</RATING>‘ </RATINGS>‘</XML>

‘Build the XML using LinqDim xmlDataIsland As New XElement("XML", New XAttribute("id", ControlID),

New XElement("RATINGS", New XElement("RATING",New XAttribute("value", "1"), "Strongly Agree"),New XElement("RATING", New XAttribute("value", "2"), "Agree"),New XElement("RATING", New XAttribute("value", "3"), "Disagree"),New XElement("RATING", New XAttribute("value", "4"), _

"Strongly Disagree"),New XElement("RATING", New XAttribute("value", "5"), "Not Applicable")))

Return New LiteralControl(xmlDataIsland.ToString())End Function

Running the page, you will be able to see the XML Data Island inside the page by viewing the sourcein Internet Explorer. Listing 7-20 shows the source code for the SharePoint page that contains your Web

222

Fox c07.tex V3 - 01/30/2009 3:26pm Page 223

Chapter 7: Data Connectivity

Part. The entire Web Part is contained in a single TD tag. You can also see the HiddenField that you addedearlier as well as the Silverlight plug-in control. Also within the Silverlight plug-in code, you can see theInitParameters that you set in the first part of this chapter.

Listing 7-20: HTML source code for Web Part

<td class="" valign="top"><div WebPartID="805e723e-0b57-4c35-b893-c203905bc5c5" HasPers="false"

id="WebPartctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5"width="100%" class="ms-WPBody" allowDelete="false"allowExport="false" style="" >

<div id="ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5"><script type="text/javascript">//<![CDATA[

Sys.WebForms.PageRequestManager._initialize(’ctl00$m$g_805e723e_0b57_4c35_b893_c203905bc5c5$ctl00’,

document.getElementById(’aspnetForm’));Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);//]]>

</script><input type="hidden"

name="ctl00$m$g_805e723e_0b57_4c35_b893_c203905bc5c5$RatingId"id="ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_RatingId"value="4" /><XML id="RatingValues"><RATINGS>

<RATING value="1">Strongly Agree</RATING><RATING value="2">Agree</RATING><RATING value="3">Disagree</RATING><RATING value="4">Strongly Disagree</RATING><RATING value="5">Not Applicable</RATING>

</RATINGS></XML><span id="ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_SLWebPartID_parent">

</span><script type="text/javascript">//<![CDATA[

Sys.UI.Silverlight.Control.createObject(’ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_SLWebPartID_parent’,’<object type="application/x-silverlight"data="data:application/x-silverlight,"id="ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_SLWebPartID"style="height:300px;width:100%;">\r\n\t<param name="InitParams"value="DisplayMode=Browse,RatingControl

Id=ctl00_m_g_805e723e_0b57_4c35_b893_c203905bc5c5_RatingId,RatingValuesID=RatingValues">\r\n\r\n\t</param><ahref="http://go2.microsoft.com/fwlink/?LinkID=114576&amp;v=1.0">

<img src="http://go2.microsoft.com/fwlink/?LinkID=108181"alt="Get Microsoft Silverlight" style="border-width:0;" />

Continued

223

Fox c07.tex V3 - 01/30/2009 3:26pm Page 224

Chapter 7: Data Connectivity

Listing 7-20: HTML source code for Web Part (continued)

</a>\r\n</object>’);//]]>

</script>

</div></div>

</td>

In the App class of the Silverlight application, you will retrieve the XML Data Island from the HTMLdocument. In this example, you pass the name of the Data Island down to the Silverlight applicationusing the InitParameters property. This is not strictly necessary in this case as, unlike the HiddenFieldexample, the ID of the XML Data Island is not changed when it is generated. But it is good practice todecouple your application as much as possible. This also allows greater reuse of code because the namesare not hard-coded. Listing 7-21 shows the code to extract the XML string and convert it to a LINQ forXML XElement class. Add this code to the Application_Startup method. The value is stored as a staticvariable in the class called RatingValues.

Listing 7-21: Convert the XML Data Island to a System.Xml.Linq.XElement object

C#//get a reference to the RatingValues XML Data Islandstring RatingValuesID = "RatingValuesID";if (e.InitParams.ContainsKey(RatingValuesID)){

//Get the data islandHtmlElement XMLDataIslandElement =

HtmlPage.Document.GetElementById(e.InitParams[RatingValuesID]);//Get the XML stringString XMLDataIslandText = XMLDataIslandElement.

GetProperty("innerHTML").ToString();

//Load the XML Data IslandRatingValues = XElement.Parse(XMLDataIslandText);

}

VB‘get a reference to the RatingValues XML Data IslandDim RatingValuesID As String = "RatingValuesID"If e.InitParams.ContainsKey(RatingValuesID) Then

‘Get the data islandDim XMLDataIslandElement As HtmlElement = HtmlPage.Document.

GetElementById(e.InitParams(RatingValuesID))‘Get the XML stringDim XMLDataIslandText As String = XMLDataIslandElement.

GetProperty("innerHTML").ToString()

224

Fox c07.tex V3 - 01/30/2009 3:26pm Page 225

Chapter 7: Data Connectivity

‘Load the XML Data IslandRatingValues = XElement.Parse(XMLDataIslandText)

End If

Once you have the XML as an XElement, you can parse this to extract the individual rating text values. Inthe user control class, each time the slider control value changes, you can update the label control. Addthe code in Listing 7-22 to your BrowseMode class. This method uses LINQ for XML to query the XMLData Island searching for an XML node with an attribute called value equal to the rating slider control’svalue. The query will return a collection of string values. In this example, there should only ever be one,so just set the label’s text property to the first item in the LINQ collection.

Listing 7-22: Use LINQ for XML to query the XML Data Island

C#private void UpdateSliderTextValue(){

var RatingValue = from item in App.RatingValues.Elements("RATING")where (string)item.Attribute("value").Value ==

RatingSlider.Value.ToString()select (string)item.Value;

//Set the text valueModeLabel.Text = RatingValue.First<String>();

}

VBPrivate Sub UpdateSliderTextValue()

Dim RatingValue = From item In App.RatingValues.Elements("RATING") _Where DirectCast(

item.Attribute("value").Value, String) =RatingSlider.Value.ToString() _Select DirectCast(item.Value, String)

‘Set the text valueModeLabel.Text = RatingValue.First

End Sub

In Figure 7-7 you can see the various slider states and the different label values that you extracted fromthe XML Data Island.

Setting the URL for an XML Data SourceYou have seen in this section that using XML Data Islands is a convenient way to pass XML structureddata down to the HTML page. Another supported way to get the XML into the Data Island is using thesrc property of the XML node. For example, to inject an XML document called RatingValues.xml into thepage, you would use the following code:

<XML ID="RatingValues" SRC="http://localhost/ RatingValues.xml"></XML>

225

Fox c07.tex V3 - 01/30/2009 3:26pm Page 226

Chapter 7: Data Connectivity

Figure 7-7

226

Fox c07.tex V3 - 01/30/2009 3:26pm Page 227

Chapter 7: Data Connectivity

Calling Web ServicesUp to this point, you have seen how to push data down to the Silverlight client. In this section, you willsee how to use Silverlight to pull data down into the client from SharePoint Web Services and how tobuild and call your own custom Web Services. To do this, add a new contact list to the SharePoint site.

Adding a New Contact List to the SharePoint SiteThis list will be the list you data-bind to in your Silverlight control. To add a new list in SharePoint:

1. Select Site Actions � Create from the page menu.

2. On the Create page, select Contacts under the Communications section, and name the listContactsList.

3. Add some names to the list. Your list should look similar to Figure 7-8.

Figure 7-8

227

Fox c07.tex V3 - 01/30/2009 3:26pm Page 228

Chapter 7: Data Connectivity

You can now get the ContactsList in your Silverlight control using the built-in SharePointWeb Service, List.asmx. This Web Service allows you to read and write SharePoint lists.

4. Add a service reference to your Silverlight control. The URL to the GetList servicewill be http://localhost/vtibin/list.asmx. Name the service ListService. Youwill see that the Add Service Reference Wizard has also added a config file calledServiceReferences.ClientConfig to your Silverlight project. This config file contains the WCFconfiguration information. For this example, there are no changes required to the config file.

5. In the constructor of the Page user control, add the code from Listing 7-23.

Listing 7-23: Call the ListService to return items from the SharePoint list

C#public Page(){

InitializeComponent();

ListService.ListsSoapClient SPList =new CustomListSilverlight.ListService.ListsSoapClient();

//Add handler to get resultsSPList.GetListItemsCompleted +=

new EventHandler<CustomListSilverlight.ListService.GetListItemsCompletedEventArgs>(SPList_GetListItemsCompleted);

String listName = "ContactsList";//Build CAML fieldsString viewName = null;XElement query = XElement.Parse(@"<Query />"); //return all rowsXElement viewFields = XElement.Parse(@"

<ViewFields><FieldRef Name=’FirstName’ /><FieldRef Name=’Title’ />

</ViewFields>"); //return First and Last Name

String rowLimit = null;XElement queryOptions = XElement.Parse(@"<QueryOptions />");string webID = null;

//Call the List Service to return the items from the listSPList.GetListItemsAsync(

listName, viewName, query,viewFields, rowLimit, queryOptions, webID);

}

VBPublic Sub New()

InitializeComponent()

Dim SPList As ListService.ListsSoapClient =

228

Fox c07.tex V3 - 01/30/2009 3:26pm Page 229

Chapter 7: Data Connectivity

New CustomListSilverlight.ListService.ListsSoapClient()

‘Add handler to get resultsAddHandler SPList.GetListItemsCompleted, AddressOf

SPList_GetListItemsCompleted‘SPList.geGetListItemsCompleted += New EventHandler(Of

CustomListSilverlight.ListService.GetListItemsCompletedEventArgs)(SPList_GetListItemsCompleted)

Dim listName As String = "ContactsList"‘Build CAML fieldsDim viewName As String = Nothing‘return all rowsDim query As XElement = <Query/>‘return First and Last NameDim viewFields As XElement = <ViewFields>

<FieldRef Name=’FirstName’/><FieldRef Name=’Title’/>

</ViewFields>Dim rowLimit As String = NothingDim queryOptions As XElement = <QueryOptions/>Dim webID As String = Nothing

‘Call the List Service to return the items from the listSPList.GetListItemsAsync(listName, viewName, query,

viewFields, rowLimit, queryOptions, _webID)

End Sub

The code in Listing 7-23 creates a new instance of the ListService. You then need to addan event handler to handle the GetListItems completed event. In Silverlight all service callsare done asynchronously. Next you need to build a CAML query to pass as a parameter inthe GetListItems method call. CAML is the query language of SharePoint and is outside thescope of this book.

6. In the Page.xaml, add a ListBox to render the results of the GetListItems service call. Addthe XAML in Listing 7-24 to your Page.xaml file. This will add a ListBox to the page andalso provide a data template to bind the individual fields to.

Listing 7-24: Add a list to data-bind the SharePoint list results

<Grid x:Name="LayoutRoot" Background="White"><ListBox x:Name="SPList" Width="375" Height="275">

<ListBox.ItemTemplate><DataTemplate>

<StackPanel Orientation="Vertical"><TextBlock FontFamily="Arial"

Continued

229

Fox c07.tex V3 - 01/30/2009 3:26pm Page 230

Chapter 7: Data Connectivity

Listing 7-24: Add a list to data-bind the SharePoint list results (continued)

FontWeight="Bold"Foreground="Red"

Text="{Binding LastName}" /><TextBlock FontFamily="Arial"

Text="{Binding FirstName}" /></StackPanel>

</DataTemplate></ListBox.ItemTemplate>

</ListBox></Grid>

Data-Bind to the ListBoxAt this point, you have created the SharePoint List, added the Service Reference, created a data-bindableListBox, and called the GetListItems service. The last step is to handle the completed event to data-bindthe results to the ListBox. Calling SharePoint Web Services can get a little complicated and is not asstraightforward as calling the SharePoint API directly. For example, the GetListItems service call returnsan ADO.NET data set formatted XML document like the one in Listing 7-25.

Listing 7-25: XML result set returned by the SharePoint GetListItem service

<?xml version="1.0" encoding="utf-8"?><listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"xmlns:rs="urn:schemas-microsoft-com:rowset"

xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/"><rs:data ItemCount="3"><z:row ows_FirstName="Steve"

ows_Title="Fox"ows_MetaInfo="2;#"ows__ModerationStatus="0"ows__Level="1" ows_ID="2"ows_owshiddenversion="1"ows_UniqueId="2;#{9D6BED54-9A42-48B8-BC41-F902F8DE6895}"ows_FSObjType="2;#0"ows_Created="2008-10-15 09:28:10"ows_FileRef="2;#Lists/ContactsList/2_.000" />

<z:row ows_FirstName="Laurence"ows_Title="Moroney"ows_MetaInfo="3;#"ows__ModerationStatus="0"ows__Level="1"ows_ID="3"ows_owshiddenversion="1"ows_UniqueId="3;#{FB0AE8A8-4154-43C6-8EA3-EFC7EC954EA0}"ows_FSObjType="3;#0"ows_Created="2008-10-15 09:29:10"ows_FileRef="3;#Lists/ContactsList/3_.000" />

<z:row ows_FirstName="Paul"

230

Fox c07.tex V3 - 01/30/2009 3:26pm Page 231

Chapter 7: Data Connectivity

ows_Title="Stubbs"ows_MetaInfo="1;#"ows__ModerationStatus="0"ows__Level="1"ows_ID="1"ows_owshiddenversion="1"ows_UniqueId="1;#{2071900D-E333-4410-8A7C-7EB1594AABC6}"ows_FSObjType="1;#0"ows_Created="2008-10-15 09:27:59"ows_FileRef="1;#Lists/ContactsList/1_.000" />

</rs:data></listitems>

Although this looks complicated, LINQ for XML makes short work of parsing and data-bindingthe code to your ListBox. Before you write the code to handle the results, you need to create a simpleclass to hold the results as you parse them with LINQ. Create a class called ListRow, and add the code inListing 7-26.

Listing 7-26: Simple class to hold LINQ results for data-binding

C#public class ListRow{

public string LastName { get; set; }public string FirstName { get; set; }

}

VBPublic Class ListRow

Private _FirstName As String = ""Private _LastName As String = ""

Public Property LastName() As StringGet

Return _LastNameEnd GetSet(ByVal value As String)

_LastName = valueEnd Set

End Property

Public Property FirstName() As StringGet

Return _FirstNameEnd GetSet(ByVal value As String)

_FirstName = valueEnd Set

End PropertyEnd Class

231

Fox c07.tex V3 - 01/30/2009 3:26pm Page 232

Chapter 7: Data Connectivity

You now have everything in place to handle the results. Add the code in Listing 7-27 to your Page class.First, convert the results into an XDocument object. Next, use a LINQ query to parse the results and convertthem to a format for data-binding to the list. You can see in Listing 7-24 that you created two propertybindings called LastName and FirstName. Once you have the new data structure, you simply set theItemsSource property of the SPList ListBox to the results of the LINQ query. Not too bad — only threelines of code to display the list items from SharePoint.

Listing 7-27: Parse and data-bind the GetListItems service results to the ListBox

C#void SPList_GetListItemsCompleted(object sender,

SilverlightControl.ListsService.GetListItemsCompletedEventArgs e)

{XDocument listResults = XDocument.Parse(e.Result.ToString());

var rows = from item in listResults.Descendants(XName.Get("row", "#RowsetSchema"))

select new ListRow{

FirstName = (String)item.Attribute("ows_FirstName").Value,

LastName = (String)item.Attribute("ows_Title").Value};

SPList.ItemsSource = rows;}

VBPrivate Sub SPList_GetListItemsCompleted(ByVal sender As Object,

ByVal e As ListService.GetListItemsCompletedEventArgs)Dim listResults As XDocument = XDocument.Parse(e.Result.ToString())

Dim rows = From item In _listResults.Descendants(XName.[Get]("row", "#RowsetSchema")) _

Select New ListRow() With _{ _

.FirstName = item.Attribute("ows_FirstName").Value, _

.LastName = item.Attribute("ows_Title").Value _}

SPList.ItemsSource = rowsEnd Sub

When you run your solution, you should see results similar to those shown in Figure 7-9.

While in the end calling the built-in SharePoint Web Service was not very difficult in this example, it canget very complicated as the size of your application increases. Also, the Web Services do not supportall of the functionality of SharePoint. To access all that SharePoint has to offer, you will need to use theSharePoint API. You saw in Chapter 3 how to create and call your own custom Web Services.

232

Fox c07.tex V3 - 01/30/2009 3:26pm Page 233

Chapter 7: Data Connectivity

Figure 7-9

Part-to-Part CommunicationIn the previous sections, you learned how to communicate from the server to the client by pushing datadown to Silverlight. You also learned how to communicate from the client to the server using servicecalls. In this section, you will learn how to communicate between Silverlight controls on the same page.

There are two main ways that you can transfer data between Silverlight controls in Web Parts: on theserver or on the client. On the server, you communicate using standard Web Part–to–Web Part tech-niques that are built into SharePoint. There are many books and articles published that demonstrate howto do this, so we won’t repeat them in this book. These techniques are good for communicating betweenSilverlight controls, but the communication only occurs on the server.

The second way for Silverlight controls to communicate is on the client. You can see in Figure 7-10 thatthe Silverlight controls can communicate with any other Silverlight control on the page, even if it’s notwithin a Web Part. This gives you the ability to communicate with Silverlight controls in the master pageor the page layout.

233

Fox c07.tex V3 - 01/30/2009 3:26pm Page 234

Chapter 7: Data Connectivity

Looking at the client side of the diagram in Figure 7-10, you can see that there are three basic ways thatthe controls can connect to each other:

❑ The most common is through JavaScript code on the HTML page.

❑ The one that you are going to use in this chapter allows the Silverlight controls to communicatedirectly without writing any JavaScript code.

❑ The third way is really a variation on the second approach, in which you have a single Silverlightcontrol be the event aggregator for all of the other controls on the page.

An event aggregator allows you the most flexibility to construct the architecture of your SharePoint site.For example, if you use the event aggregator pattern, you could create a single Silverlight applicationthat contains several user controls. As your application grows, you could move those user controls intoseparate Web Parts without changing any code. The event aggregation model would apply to user con-trols in a single application and user controls contained within a Web Part. Although a detailed exampleof the event aggregator is out of the scope of this book, the example you will create is the foundation formore advanced scenarios.

MySharePointPage.aspx

MySharePointPage.aspx

Web Part 1(Provider)

Web Part 1(Provider)

Web Part 2 (Consumer)

Web Part 2 (Consumer)

SilverlightControl 1

SilverlightControl 1

SilverlightControl 3

SilverlightControl 3

Javascript/HtmlPage

SilverlightControl 2

SilverlightControl 2

Serv

erCl

ient

Figure 7-10

The Browser Bridge is very useful in having Silverlight–Silverlight communication on the same page.While it is very common for developers to use JavaScript to marshal the communication, it’s actuallypretty simple, and arguably more powerful, to do this marshalling in your .NET code too. In this example,you’ll see how to do this. You are going to use the rating slider application that you have been buildingthroughout this chapter. You will add the ability for the application so that if the slider changes on onecontrol, all of the others will change as well. What is interesting about this code is that the applicationwill dynamically find the other controls on the page and hook up the events. Unlike the SharePoint Web

234

Fox c07.tex V3 - 01/30/2009 3:26pm Page 235

Chapter 7: Data Connectivity

Part–to–Web Part model, there is no registration required. This is a contrived application, but the patternof a parent control controlling a number of child controls is very common. For example, Master detailapplications can actually be separate Web Parts so that as a user adds any number of Web Parts from agallery of detail views, he or she would automatically get the events from the parent control. Let’s getstarted.

Registering ControlsYou can see in Figure 7-10 that the Silverlight controls communicate with each other via the HTML pagethat the controls are part of. In this solution, each control registers its control ID to a property on thepage. By doing this, each Silverlight control added to the page is added to the list of available controls.You could use this technique to group like controls together by using different properties. Listing 7-28shows how each control is registered. This method is called from the class constructor. In this code, youfirst retrieve the current list of registered Silverlight controls. After adding the current control’s ID tothe list, it is serialized to a comma-delimited string and saved as an HTML Window property. This isrequired because like the HiddenField control, the Silverlight plug-in ID is dynamically generated onthe server. You also must register the instance of the object that you want to make available to the otherclasses. In this case it is this object, but it could be any class that is marked with the ScriptableTypeattribute. You will use the ScriptObject’s registered name later when you retrieve an instance to call.

Listing 7-28: Register the control with the HTML page

C#//Register this control with the HTML pageprivate void RegisterSLControl(){

List<string> SLRatingControls = GetSLRatingsControlsList();

//Add the ControlID to the listSLRatingControls.Add(HtmlPage.Plugin.Id);

HtmlPage.RegisterScriptableObject(ScriptObjectName, this);HtmlPage.Window.SetProperty(SLRatingControlsPropertyName,

string.Join(",", SLRatingControls.ToArray()));}

VB‘Register this control with the HTML pagePrivate Sub RegisterSLControl()

Dim SLRatingControls As List(Of String) = GetSLRatingsControlsList()

‘Add the ControlID to the listSLRatingControls.Add(HtmlPage.Plugin.Id)

HtmlPage.RegisterScriptableObject(ScriptObjectName, Me)HtmlPage.Window.SetProperty(SLRatingControlsPropertyName,String.Join(",", SLRatingControls.ToArray()))

End Sub

In Listing 7-28, you made a call to the GetSLRatingControlsList method. This method reads the stringproperty from the HTML page and converts it to a List object. Enter the method in Listing 7-29 to yourclass.

235

Fox c07.tex V3 - 01/30/2009 3:26pm Page 236

Chapter 7: Data Connectivity

Listing 7-29: Convert the registered Silverlight control string to a List object

C#private List<string> GetSLRatingsControlsList(){

List<string> SLRatingControls;

string SLRatingControlsString =(string)HtmlPage.Window.GetProperty(SLRatingControlsPropertyName);

if (SLRatingControlsString == null)SLRatingControls = new List<string>();

else//convert the string back to a listSLRatingControls = new

List<string>(SLRatingControlsString.Split(’,’));

return SLRatingControls;}

VBPrivate Function GetSLRatingsControlsList() As List(Of String)

Dim SLRatingControls As List(Of String)

Dim SLRatingControlsString As String =DirectCast(HtmlPage.Window.GetProperty(

SLRatingControlsPropertyName), String)

If SLRatingControlsString Is Nothing ThenSLRatingControls = New List(Of String)()

Else‘convert the string back to a listSLRatingControls = New List(OfString)(SLRatingControlsString.Split(","c))

End If

Return SLRatingControlsEnd Function

Setting the ScriptableMethod AttributeNow that each Silverlight control is registered, you need to set the ScriptableMethod attribute on themethods that you want to make callable by other controls or other instances of this control. For example,in this case, you can add the code in Listing 7-30 to update the slider value.

Listing 7-30: Set attribute to make method available to other Silverlight controls

C#[ScriptableMember]public void SetRatingValue(int value){

if (value > 5) value = 5;if (value < 0) value = 1;

236

Fox c07.tex V3 - 01/30/2009 3:26pm Page 237

Chapter 7: Data Connectivity

RatingSlider.Value = value;}

VB<ScriptableMember()> _

Public Sub SetRatingValue(ByVal value As Integer)If value > 5 Then

value = 5End IfIf value < 0 Then

value = 1End If

RatingSlider.Value = valueEnd Sub

Each time that the slider control is updated, you will iterate over all of the registered Silverlight con-trols and call the SetRatingValue method, passing the new slider value. Add the method in Listing 7-31to your class. The first thing you do is retrieve the list of registered Silverlight controls. Next, iterateover the controls skipping the current instance of this control. Next, get a reference to the Silverlightplug-in control using the registered property value. Once you have a reference to the plug-in, get a refer-ence to the Content property. The Content property is a ScriptObject. To get a reference to the actualprogrammable instance, get the ScriptObject property from the Content object. The ScriptObjectproperty name will be the same name you registered in Listing 7-30.

Listing 7-31: Update the rating value on all of the other Silverlight controls

C#private void UpdateTheOtherControl(int value){

List<string> SLRatingControls = GetSLRatingsControlsList();

//iterate through all of the controls updating the Rating valueforeach (string SLCtrl in SLRatingControls){

//skip ourselfif (SLCtrl != HtmlPage.Plugin.Id){

HtmlElement SLControl =(HtmlElement)HtmlPage.Document.GetElementById(SLCtrl);ScriptObject Content =

(ScriptObject)SLControl.GetProperty("Content");ScriptObject otherControl =(ScriptObject)Content.GetProperty(ScriptObjectName);

otherControl.Invoke("SetRatingValue", value);}

}

}

VBPrivate Sub UpdateTheOtherControl(ByVal value As Integer)

Continued

237

Fox c07.tex V3 - 01/30/2009 3:26pm Page 238

Chapter 7: Data Connectivity

Listing 7-31: Update the rating value on all of the other Silverlight controls (continued)

Dim SLRatingControls As List(Of String) = GetSLRatingsControlsList()

‘iterate through all of the controls updating the Rating valueFor Each SLCtrl As String In SLRatingControls

‘skip ourselfIf SLCtrl <> HtmlPage.Plugin.Id Then

Dim SLControl As HtmlElement =DirectCast(HtmlPage.Document.

GetElementById(SLCtrl), HtmlElement)Dim Content As ScriptObject =

DirectCast(SLControl.GetProperty("Content"),ScriptObject)

Dim otherControl As ScriptObject =DirectCast(Content.GetProperty(ScriptObjectName),

ScriptObject)

otherControl.Invoke("SetRatingValue", value)End If

Next

End Sub

Figure 7-11

238

Fox c07.tex V3 - 01/30/2009 3:26pm Page 239

Chapter 7: Data Connectivity

Now when you open the SharePoint site and add two or three of these Web Parts to the site, you willsee that they all automatically update each other to stay in sync. Figure 7-11 shows an example of thisin action. In this example, we have added four instances of the Web Part, and they all stay in sync evenacross Web Part Zones.

Listing 7-32 is the complete listing for the BrowseMode.xaml.cs file that was used for most of the samplesin this chapter.

Listing 7-32: Complete BrowseMode class used for most of the examples in thischapter

C#using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;

using System.Windows.Browser;using System.Xml.Linq;

namespace SilverlightControl{

[ScriptableType]public partial class BrowseMode : UserControl{

//bool IsPrimary = false;

public BrowseMode(){

InitializeComponent();

//Control to Control communicationRegisterSLControl();

RatingSlider.ValueChanged += newRoutedPropertyChangedEventHandler<double>(

RatingSlider_ValueChanged);//Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value =

(int)int.Parse(App.RatingControl.GetAttribute("value"));

//Update the Slider Text value from the XML Data IslandUpdateSliderTextValue();UpdateSliderValue();

Continued

239

Fox c07.tex V3 - 01/30/2009 3:26pm Page 240

Chapter 7: Data Connectivity

Listing 7-32: Complete BrowseMode class used for most of the examples in thischapter (continued)

StopColor.Color = ColorFromString(GetCookie("BGColor"));

}

private static string GetCookie(string CookieName){

//return a ; delimeted string or Key and value pairsstring CookiesString = (string)HtmlPage.Document.Cookies;//Convert to arraystring[] CookiesArray = (string[])CookiesString.Split(’;’);//Convert Array to DictionaryDictionary<string, string> CookiesDictionary =

CookiesArray.ToDictionary(x => x.Split(’=’)[0], x => x.Split(’=’)[1]);

if(CookiesDictionary.ContainsKey(CookieName))return CookiesDictionary[CookieName];

elsethrow new System.Collections.Generic.KeyNotFoundException(

"The Cookie does not exist");}

void RatingSlider_ValueChanged(object sender,RoutedPropertyChangedEventArgs<double> e){

//When the slider changes update the text and the labelUpdateSliderValue();UpdateSliderTextValue();

UpdateTheOtherControl((int)RatingSlider.Value);}

private void UpdateSliderTextValue(){

var RatingValue = from item in App.RatingValues.Elements("RATING")where (string)item.Attribute("value").Value ==

RatingSlider.Value.ToString()select (string)item.Value;

//Set the text valueModeLabel.Text = RatingValue.First<String>();

}

private void UpdateSliderValue(){

//Update the LabelRatingLabel.Text = RatingSlider.Value.ToString();//Update the Hidden HTML Control Valueif (App.RatingControl != null){

App.RatingControl.SetAttribute("value",

240

Fox c07.tex V3 - 01/30/2009 3:26pm Page 241

Chapter 7: Data Connectivity

RatingSlider.Value.ToString());}

}

[ScriptableMember]public void SetRatingValue(int value){

if (value > 5) value = 5;if (value < 0) value = 1;

RatingSlider.Value = value;}

//Name of List to hold Control IDsstring SLRatingControlsPropertyName = "SLRatingControls";string ScriptObjectName = "SLRating";

//Register this control with the HTML pageprivate void RegisterSLControl(){

List<string> SLRatingControls = GetSLRatingsControlsList();

//Add the ControlID to the listSLRatingControls.Add(HtmlPage.Plugin.Id);

HtmlPage.RegisterScriptableObject(ScriptObjectName, this);HtmlPage.Window.SetProperty(SLRatingControlsPropertyName,

string.Join(",", SLRatingControls.ToArray()));}

private List<string> GetSLRatingsControlsList(){

List<string> SLRatingControls;

string SLRatingControlsString =(string)HtmlPage.Window.GetProperty(SLRatingControlsPropertyName);

if (SLRatingControlsString == null)SLRatingControls = new List<string>();

else//convert the string back to a listSLRatingControls = new List<string>(

SLRatingControlsString.Split(’,’));

return SLRatingControls;}

private void UpdateTheOtherControl(int value){

List<string> SLRatingControls = GetSLRatingsControlsList();

//iterate through all of the controls updating the Rating valueforeach (string SLCtrl in SLRatingControls){

Continued

241

Fox c07.tex V3 - 01/30/2009 3:26pm Page 242

Chapter 7: Data Connectivity

Listing 7-32: Complete BrowseMode class used for most of the examples in thischapter (continued)

//skip ourselfif (SLCtrl != HtmlPage.Plugin.Id){

HtmlElement SLControl = (HtmlElement)HtmlPage.Document.GetElementById(SLCtrl);

ScriptObject Content = (ScriptObject)SLControl.GetProperty("Content");ScriptObject otherControl =

(ScriptObject)Content.GetProperty(ScriptObjectName);

otherControl.Invoke("SetRatingValue", value);}

}

}

public Color ColorFromString(string colorString){

//Assumes format "#FFFF0000"byte alpha, red, green, blue;int StartIndex = 1; //skip the #string value;

value = colorString.Substring(StartIndex, 2);alpha = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);red = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);green = Convert.ToByte(value, 16);

value = colorString.Substring(StartIndex += 2, 2);blue = Convert.ToByte(value, 16);

return Color.FromArgb(alpha, red, green, blue);}

}}

VBImports System.Windows.BrowserImports System.Xml.Linq

Partial Public Class BrowseModeInherits UserControl

Public Sub New()InitializeComponent()

242

Fox c07.tex V3 - 01/30/2009 3:26pm Page 243

Chapter 7: Data Connectivity

‘Control to Control communicationRegisterSLControl()

AddHandler RatingSlider.ValueChanged, AddressOf RatingSlider_ValueChanged‘Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value = CInt(Integer.Parse(App.RatingControl.

GetAttribute("value")))

‘Update the Slider Text value from the XML Data IslandUpdateSliderTextValue()UpdateSliderValue()

StopColor.Color = ColorFromString(GetCookie("BGColor"))

‘Update the Slider from the Hidden HTMl Control ValueRatingSlider.Value = DirectCast(Integer.Parse(App.RatingControl.

GetAttribute("value")), Integer)End Sub

Private Shared Function GetCookie(ByVal CookieName As String) As String‘return a ; delimeted string or Key and value pairsDim CookiesString As String = DirectCast(HtmlPage.Document.Cookies, String)‘Convert to arrayDim CookiesArray As String() =

DirectCast(CookiesString.Split(";"c), String())‘Convert Array to DictionaryDim CookiesDictionary As Dictionary(Of String, String) = _CookiesArray.ToDictionary(Function(x As String) x.Split("=")(0), _

Function(x As String) x.Split("=")(1))

If CookiesDictionary.ContainsKey(CookieName) ThenReturn CookiesDictionary(CookieName)

ElseThrow New System.Collections.Generic.KeyNotFoundException(

"The Cookie does not exist")End If

End Function

Sub RatingSlider_ValueChanged(ByVal sender As Object,ByVal e As RoutedPropertyChangedEventArgs(Of Double))

‘When the slider changes update the text and the labelUpdateSliderValue()UpdateSliderTextValue()

UpdateTheOtherControl(CInt(RatingSlider.Value))

End Sub

Private Sub UpdateSliderTextValue()Dim RatingValue = From item In App.RatingValues.Elements("RATING") _Where DirectCast(

item.Attribute("value").Value, String) =RatingSlider.Value.ToString() _

Continued

243

Fox c07.tex V3 - 01/30/2009 3:26pm Page 244

Chapter 7: Data Connectivity

Listing 7-32: Complete BrowseMode class used for most of the examples in thischapter (continued)

Select DirectCast(item.Value, String)

‘Set the text valueModeLabel.Text = RatingValue.First

End Sub

Private Sub UpdateSliderValue()‘Update the LabelRatingLabel.Text = RatingSlider.Value.ToString()‘Update the Hidden HTML Control ValueIf App.RatingControl IsNot Nothing Then

App.RatingControl.SetAttribute("value", RatingSlider.Value.ToString())End If

End Sub

<ScriptableMember()> _Public Sub SetRatingValue(ByVal value As Integer)

If value > 5 Thenvalue = 5

End IfIf value < 0 Then

value = 1End If

RatingSlider.Value = valueEnd Sub

‘Name of List to hold Control IDsPrivate SLRatingControlsPropertyName As String = "SLRatingControls"Private ScriptObjectName As String = "SLRating"

‘Register this control with the HTML pagePrivate Sub RegisterSLControl()

Dim SLRatingControls As List(Of String) = GetSLRatingsControlsList()

‘Add the ControlID to the listSLRatingControls.Add(HtmlPage.Plugin.Id)

HtmlPage.RegisterScriptableObject(ScriptObjectName, Me)HtmlPage.Window.SetProperty(

SLRatingControlsPropertyName, String.Join(",",SLRatingControls.ToArray()))

End Sub

Private Function GetSLRatingsControlsList() As List(Of String)Dim SLRatingControls As List(Of String)

Dim SLRatingControlsString As String =

244

Fox c07.tex V3 - 01/30/2009 3:26pm Page 245

Chapter 7: Data Connectivity

DirectCast(HtmlPage.Window.GetProperty(SLRatingControlsPropertyName), String)

If SLRatingControlsString Is Nothing ThenSLRatingControls = New List(Of String)()

Else‘convert the string back to a listSLRatingControls = New List(Of String)(SLRatingControlsString.Split(","c))

End If

Return SLRatingControlsEnd Function

Private Sub UpdateTheOtherControl(ByVal value As Integer)Dim SLRatingControls As List(Of String) = GetSLRatingsControlsList()

‘iterate through all of the controls updating the Rating valueFor Each SLCtrl As String In SLRatingControls

‘skip ourselfIf SLCtrl <> HtmlPage.Plugin.Id Then

Dim SLControl As HtmlElement = DirectCast(HtmlPage.Document.GetElementById(SLCtrl), HtmlElement)

Dim Content As ScriptObject = DirectCast(SLControl.GetProperty("Content"), ScriptObject)

Dim otherControl As ScriptObject = DirectCast(Content.GetProperty(ScriptObjectName), ScriptObject)

otherControl.Invoke("SetRatingValue", value)End If

Next

End Sub

Public Function ColorFromString(ByVal colorString As String) As Color‘Assumes format "#FFFF0000"Dim alpha As ByteDim red As ByteDim green As ByteDim blue As Byte‘skip the #Dim StartIndex As Integer = 1

Dim colorValue As String = ""

colorValue = colorString.Substring(StartIndex, 2)alpha = Convert.ToByte(colorValue, 16)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)red = Convert.ToByte(colorValue, 16)

Continued

245

Fox c07.tex V3 - 01/30/2009 3:26pm Page 246

Chapter 7: Data Connectivity

Listing 7-32: Complete BrowseMode class used for most of the examples in thischapter (continued)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)green = Convert.ToByte(colorValue, 16)

StartIndex = StartIndex + 2colorValue = colorString.Substring(StartIndex, 2)blue = Convert.ToByte(colorValue, 16)

Return Color.FromArgb(alpha, red, green, blue)End Function

End Class

SummaryIn this chapter, you saw various techniques to display data in Silverlight from SharePoint and othersources. Silverlight is very powerful and flexible. This flexibility means that you have many differ-ent ways to achieve the same goal. You saw that you could use the InitParameters, HiddenFields,cookies, and XML Data Islands to push data into the Silverlight application. Each method has pros andcons depending on your specific scenario. You saw how easy it is to data-bind Silverlight controls toSharePoint Web Services using LINQ for XML. And finally, you learned that you can create powerfulcomposite applications using Silverlight-to-Silverlight communications.

All of these techniques used together make Silverlight and SharePoint a great platform for creatingline-of-business applications that provide a rich user experience coupled with a powerful server model.

246

Fox c08.tex V3 - 01/30/2009 5:06pm Page 247

Bringing It All Together

Throughout this book, we have discussed many different topics regarding SharePoint and Sil-verlight. For example, in Chapter 2, you saw how to create a simple Silverlight application andthen integrate that application with a Web Part. You then learned many different ways to integrateSilverlight applications with SharePoint. For example, the different ways of integrating with WebParts was discussed in Chapters 5 and 6; you saw how to build custom field types in Chapter 3; youwalked through Web Part connectivity and data-binding in Chapter 7; and you saw how to brandand customize your SharePoint site using Silverlight in Chapter 4. With all that behind you, thisbrings you to the final chapter.

In this chapter, we will discuss (as opposed to presenting a how-to walk-through) a sample appli-cation that brings together some of what you have learned in this book. This was, first, to avoidrepetition and, second, to include other design advice and options as you work through each partof the sample application. Hopefully, this approach will spawn some ideas of what you can do withSilverlight and SharePoint in your own environment. As was mentioned earlier in the book, youcan have multiple levels of integration between the two technologies. For example, lighter integra-tions include embedding Silverlight Streaming media into your SharePoint site or using the Con-tent Editor Web Part, whereas heavier-weight integrations might integrate more deeply with theSharePoint object model. And all told, you could effectively use the Silverlight solutions thatyou stitch together (or just use one main application hosted by SharePoint) to represent the totaluser experience for SharePoint. This is certainly feasible and an option that not only draws on thestrength of the SharePoint infrastructure, but also re-designs the user experience with SharePoint.

That said, the sample application you’ll build in this chapter will represent a simple IT training man-agement application built for a fictional company called Contoso Pharmaceuticals, who want to trackthe training offerings to ensure that their IT department is trained on all of the latest technologies.The core application will be composed of four main parts:

❑ SharePoint Training list to track the different offerings

❑ User entry form to enter in training data (using the Training list as a back-end data source)

Fox c08.tex V3 - 01/30/2009 5:06pm Page 248

Chapter 8: Bringing It All Together

❑ Charting capabilities to graph the number of offerings completed

❑ Silverlight control view of the Training list

We will keep the architecture simple not only to keep the chapter manageable, but also to ensure thatyou learn some of the core design principles that have been incorporated within the application. At ahigh level, Figure 8-1 represents the main pieces of the application and how they will fit together. Notethat for the most part, you’ll be pushing data from the data-entry form to the Training list and from thereupdating the reporting control and list control using services.

Training DataUser Entry Form

Training ListRe-skinnedTraining List

TrainingChart

Figure 8-1

By the end of the chapter, you’ll have learned entering and managing data, re-skinning a SharePointlist to be more presentable, building charting and reporting controls to display data, and finally, allof this within a services-oriented approach. The key takeaway from this chapter should be for you tounderstand how you could extend this type of simple application to apply your own integrations withSharePoint — be it with a list or with other SharePoint services or objects.

This chapter has been structured to discuss:

❑ The Elements of the Training List — Since all things pretty much arrive and depart from thislist, we wanted to make sure that this is discussed up front.

❑ The Services Layer of the Application — This will touch on both the charting and re-skinningcapabilities mentioned above.

❑ The Presentation Layer — This includes the Training data-entry form, the charting capabilities,and the re-skinned list.

❑ Extensibility — Some of the extensibility you might build into such an application, for example,custom navigation or extended controls

The Training ListThe training list is essentially a list that provides key information for your sample application, an appli-cation that tracks the core developer training offerings in an IT department within a fictional companycalled Contoso Pharmaceuticals, information about those offerings, and who in the IT department has

248

Fox c08.tex V3 - 01/30/2009 5:06pm Page 249

Chapter 8: Bringing It All Together

signed up for the training and completed the training. At the end of the day, the offerings are some-what immaterial; it’s the way in which the Silverlight applications integrate with SharePoint that you’llwant to focus on. For example, Figure 8-2 provides a screenshot of the Training list we created for thisapplication. You’ll note that there are several key data types included within this list:

❑ Name of the training

❑ Description of the training

❑ Core Technology for the training

❑ Student name

❑ Student contact information

❑ Training offering level of difficulty

❑ Training completed

❑ Training ID

You can consider each entry of the above list as a training offering record in the list. Figure 8-2 shows thelist within the Contoso site.

Figure 8-2

249

Fox c08.tex V3 - 01/30/2009 5:06pm Page 250

Chapter 8: Bringing It All Together

As you’ll see a little later on in this chapter, the way in which you’re interacting with this list is byenabling a user to interact with a user data-entry form, which subsequently creates a business objectand pushes data to a custom Web Service for inserting a record into the SharePoint list.

While we opted to go for using native field types for our Training list for editing directly in SharePoint,as you saw in Chapter 3, you could also create a Silverlight-enabled data-entry mechanism directly fromSharePoint. Figure 8-3 provides a screenshot of data entry directly from the SharePoint site — should auser click New from the list and then enter the field — essentially the alternative to our data-entry form.

For design simplicity, all of the items within a particular record were defined as strings — this made iteasier to push the payload across the service calls. That said, while each of the items within SharePointwas a native field type, they were not all of the same field type. The following table is a listing of thedifferent field types used:

Field Field Type

Name of the training Single line of text

Description of the training Multiple lines of text

Core Technology for the training Choice

Student name Single line of text

Student contact information Multiple lines of text

Training offering level of difficulty Choice

Training completed Yes/No

Training ID Choice

At this point, that’s probably enough information for the Training list. We’ll discuss specific businessobjects and variables in the context of the user data-entry form and services later in the chapter, so let’snow move on to discussing the Web Service.

ServiceThe service you build to integrate with your SharePoint site can take on a couple of flavors. Forexample, you could build a Windows Communication Foundation (WCF) Service or an ASP.NETWeb Service. Either works similarly in the way in which they can integrate with SharePoint — forexample, setting or getting data; however, each of these options has different deployment methods.In Chapter 3, you used the ASP.NET Web Service and had to follow a number of steps to deploy itcorrectly to the SharePoint server. Using the WCF Service is a little different — you need to createa different project (‘‘WCF Service’’); define your methods, operations, and contracts; and publishyour service. You wouldn’t, though, publish it to the _layouts folder, for example; rather, you’dpublish it to its own web application domain. This section of the chapter discusses the syntax of theweb methods within the service both in the context of WCF and ASP.NET Web Services. We willdiscuss WCF Services at a high level in this chapter, but won’t go into great detail on deploymentof WCF Services. For in-depth information on WCF, we recommend taking a look at the following

250

Fox c08.tex V3 - 01/30/2009 5:06pm Page 251

Chapter 8: Bringing It All Together

resource: http://msdn.microsoft.com/en-us/library/ms735119.aspx. You can also look athttp://mssharepointdeveloper.com, where you’ll find more information on specifically using WCFwith Silverlight and SharePoint.

Figure 8-3

The service that we used for this chapter contains three web methods:

❑ The first method gets information from the Training list that you can use to create a graph of thedifferent training offerings.

❑ The second method updates the SharePoint Training list with data entered into a data-entryform.

❑ The third method grabs all of the data from the list, which enables us to map the data to aSilverlight list control.

Irrespective of whether you use WCF or ASP.NET Web Services to implement the service calls, the coreweb method syntax will be similar across the two. This section discusses the core web method syntaxand provides some notes on the differences on implementation if you were to use WCF versus ASP.NETWeb Services.

251

Fox c08.tex V3 - 01/30/2009 5:06pm Page 252

Chapter 8: Bringing It All Together

Using getListIDInfoThe first web method, called getListIDInfo, simply makes a request to the Training list, gets all of thefield items in the Training ID column, and returns an array of Training IDs. In the calling code, you’llthen use some logic to calculate the number of specific offerings — because each ID could be thought ofas a unique instance or occurrence for the training. In Listing 8-1, notice that the array is hard-coded tohave five elements; you iterate through the items in the SharePoint list, adding each item to the array. TheVB version is the same call. When you implement your own code, you’ll likely want to make your arraysmore dynamic — for example, having a method in your service that gets the count within the SharePointlist and then uses that number as the upper ceiling in your array.

To successfully make this call into SharePoint, you’ll need to make sure you add a reference to theMicrosoft.SharePoint DLL to your project. The returned array will then be used to create data (specificallya set of name/value pairs) that can be bound to a Silverlight control.

Listing 8-1: getListIDInfo web method

C#[WebMethod]public string[] getListIDInfo(string listName){

string trnIDField = "";string[] sales = new string[5];

using (SPSite mySPSite = new SPSite("http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

string SPListName = listName;

SPListItemCollection listItems = mySPWeb.Lists[SPListName].Items;

for (int i = 0; i < listItems.Count; i++){

SPListItem item = listItems[i];trnIDField = item["Training ID"].ToString();sales[i] = trnIDField;

}}return sales;

}}

VB<WebMethod()> _Public Function getListIDInfo(listName As String) As String()

Dim trnIDField As String = ""Dim sales As String() = New String(4) {}

Using mySPSite As New SPSite("http://stefoxdemo")

252

Fox c08.tex V3 - 01/30/2009 5:06pm Page 253

Chapter 8: Bringing It All Together

Using mySPWeb As SPWeb = mySPSite.OpenWeb()Dim SPListName As String = listName

Dim listItems As SPListItemCollection = _mySPWeb.Lists(SPListName).Items

For i As Integer = 0 To listItems.Count - 1Dim item As SPListItem = listItems(i)trnIDField = item("Training ID").ToString()sales(i) = trnIDField

NextEnd UsingReturn sales

End UsingEnd Function

Using updateListThe second method in the service, updateList, takes several string variables, which are then used toupdate the Training list. This service is the main service used by the user data-entry form, a Silverlightcontrol that can be used to enter data to the list. Similar to the first web method, the updateList methodcreates an instance of the SharePoint web and sets a string variable to Training, which represents thename of the list. You iterate through the lists to find the right match and then set that to the currentlist. You then create an instance of the ListItem object, to which you can add the data that has beenpassed to the method from your calling object by calling the Update method. There is no return value forthis particular method, but in production code, you would likely want to return a value that representswhether the items have indeed been updated — for example, a Boolean value that is set when the list hasbeen updated. Listing 8-2 shows this code.

Listing 8-2: updateList method

C#[WebMethod]

public void updateList(string trnName,string trnDescr,string coreTech,string studentName,string studentInfo,string trnLevel,string trnCompleted,string trnID){

using (SPSite mySPSite = new SPSite("http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

mySPWeb.AllowUnsafeUpdates = true;string SPListName = "Training";SPList SPList = null;foreach (SPList currentSPList in mySPWeb.Lists){

Continued

253

Fox c08.tex V3 - 01/30/2009 5:06pm Page 254

Chapter 8: Bringing It All Together

Listing 8-2: updateList method (continued)

if (currentSPList.Title.Equals(SPListName,StringComparison.InvariantCultureIgnoreCase))

{SPList = currentSPList;break;

}}SPListItem newSPListItem = SPList.Items.Add();newSPListItem["Training Offering"] = trnName;newSPListItem["Training Description"] = trnDescr;newSPListItem["Core Technology"] = coreTech;newSPListItem["Student Name"] = studentName;newSPListItem["Student Contact Info"] = studentInfo;newSPListItem["Offering Level"] = trnLevel;newSPListItem["Offering Completed"] = trnCompleted;newSPListItem["Training ID"] = trnID;newSPListItem.Update();

}}

}

VB<WebMethod()>

Public Sub updateList(trnName As String, trnDescr As String, coreTechAs String, studentName As String, studentInfo As String, trnLevel AsString, trnCompleted As String, trnID As String)

Using mySPSite As New SPSite("http://stefoxdemo")

Using mySPWeb As SPWeb = mySPSite.OpenWeb()mySPWeb.AllowUnsafeUpdates = TrueDim SPListName As String = "Training"Dim SPList As SPList = NothingFor Each currentSPList As SPList In _ mySPWeb.Lists

If currentSPList.Title.Equals(SPListName,StringComparison.InvariantCultureIgnoreCase) Then

SPList = currentSPListExit For

End IfNextDim newSPListItem As SPListItem = SPList.Items.Add()newSPListItem("Training Offering") = trnNamenewSPListItem("Training Description") = trnDescrnewSPListItem("Core Technology") = coreTechnewSPListItem("Student Name") = studentNamenewSPListItem("Student Contact Info") = studentInfonewSPListItem("Offering Level") = trnLevelnewSPListItem("Offering Completed") = trnCompletednewSPListItem("Training ID") = trnIDnewSPListItem.Update()

End UsingEnd Using

End Sub

254

Fox c08.tex V3 - 01/30/2009 5:06pm Page 255

Chapter 8: Bringing It All Together

Using getTrainingListDataThe third and final web method, called getTrainingListData, gets all of the data in the Training listand passes the data back to the calling object. In this method, you’ll see similar code when creating theinstance of the SharePoint site using the SPSite object; however, in this sample code, you’re also using alist collection of objects (the FieldCollection object mirrors the structure of the Training list) that you’llpass across the service call. Listing 8-3 shows the code for the object definition.

Listing 8-3: FieldCollection object

C#public class FieldCollection{

public string listField { get; set; }public string nameField { get; set; }public string descrField { get; set; }public string coreTechField { get; set; }public string studentNameField { get; set; }public string studentInfoField { get; set; }public string trnLevelField { get; set; }public string trnCompletedField { get; set; }public string trnIDField { get; set; }

public FieldCollection(){

}}

VBPublic Class FieldCollection

Public Property listField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property nameField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property descrField() As String

GetEnd GetSetEnd Set

End Property

Continued

255

Fox c08.tex V3 - 01/30/2009 5:06pm Page 256

Chapter 8: Bringing It All Together

Listing 8-3: FieldCollection object (continued)

Public Property coreTechField() As StringGetEnd GetSetEnd Set

End PropertyPublic Property studentNameField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property studentInfoField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property trnLevelField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property trnCompletedField() As String

GetEnd GetSetEnd Set

End PropertyPublic Property trnIDField() As String

GetEnd GetSetEnd Set

End Property

Public Sub New()End Sub

End Class

Populating the List CollectionTo populate the list collection of objects, you first create instances of string variables and set them to null;these variables represent the individual items in the SharePoint list. You then create an instance of theFieldCollection object and a list collection of the FieldCollection objects. You then iterate throughthe list and retrieve each item in the list. For each record in the SharePoint list, you then add each recordas an element in the list collection of FieldCollection objects. Listing 8-4 shows this code.

256

Fox c08.tex V3 - 01/30/2009 5:06pm Page 257

Chapter 8: Bringing It All Together

Listing 8-4: getTrainingListData method

C#[WebMethod]public List<FieldCollection> getTrainingListData(){

string nameField = "";string descrField = "";string coreTechField = "";string studentNameField = "";string studentInfoField = "";string trnLevelField = "";string trnCompletedField = "";string trnIDField = "";

FieldCollection fieldCllctn = new FieldCollection();List<FieldCollection> data = new List<FieldCollection>();

using (SPSite mySPSite = new SPSite("http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

string SPListName = "Training";

SPListItemCollection listItems =mySPWeb.Lists[SPListName].Items;

for (int i = 0; i < listItems.Count; i++){

SPListItem item = listItems[i];

nameField = item["Training Offering"].ToString();descrField = item["Training Description"].ToString();coreTechField = item["Core Technology"].ToString();studentNameField = item["Student Name"].ToString();studentInfoField = item["Student Contact Info"].ToString();trnLevelField = item["Offering Level"].ToString();trnCompletedField = item["Offering Completed"].ToString();trnIDField = item["Training ID"].ToString();

fieldCllctn.nameField = nameField;fieldCllctn.descrField = descrField;fieldCllctn.coreTechField = coreTechField;fieldCllctn.studentNameField = studentNameField;fieldCllctn.studentInfoField = studentInfoField;fieldCllctn.trnLevelField = trnLevelField;fieldCllctn.trnCompletedField = trnCompletedField;fieldCllctn.trnIDField = trnIDField;

Continued

257

Fox c08.tex V3 - 01/30/2009 5:06pm Page 258

Chapter 8: Bringing It All Together

Listing 8-4: getTrainingListData method (continued)

data.Add(fieldCllctn);}

}}

return data;}

}

VB<WebMethod> _Public Function getTrainingListData() As List(Of FieldCollection)

Dim nameField As String = ""Dim descrField As String = ""Dim coreTechField As String = ""Dim studentNameField As String = ""Dim studentInfoField As String = ""Dim trnLevelField As String = ""Dim trnCompletedField As String = ""Dim trnIDField As String = ""

Dim fieldCllctn As New FieldCollection()Dim data As List(Of FieldCollection) = New List(Of FieldCollection)()

Using mySPSite As New SPSite("http://stefoxdemo")Using mySPWeb As SPWeb = mySPSite.OpenWeb()

Dim SPListName As String = "Training"

Dim listItems As SPListItemCollection =mySPWeb.Lists(SPListName).Items

For i As Integer = 0 To listItems.Count - 1Dim item As SPListItem = listItems(i)

nameField = item("Training Offering").ToString()descrField = item("Training Description").ToString()coreTechField = item("Core Technology").ToString()studentNameField = item("Student Name").ToString()studentInfoField = item("Student Contact

Info").ToString()trnLevelField = item("Offering Level").ToString()trnCompletedField = item("Offering

Completed").ToString()trnIDField = item("Training ID").ToString()

fieldCllctn.nameField = nameFieldfieldCllctn.descrField = descrFieldfieldCllctn.coreTechField = coreTechFieldfieldCllctn.studentNameField = studentNameFieldfieldCllctn.studentInfoField = studentInfoFieldfieldCllctn.trnLevelField = trnLevelField

258

Fox c08.tex V3 - 01/30/2009 5:06pm Page 259

Chapter 8: Bringing It All Together

fieldCllctn.trnCompletedField = trnCompletedFieldfieldCllctn.trnIDField = trnIDFielddata.Add(fieldCllctn)

Next i

End UsingEnd Using

Return dataEnd Function

Note that in this service you’re using a complex type as the payload in the web method. This meansthat you’ll need to serialize the object into an XML document, which can, in turn, be deserialized backinto an object from the calling method. For example, when the getTrainingList method is run againstthe Training list, the result is an XML document that is passed back to the calling method, which con-tains essentially what represents an array of the FieldCollection objects expressed as XML. Listing 8-5provides an example of one of the XML FieldCollection nodes in the serialized object.

Listing 8-5: getTrainingList payload

<ArrayOfFieldCollection><FieldCollection>

<nameField>Intro to Visual Studio 2008</nameField><descrField>This training provides an introduction on how to use

Visual Studio 2008.</descrField><coreTechField>Visual Studio</coreTechField><studentNameField>Mike Fitzmaurice</studentNameField><studentInfoField>[email protected]</studentInfoField><trnLevelField>100 (Intro)</trnLevelField><trnCompletedField>True</trnCompletedField><trnIDField>2</trnIDField></FieldCollection>

<FieldCollection>. . .

</ArrayOfFieldCollection>

With the knowledge of the object structure, you can create a method that deserializes the payload andre-creates the object from the side of the calling method. After you deserialize the data from the Traininglist, it is now on the side of the calling method, so you can safely use the data and bind it to a Silverlightcontrol, which is discussed a little later on in the chapter.

What about WCF?If you were to use WCF to implement these web methods, you would have to do several things dif-ferently from using ASMX services. As was mentioned earlier, you first need to make sure that youcreate a separate web application in IIS and then deploy your service to that location. You’ll wantto read up on how this is done before you try it if you’ve never done this before. For more informa-tion, see http://msdn.microsoft.com/en-us/library/ms735119.aspx. While deployment of the ser-vice is a little different from that covered in Chapter 3, the syntax of the web methods differs onlyslightly — although there are additional requirements for WCF services in the way of having contractsfor your web methods and data types. You also have additional configuration options for your service

259

Fox c08.tex V3 - 01/30/2009 5:06pm Page 260

Chapter 8: Bringing It All Together

within WCF. The aforementioned link should provide you with a good starting point for the deploymentand configuration of web methods, so let’s focus on the minor syntactical differences across the code inthe above three web methods.

Using Service ContractFor the most part, the syntax would be the same for the three web methods, but it would not havethe [WebMethod] declaration before it in the service class. Furthermore, you would need to define anOperationContract for the method in the IService interface — a default interface that is created whenyou create the WCF Service. Note that in the service contract, there are no modifiers added to the methoddeclaration. The code sample in Listing 8-6 provides an overview of the service contract within the WCFversion of our service.

Note that in this code sample, the three methods are listed, essentially declared as operation contracts,and we include the parameters that are required for the web methods in these operational declarations.

Listing 8-6: Service contract for getListIDInfo

C#[ServiceContract]

public interface IService{

[OperationContract]string[] getListIDInfo(string listName);

[OperationContract]void updateList(string trnName,string trnDescr,string coreTech,string studentName,string studentInfo,string trnLevel,string trnCompleted,string trnID);

[OperationContract]List<FieldCollection> getTrainingListData();

}

VB<ServiceContract()>Public Interface IService

<OperationContract()>Function getListIDInfo(listName As String) As String()

<OperationContract()>Sub updateList(trnName As String, trnDescr As String, coreTechAs

String, studentName As String, studentInfo As String, trnLevel As

260

Fox c08.tex V3 - 01/30/2009 5:06pm Page 261

Chapter 8: Bringing It All Together

String, trnCompleted As String, trnID As String)

<OperationContract()>Function getTrainingListData() As List(Of FieldCollection)

End Interface

Using the Web Method in WCFIn WCF, the core web methods live in a Service class (named Service by default), which derives fromthe IService interface — discussed above. Again, the syntax is not different from the core methods; theonly difference here is the fact that there is no [WebMethod] before the method. Listing 8-7 provides anoverview of our web method; this time in the WCF service.

Listing 8-7: Web method in WCF

C#public class Service : IService{

public string[] getListIDInfo(string listName){

string trnIDField = "";string[] sales = new string[3];

using (SPSite mySPSite = new SPSite("http://stefoxdemo")){

using (SPWeb mySPWeb = mySPSite.OpenWeb()){

string SPListName = listName;

SPListItemCollection listItems = mySPWeb.Lists[SPListName].Items;

for (int i = 0; i < listItems.Count; i++){

SPListItem item = listItems[i];trnIDField = item["Training ID"].ToString();sales[i] = trnIDField;

}}return sales;

}}

. . .

}

VBPublic Class Service

Continued

261

Fox c08.tex V3 - 01/30/2009 5:06pm Page 262

Chapter 8: Bringing It All Together

Listing 8-7: Web method in WCF (continued)

Implements IService

Public Function getListIDInfo(listName As String) As String()

Dim trnIDField As String = ""Dim sales As String() = New String(2) {}

Using mySPSite As New SPSite("http://stefoxdemo")Using mySPWeb As SPWeb = mySPSite.OpenWeb()

Dim SPListName As String = listName

Dim listItems AsSPListItemCollection = mySPWeb.Lists(SPListName).Items

For i As Integer = 0 To listItems.Count - 1Dim item As SPListItem = listItems(i)trnIDField = item("Training ID").ToString()

sales(i) = trnIDFieldNext

End UsingReturn sales

End UsingEnd Function. . .

End Class

Using a Client Access Policy FileIf you use WCF when building your own custom services against SharePoint, you’ll need to remember tocreate a separate IIS application, publish your WCF service to that domain, and then add a client accesspolicy file at the root of your SharePoint folder hierarchy. Listing 8-8 is a code sample that illustrates aclient access policy file; one that provides access to all domain URIs.

Listing 8-8: Client access policy file

<?xml version="1.0" encoding="utf-8"?><access-policy>

<cross-domain-access><policy>

<allow-from http-request-headers="*"><domain uri="*"/>

</allow-from><grant-to><resource path="/" include-subpaths="true"/>

</grant-to></policy>

</cross-domain-access></access-policy>

If you’d like to walk through some hands-on labs to help you understand this better, you can find gooddeveloper content in this area on http://mssharepointdeveloper.com.

262

Fox c08.tex V3 - 01/30/2009 5:06pm Page 263

Chapter 8: Bringing It All Together

At this point, you should have a good understanding of the web methods within the service. As men-tioned earlier, we recommend doing some research on how to implement your service when comparingASP.NET services versus WCF. There are pros and cons to either, and ultimately you are the ownerof the design of your production code. Let’s now talk about the data-entry component of our simpleapplication.

Data EntryYou’ve seen within this book the use of Silverlight to manage media; in fact, you’ve probably seen thisa lot in the real-world application of Silverlight. However, media playback is only one of the strengthsof Silverlight. Another core strength of Silverlight is the fact that you can build many different types ofbusiness applications; furthermore, ones that can accept user input, connect to existing services, store datawithin SharePoint (or outside in another database if need be), enhance the user experience, and much,much more. If you apply this to SharePoint, you’ll see that you can really enhance the ways in whichpeople interact with SharePoint as a business tool by creating and deploying rich applications usingSilverlight. This section discusses the simple data-entry form that we created for the sample trainingapplication. The sample application we built enables a user to load specific training offerings, then add aname and e-mail address to the user data-entry form, and finally, add that to the SharePoint list.Figure 8-4 provides a view of the data-entry project in Visual Studio.

Figure 8-4

263

Fox c08.tex V3 - 01/30/2009 5:06pm Page 264

Chapter 8: Bringing It All Together

The data-entry form is a fairly simple form. It has several controls that are used to display and acceptdata. There is also some gradient added to the form to provide a richer visual effect. This project wascreated similarly to the way you’ve learned throughout this book: You add a Silverlight project to a‘‘Blank Solution,’’ then use the native designer within Visual Studio to create a user entry form as theuser interface, and, finally, add event handlers to manage the events associated with each of the controls.The main event handlers were associated with the checkbox and the two buttons, but there is also someinteractivity with the properties of the other controls on the page as well.

Listing 8-9 provides an overview of the code to create the user data-entry form. Of note within the XAMLcode is the fact that we have added five elements within the combo-box to represent each of the potentialfive choices of training. In our solution, we’ve added these as combo-box items statically within the code;however, you could equally add these as dynamic elements that are read from an external database or listof training offerings. Based on the user’s selection, information about a specific training offering is loadedinto the user form. Furthermore, the user can enter a name and e-mail address into the form. Again, asyou’ve seen throughout the book, we’ve also provided named objects for most of the controls that we’llneed to update in some way based on the user interaction. For example, cmboBoxOfferings is the nameof the combo-box, and you need this name to ensure that you can attach the DropDownClosed event withthat object. Also, there are two buttons that provide the user the ability to re-set the user entries or submitthe data in the form to the SharePoint Training list and a checkbox to indicate whether the student hascompleted the training or not.

Listing 8-9: XAML for user data-entry form

<UserControl x:Class="CustomerEntryForm.Page"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Width="750" Height="380"><Canvas x:Name="LayoutRoot" >

<Canvas Width="750" Height="750"><!-- Canvas fill --><Path Width="475" Height="300" Canvas.Left="38"

Canvas.Top="9" Stretch="Fill"Data="F1 M 42.336,8.86813L 257.336,8.86813C

259.545,8.86813 261.336,10.659 261.336,12.8681L 261.336,77.8681C261.336,80.0773 259.545,81.8681 257.336,81.8681L 42.336,81.8681C40.1269,81.8681 38.336,80.0773 38.336,77.8681L 38.336,12.8681C38.336,10.659 40.1269,8.86813 42.336,8.86813 Z ">

<Path.Fill><LinearGradientBrush StartPoint="0.75,0.7"

EndPoint="0.75,-0.01"><LinearGradientBrush.GradientStops>

<GradientStop Color="Azure" Offset="0"/><GradientStop Color="#FFDCDCDC" Offset="0.8"/><GradientStop Color="#FFC3C3C3" Offset="1"/>

</LinearGradientBrush.GradientStops></LinearGradientBrush>

</Path.Fill></Path>

</Canvas><!-- Header Title Text--><TextBlock

Canvas.Left="50"

264

Fox c08.tex V3 - 01/30/2009 5:06pm Page 265

Chapter 8: Bringing It All Together

Canvas.Top="15"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="18"Text="New Customer Entry Form"Foreground="#FFF3F3F3" />

<TextBlockCanvas.Left="51"Canvas.Top="16"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="18"Text="New Customer Entry Form"Foreground="#FF666666" />

<!-- End Header Title Text-->

<!-- User entry form text and controls.--><TextBlock

Canvas.Left="50"Canvas.Top="50"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Training Offering: "Foreground="#FF666666"/>

<ComboBox x:Name="cmboBoxOfferings"Canvas.Left="190"Canvas.Top="50"Height="20"Width="290"DropDownClosed="cmboBoxOfferings_DropDownClosed">

<ComboBoxItem x:Name="optionOne"><TextBlock x:Name="txtSPDev">

Intro to SharePoint Development</TextBlock>

</ComboBoxItem><ComboBoxItem x:Name="optionTwo">

<TextBlock x:Name="txtVSDev">Intro to Visual Studio 2008

</TextBlock></ComboBoxItem><ComboBoxItem x:Name="OptionThree">

<TextBlock x:Name="txtSQLSRVDev">SQL Server 2008 Deep Dive

</TextBlock></ComboBoxItem><ComboBoxItem x:Name="OptionFour">

<TextBlock x:Name="txtAdvSPDev">Developing Advanced Apps for SharePoint

</TextBlock></ComboBoxItem><ComboBoxItem x:Name="OptionFive">

<TextBlock x:Name="txtClientDev">Intro to Office Client Development

</TextBlock></ComboBoxItem>

Continued

265

Fox c08.tex V3 - 01/30/2009 5:06pm Page 266

Chapter 8: Bringing It All Together

Listing 8-9: XAML for user data-entry form (continued)

</ComboBox>

<TextBlockCanvas.Left="50"Canvas.Top="80"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Training Description: "Foreground="#FF666666" />

<TextBlock x:Name="txtTrainingDescr"Canvas.Left="190"Canvas.Top="80"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Description Here."Foreground="Black"Width="290"TextWrapping="Wrap"/>

<TextBlockCanvas.Left="50"Canvas.Top="110"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Training Level: "Foreground="#FF666666"/>

<TextBlock x:Name="txtTrainingLevel"Canvas.Left="190"Canvas.Top="110"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Level Here."Foreground="Black"Width="290"TextWrapping="Wrap"/>

<TextBlockCanvas.Left="50"Canvas.Top="140"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Core Technology:"Foreground="#FF666666" />

<TextBlock x:Name="txtCoreTechnology"Canvas.Left="190"Canvas.Top="140"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Technology Here."Foreground="Black"Width="290"TextWrapping="Wrap"/>

266

Fox c08.tex V3 - 01/30/2009 5:06pm Page 267

Chapter 8: Bringing It All Together

<TextBlockCanvas.Left="50"Canvas.Top="170"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Student Name:"Foreground="#FF666666" />

<TextBox x:Name="txtBxCustomerName"Canvas.Left="190"Canvas.Top="170"Height="20"Width="175" />

<TextBlockCanvas.Left="50"Canvas.Top="200"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Student Email:"Foreground="#FF666666" />

<TextBox x:Name="txtBxCustomerEmail"Canvas.Left="190"Canvas.Top="200"Height="20"Width="175" />

<TextBlockCanvas.Left="50"Canvas.Top="240"Height="20"Width="175"FontFamily="Trebuchet MS"FontWeight="Bold" FontSize="12"Text="Training Completed:"Foreground="#FF666666"/>

<CheckBox x:Name="chkBxCompleted"Canvas.Left="190"Canvas.Top="235"/>

<Button x:Name="btnClear"Canvas.Left="130"Canvas.Top="275"Height="25"Width="70"Content="Clear"Click="btnClear_Click"/>

<Button x:Name="btnSubmit"Canvas.Left="230"Canvas.Top="275"Height="25"Width="70"

Continued

267

Fox c08.tex V3 - 01/30/2009 5:06pm Page 268

Chapter 8: Bringing It All Together

Listing 8-9: XAML for user data-entry form (continued)

Content="Submit"Click="btnSubmit_Click"/>

<!-- End of user entry form text and controls.--></Canvas>

</UserControl>

The code-behind that corresponds to each of the controls in the user interface provides for some straight-forward user interactions. The code is also a combination of the hard-coded variables we used to repre-sent the five training offerings (as opposed to dynamically loading them from an outside data source).For example, five class-level string variables (shown below in C#) represent the names of each of thetrainings and one additional variable for the Training ID:

C#int trainingID;string trningOfferOne = "Intro to SharePoint Development";string trningOfferTwo = "Intro to Visual Studio 2008";string trningOfferThree = "SQL Server 2008 Deep Dive";string trningOfferFour = "Developing Advanced Apps for SharePoint";string trningOfferFive = "Intro to Office Client Development";

VBDim trainingID As IntegerDim trningOfferOne As String = "Intro to SharePoint Development"Dim trningOfferTwo As String = "Intro to Visual Studio 2008"Dim trningOfferThree As String = "SQL Server 2008 Deep Dive"Dim trningOfferFour As String = "Developing Advanced Apps for SharePoint"Dim trningOfferFive As String = "Intro to Office Client Development"

These class-level variables are used by the combo-box when loading specific training into the user inter-face. When the user interacts with the combo-box, that is, when the combo-box is closed, it calls thecmboBxOfferings_DropDownClosed event, which uses the class-level variables to set other properties inthe combo-box. Again, we have kept this simple to illustrate the interactivity between the UI and thecode-behind and used conditional if statements to check to see if the selected item in the combo-box cor-responds to one of the class-level variables. Depending on which one corresponds to the user selection,specific properties of the UI will be set and displayed as per these mappings. Listing 8-10 displays thissample code.

Listing 8-10: DropDownClosed event

C#namespace CustomerEntryForm{

public partial class Page : UserControl{

. . .

private void cmboBoxOfferings_DropDownClosed(object sender, EventArgs e){

if (txtSPDev.Text == trningOfferOne && optionOne.IsSelected == true){

268

Fox c08.tex V3 - 01/30/2009 5:06pm Page 269

Chapter 8: Bringing It All Together

selectedTrng.trainingID = 1;selectedTrng.trainingDescr = "This training provides an

introduction to SharePoint training.";selectedTrng.trainingLevel = 100;selectedTrng.trainingTech = "SharePoint";resetTxtValues();setUITextProperties(selectedTrng.trainingID,

selectedTrng.trainingDescr, selectedTrng.trainingLevel,selectedTrng.trainingTech);

}

else if (txtAdvSPDev.Text == trningOfferFour &&OptionFour.IsSelected == true)

{

selectedTrng.trainingID = 4;selectedTrng.trainingDescr = "This training teaches how

to develop advanced custom solutions for SharePoint.";selectedTrng.trainingLevel = 400;selectedTrng.trainingTech = "SharePoint";resetTxtValues();setUITextProperties(selectedTrng.trainingID,

selectedTrng.trainingDescr, selectedTrng.trainingLevel,selectedTrng.trainingTech);

}

}. . .

}}

VBNamespace CustomerEntryFormPublic Partial Class Page

Inherits UserControl

Private Sub cmboBoxOfferings_DropDownClosed(sender AsObject, e As EventArgs)

If txtSPDev.Text = trningOfferOne AndAlsooptionOne.IsSelected = True Then

selectedTrng.trainingID = 1selectedTrng.trainingDescr = "This training provides an

introduction to SharePoint training."selectedTrng.trainingLevel = 100selectedTrng.trainingTech = "SharePoint"resetTxtValues()

setUITextProperties(selectedTrng.trainingID,selectedTrng.trainingDescr, selectedTrng.trainingLevel,selectedTrng.trainingTech)

ElseIf txtAdvSPDev.Text = trningOfferFour

Continued

269

Fox c08.tex V3 - 01/30/2009 5:06pm Page 270

Chapter 8: Bringing It All Together

Listing 8-10: DropDownClosed event (continued)

AndAlso OptionFour.IsSelected = True Then

selectedTrng.trainingID = 4selectedTrng.trainingDescr = "This training teaches how to

develop advanced custom solutions for SharePoint."selectedTrng.trainingLevel = 400selectedTrng.trainingTech = "SharePoint"resetTxtValues()setUITextProperties(selectedTrng.trainingID,

selectedTrng.trainingDescr, selectedTrng.trainingLevel,selectedTrng.trainingTech)

End If

End SubEnd Class

End Namespace

You’ll notice that there are two helper functions that are called during the processing of theDropDownClosed event. One is the resetTxtValues method, and the other is the SetUITextPropertiesmethod — see Listing 8-11. The resetTxtValues method simply ensures that the class-levelvariables are set to null — some very modest clean-up code. The setUITextProperties is the methodthat takes the updated properties from the user selection and sets them accordingly. For example,when the Text property of txtTrainingDescr is set to descry, this is the description that is passed tothis Helper function from the DropDownClosed event, which subsequently displays the description thatcorresponds to the selected training offering.

Listing 8-11: Helper functions

C#public void setUITextProperties(int offeringID, string descr, intlevel, string coreTech)

{trainingID = offeringID;txtTrainingDescr.Text = descr;txtTrainingLevel.Text = level.ToString();txtCoreTechnology.Text = coreTech;

}

public void resetTxtValues(){

trainingID = 0;txtTrainingDescr.Text = "";txtTrainingLevel.Text = "";txtCoreTechnology.Text = "";

}

VBPublic Sub setUITextProperties(offeringID As Integer, descr As String,level As Integer, coreTech As String)trainingID = offeringID

270

Fox c08.tex V3 - 01/30/2009 5:06pm Page 271

Chapter 8: Bringing It All Together

txtTrainingDescr.Text = descrtxtTrainingLevel.Text = level.ToString()txtCoreTechnology.Text = coreTech

End Sub

Public Sub resetTxtValues()trainingID = 0txtTrainingDescr.Text = ""txtTrainingLevel.Text = ""txtCoreTechnology.Text = ""

End Sub

There are also events tied to the two button controls, one to clear entries from the two text blocks andthe checkbox and another to submit the information to the SharePoint list. The first of these methods isstraightforward; it sets the Text property of the text blocks to null and then sets the isChecked propertyof the chkBxCompleted checkbox to false, which removes a selection should one exist. Listing 8-12provides a snapshot of the sample code.

Listing 8-12: Method to clear user entries

C#namespace CustomerEntryForm{

public partial class Page : UserControl{

private void btnClear_Click(object sender, RoutedEventArgs e){

txtBxCustomerEmail.Text = "";txtBxCustomerName.Text = "";chkBxCompleted.IsChecked = false;

}

. . .

}

}

VBNamespace CustomerEntryFormPublic Partial Class Page

Inherits UserControl

Private Sub btnClear_Click(sender As Object, e As RoutedEventArgs)txtBxCustomerEmail.Text = ""txtBxCustomerName.Text = ""chkBxCompleted.IsChecked = False

End Sub

. . .

End Class

End Namespace

271

Fox c08.tex V3 - 01/30/2009 5:06pm Page 272

Chapter 8: Bringing It All Together

One of the more important parts in this simple application is this next method; it is the event that istied to the Submit button on the data-entry form. The reason this is important is that it calls a ser-vice that updates the SharePoint list. To use this service, we have added a reference to the project andcalled the service TrainingListWS (see Figure 8-5). In this application, you’re specifically interested inthe updateList method within the service. Remember back to earlier in the chapter where this methodaccepts several parameters and then updates the items in a SharePoint list.

Figure 8-5

In this method, we’ve created a number of variables and then set these variables to the most currentselections in the UI. One of the variables, the trainingCompleted variable, is determined by a conditionalcheck on the state of the checkbox. Each of these variables is then passed to the service to the updateListmethod. Note that in this application, you are only allowed asynchronous Web Service calls, so thesyntax of the method call is updateListAsync along with the necessary parameters. Also, you have toadd an updateListCompleted event that fires an event after the asynchronous service call is complete. InListing 8-13, a simple message is specified to indicate that the list has, indeed, been updated.

Listing 8-13: Web Service call

C#namespace CustomerEntryForm{

public partial class Page : UserControl{

. . .

private void btnSubmit_Click(object sender, RoutedEventArgs e)

272

Fox c08.tex V3 - 01/30/2009 5:06pm Page 273

Chapter 8: Bringing It All Together

{

//Variable declarations.string trainingOffering = cmboBoxOfferings.SelectedItem.ToString();string trainingDescr = txtTrainingDescr.Text;string trainingIDStr = trainingID.ToString();string trainingLevel = txtTrainingLevel.Text;string coreTechnology = txtCoreTechnology.Text;string trainingCompleted = "";string studentName = txtBxCustomerName.Text;string studentEmail = txtBxCustomerEmail.Text;

//Get the response from the check-box and set thetrainingCompleted variable.

if (chkBxCompleted.IsChecked == true){

trainingCompleted = "Yes";}else{

trainingCompleted = "No";}

//Calling Web Service and Passing Parameters.TrainingListWS.ServiceSoapClient proxy = new

CustomerEntryForm.TrainingListWS.ServiceSoapClient();proxy.updateListCompleted += new

EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(proxy_updateListCompleted);

proxy.updateListAsync(trainingOffering, trainingDescr,trainingIDStr, studentName, studentEmail, trainingLevel,trainingCompleted, trainingIDStr);

}

void proxy_updateListCompleted(object sender,System.ComponentModel.AsyncCompletedEventArgs e)

{MessageBox.Show("Training list was updated.");

}

}

}

VBNamespace CustomerEntryFormPublic Partial Class Page

Inherits UserControl

Private Sub btnSubmit_Click(sender As Object, e As RoutedEventArgs)

Continued

273

Fox c08.tex V3 - 01/30/2009 5:06pm Page 274

Chapter 8: Bringing It All Together

Listing 8-13: Web Service call (continued)

‘Variable declarations.Dim trainingOffering As String =

cmboBoxOfferings.SelectedItem.ToString()Dim trainingDescr As String = txtTrainingDescr.TextDim trainingIDStr As String = trainingID.ToString()Dim trainingLevel As String = txtTrainingLevel.TextDim coreTechnology As String = txtCoreTechnology.TextDim trainingCompleted As String = ""Dim studentName As String = txtBxCustomerName.TextDim studentEmail As String = txtBxCustomerEmail.Text

‘Get the response from the check-box andset the trainingCompleted variable.

If chkBxCompleted.IsChecked = True ThentrainingCompleted = "Yes"

ElsetrainingCompleted = "No"

End If

‘Calling Web Service and Passing Parameters.Dim proxy As TrainingListWS.ServiceSoapClient = New

CustomerEntryForm.TrainingListWS.ServiceSoapClient()proxy.updateListCompleted += New EventHandler(Of

System.ComponentModel.AsyncCompletedEventArgs)(AddressOfproxy_updateListCompleted)

proxy.updateListAsync(trainingOffering,trainingDescr, trainingIDStr, studentName, studentEmail, trainingLevel,trainingCompleted, trainingIDStr)

End Sub

Private Sub proxy_updateListCompleted(sender AsObject, e As System.ComponentModel.AsyncCompletedEventArgs)

MessageBox.Show("Training list was updated.")

End Sub

End Class

End Namespace

The result of all of the above methods is an updated record in the SharePoint Training list. While thismay seem like a lot of code to accomplish this type of integration, you may apply the core Web Servicecode design to other applications as well as extend it to fit other types of applications that interface withSharePoint lists.

Hosting the Silverlight ApplicationThis book discussed several ways to host a Silverlight application. Some of them are low-touch and don’tnecessarily integrate very deeply with SharePoint, and others integrate (as in the example above) withSharePoint in a deeper manner — specifically, using the SharePoint object model or implementing nativeSharePoint Web Services. So, then, what is the most appropriate integration with SharePoint for ourSilverlight application? One of the methods we discussed was using the Web Part as a host container for

274

Fox c08.tex V3 - 01/30/2009 5:06pm Page 275

Chapter 8: Bringing It All Together

the Silverlight application. Furthermore, you learned a couple of different ways in which to implementthe Web Part as a host container, that is, through the Content Editor Web Part using the HTMLTextWriterobject or by creating and deploying a Web Part to SharePoint. For this application, the last of these wasthe method that we selected to use, that is, creating an instance of a Web Part and then deploying theWeb Part to the SharePoint server. This way, you’d have separate objects (the Web Parts) that are easilyreused across sites.

You will be familiar with how to do this by now, so we’ll just provide the core sample code created tointegrate the Web Part with the Silverlight application. Listing 8-14 lists the sample code for the hostcontainer Web Part. In this code, you’ll note that two major things are happening:

❑ You’re checking to see if there is a ScriptManager object, which enables you to host theSilverlight application.

❑ You’re creating an instance of the Silverlight ‘‘control’’ and then adding it to the Controlscollection — essentially rendering it on the SharePoint page.

Note that in the code sample in Listing 8-14, you’re adding the Silverlight application to a SharePoint siteas opposed to deploying it to the _layouts or ClientBin folder. The example is doing this to illustrate thatboth this and the aforementioned ways are all ways of deploying and integrating a Silverlight applicationwith SharePoint.

Listing 8-14: Web Part code

C#namespace SPCustomEntryWebPart{

[Guid("e9985d3b-66c9-4099-9d50-440aaa6ee8d0")]public class CustomUserForm : System.Web.UI.WebControls.WebParts.WebPart{

public CustomUserForm(){}

protected override void OnLoad(EventArgs e){

base.OnLoad(e);

ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);if (scriptManager == null){

scriptManager = new ScriptManager();this.Controls.Add(scriptManager);

}}

protected override void CreateChildControls(){

System.Web.UI.SilverlightControls.Silverlight myCustomForm= new System.Web.UI.SilverlightControls.Silverlight();

myCustomForm.ID = "myCustomForm";myCustomForm.Source = "http://stefoxdemo/XAPS1/CustomerEntryForm.xap";

Continued

275

Fox c08.tex V3 - 01/30/2009 5:06pm Page 276

Chapter 8: Bringing It All Together

Listing 8-14: Web Part code (continued)

myCustomForm.Width = new System.Web.UI.WebControls.Unit(475);myCustomForm.Height = new System.Web.UI.WebControls.Unit(300);

this.Controls.Add(myCustomForm);}

}}

VBNamespace SPCustomEntryWebPart<Guid("e9985d3b-66c9-4099-9d50-440aaa6ee8d0")>Public Class CustomUserForm

Inherits System.Web.UI.WebControls.WebParts.WebPartPublic Sub New()End Sub

Protected Overloads Overrides Sub OnLoad(e As EventArgs)MyBase.OnLoad(e)

Dim scriptManager__1 As ScriptManager =ScriptManager.GetCurrent(AddressOf Me.Page)

If scriptManager__1 Is Nothing ThenscriptManager__1 = New ScriptManager()AddressOf Me.Controls.Add(scriptManager__1)

End IfEnd Sub

Protected Overloads Overrides Sub CreateChildControls()Dim myCustomForm As New

System.Web.UI.SilverlightControls.Silverlight()myCustomForm.ID = "myCustomForm"myCustomForm.Source =

"http://stefoxdemo/XAPS1/CustomerEntryForm.xap"myCustomForm.Width = New System.Web.UI.WebControls.Unit(475)myCustomForm.Height = New System.Web.UI.WebControls.Unit(300)

AddressOf Me.Controls.Add(myCustomForm)End Sub

End ClassEnd Namespace

At this point, we’ve covered the service and the Silverlight application that calls one of the web meth-ods within the service. However, there still remain two other web methods to be consumed. In thenext section, we’ll discuss the use of the getTrainingListData method to get all of the data from theSharePoint Training list and then render it within a Silverlight list control. And in the final section, we’lldiscuss the use of list data to create the Silverlight chart.

Re-Skinning the Training ListThere are a couple of different ways in which you can re-skin a list, ranging from using a custom orBusiness Data Catalog (BDC) Web Service to binding data to a Silverlight control such as a list or data

276

Fox c08.tex V3 - 01/30/2009 5:06pm Page 277

Chapter 8: Bringing It All Together

grid. The method we chose for our sample application was to get the necessary data to populate theSilverlight control from the getTrainingListData method and then bind that data to the Silverlightcontrol, specifically, the data grid control.

We kept the XAML fairly lightweight for this example and used a Button control that would trig-ger the call to the getTrainingListData web method. You could alternatively call the service by cre-ating a PageLoad event and calling the service within the event; this might be more appropriate forproduction-quality code. In the XAML, you’ll find a Button control with the btnGetdata_Click event,which calls the Web Service, a text block, which provides a descriptive title for the chart, and lastly thedata grid, which is used as the control to which you bind your data. Listing 8-15 displays this samplecode.

Listing 8-15: Data grid XAML

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="CustomChartSample.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Width="800" Height="200">

<Canvas Background="White">

<Button Content="Refresh"x:Name="btnGetData"Canvas.Top="10"Canvas.Left="35"Click="btnGetData_Click"/>

<TextBlockx:Name="txtBlckChartTitle"Text="Training List Data"Canvas.Left="150"Canvas.Top="10"FontFamily="Tahoma"FontSize="16"FontWeight="bold"/>

<data:DataGridx:Name="trnDataGrid"Canvas.Left="35"Canvas.Top="30"CanUserResizeColumns="True"CanUserSortColumns="True"CanUserReorderColumns="True"/>

</Canvas></UserControl>

The meat of the code-behind resides in the btnGetData_Click event. This essentially creates an instanceof the Web Service and deserializes the object being passed to it from the Web Service; the data thatwill eventually be bound to the data grid. If you remember back to Listing 8-5, the structure of theincoming XML is eight child elements within a parent element of FieldCollection. This emulatesthe FieldCollection object that was created within the Web Service and populated through the call tothe SharePoint list. Thus, you need to iterate through each parent and child element and then add the

277

Fox c08.tex V3 - 01/30/2009 5:06pm Page 278

Chapter 8: Bringing It All Together

data inside the elements to a similar FieldCollection object within the Silverlight application. Afteryou’ve done this, you can then bind the newly created object to the data grid.

To deploy the re-skinned list, you again use the Web Part as a host container. Since this has been coveredalready, it won’t be covered again; however, note that the finished Web Part looks something like the oneyou see in Figure 8-6. As you can see, this simple list looks somewhat different in presentation from ourSharePoint list. This type of presentation would be ideal for displaying multiple, even connected (i.e.,summary/detail views), lists on one SharePoint page.

Figure 8-6

That about covers it for the binding of data to the data grid, so let’s now discuss the third and final webmethod and talk about how we can bind the data from the Training list to a Silverlight chart.

Binding Data to a Silverlight ChartThe final web method provides a way for you to call into SharePoint and grab some specific data fromthe SharePoint list; specifically, you’re going to retrieve all of the SharePoint Training IDs from the list.From this data, you’ll generate a small chart that provides some reporting on the number of offeringsof a specific type that exist within the Training list. The goal of this is to illustrate how you can not onlyretrieve data from a SharePoint list via a service (which is probably something you’ve just about masteredby now), but also, and more importantly, to create a chart that provides some enhanced reporting forthat data.

To create a chart, you can use various tools. Some of these tools are Open Source and can be foundon CodePlex, and others are sold by companies like ComponentOne. Either way, Silverlight can helpyou bring some enhanced reporting to your SharePoint site. For the sample application discussed inthis chapter, in the spirit of Open Source you’re going to create a simple chart from list data using acommunity tool, that is, the Silverlight Community toolkit. The toolkit was announced at the ProfessionalDevelopers Conference (PDC) in October 2008 (see Figure 8-7). When the kit was first released, therewere a number of controls that could be used to build out charting and reporting ranging from pie chartsand line charts to bar charts. Surely, there will have been controls added to this toolkit by thetime this book releases. To download the toolkit, go to www.codeplex.com/Silverlight. The chartsprovide an easy way for developers to create and deploy Silverlight charts using straightforwarddata-binding techniques, such as data-binding name–value pairs or objects.

Because you’re using the community toolkit, you’ll need to make sure you have the appropriate DLLsinstalled on your development machine and referenced in your Visual Studio project. The specific DLLwe used for this charting example was the Microsoft.Windows.Controls.Data.Visualization assem-bly. Using this DLL, you can create an instance of different types of charts and then bind data to that chartin the code-behind. In the following example, you can see that you’re using a column series chart and

278

Fox c08.tex V3 - 01/30/2009 5:06pm Page 279

Chapter 8: Bringing It All Together

calling it MyTrainingChartData. What makes using the community kit fairly straightforward is that youcan directly bind to objects from within the XAML. In the following code sample, you’ll note that we’veset the ItemsSource property to Binding and then set the IndependentValueBinding to TrnCourse andthe DependentValueBinding to NumCourseSales. Listing 8-16 provides the code for this.

Figure 8-7

Listing 8-16: XAML for custom Silverlight chart

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="BarChart.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:chart="clr-

namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization"

Width="800" Height="450"><Grid x:Name="LayoutRoot" Background="White">

<StackPanel Orientation="Vertical" Margin="15"><chart:Chart Height="200"

Continued

279

Fox c08.tex V3 - 01/30/2009 5:06pm Page 280

Chapter 8: Bringing It All Together

Listing 8-16: XAML for custom Silverlight chart (continued)

LegendTitle="Item"Title="IT Training Report"x:Name="MyBarChart">

<chart:Chart.Series><chart:ColumnSeries x:Name="MyTrainingChartData"

Title="Offerings Report"ItemsSource="{Binding}"

IndependentValueBinding="{Binding TrnCourse}"

DependentValueBinding="{BindingNumCourseSales}"/>

</chart:Chart.Series></chart:Chart>

</StackPanel></Grid>

</UserControl>

TrnCourse and NumCourseSales essentially represent the name–value pair that is bound to the chartfrom an object, which is created through two steps:

1. Iterate through the returned data from the SharePoint list.

2. Add the number of each individual training offering based on the IDs that were retrievedfrom the SharePoint list.

Ultimately, the key then is the passing of the numerical values that represent the total amount of eachinstance of the training based on their IDs. Class-level variables are used to tally the number of eachoffering, and then these numbers are used to create a business object that is further bound to the chart.These class-level variables are initially set to null, and then they’re passed as parameters to a methodthat dynamically creates an object called TrainingData. In Listing 8-17, you can see that there are twoproperties of the object, as mentioned previously, and when the loadChartData method is called, theappropriate parameters are passed to the method and then set within the business object.

Listing 8-17: Binding the data to the Silverlight control

C#using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.Collections.ObjectModel;using System.Collections.Generic;using System.ComponentModel;

namespace BarChart

280

Fox c08.tex V3 - 01/30/2009 5:06pm Page 281

Chapter 8: Bringing It All Together

{public class TrainingData{

public class CourseData{

public string TrnCourse { get; set; }public int NumCourseSales { get; set; }

}

public static List<CourseData> loadChartData(int numOfSPOfferings,int numOfVSOfferings,int numOfSQLOfferings,int numOfADVSPOfferings,int numOfOFClientOfferings

){

List<CourseData> courseList = new List<CourseData>();

courseList.Add(new CourseData(){ NumCourseSales = numOfSPOfferings, TrnCourse = "SharePoint" });

courseList.Add(new CourseData(){ NumCourseSales = numOfVSOfferings, TrnCourse = "VS" });

courseList.Add(new CourseData(){ NumCourseSales = numOfSQLOfferings, TrnCourse = "SQL Server" });

courseList.Add(new CourseData(){ NumCourseSales = numOfADVSPOfferings, TrnCourse =

"Adv. SharePoint" });courseList.Add(new CourseData()

{ NumCourseSales = numOfOFClientOfferings, TrnCourse ="Office Client" });

return courseList;

}

}}

VBImports System.NetImports System.WindowsImports System.Windows.ControlsImports System.Windows.DocumentsImports System.Windows.InkImports System.Windows.InputImports System.Windows.MediaImports System.Windows.Media.AnimationImports System.Windows.ShapesImports System.Collections.ObjectModel

Continued

281

Fox c08.tex V3 - 01/30/2009 5:06pm Page 282

Chapter 8: Bringing It All Together

Listing 8-17: Binding the data to the Silverlight control (continued)

Imports System.Collections.GenericImports System.ComponentModel

Namespace BarChartPublic Class TrainingData

Public Class CourseData

Public Property TrnCourse() As StringGetEnd GetSetEnd Set

End PropertyPublic Property NumCourseSales() As Integer

GetEnd GetSetEnd Set

End Property

End Class

Public Shared Function loadChartData(numOfSPOfferingsAs Integer, numOfVSOfferings As Integer, numOfSQLOfferings As Integer,numOfADVSPOfferings As Integer, numOfOFClientOfferings As Integer) AsList(Of CourseData)

Dim courseList As New List(Of CourseData)()

courseList.Add(New CourseData())courseList.Add(New CourseData())courseList.Add(New CourseData())courseList.Add(New CourseData())courseList.Add(New CourseData())

Return courseList

End Function

End ClassEnd Namespace

Given the fact that the list was very data-sparse, the integer values that were calculated based on the datapassed back from the service were as follows:

❑ 3 items for SharePoint

❑ 2 items for VS

❑ 0 items for each of SQL Server, Advanced SharePoint, and Office Client

282

Fox c08.tex V3 - 01/30/2009 5:06pm Page 283

Chapter 8: Bringing It All Together

This did result, though, in a nice-looking chart that with more data would be more fully fleshed out. Notethat when you mouse over the column within the chart, you get a tool-tip event that displays the numberfor that particular column (see Figure 8-8).

Figure 8-8

The Application in ActionThis chapter has discussed quite a bit and while you didn’t walk through every single step in the process,the chapter provided you with some key code samples that you might re-purpose for your own proto-typing efforts. To close down on what the sample application looks like, the screenshot in Figure 8-9provides a snapshot of the three elements of the application on the same page. In the context of the appli-cation, a user can navigate to this page, enter some data in the entry form, and then submit that to theSharePoint Training list. When refreshing the page, the training report will calculate and load the latestnumbers, and if you click Refresh on the Training list, it will also load the data.

Figure 8-9

283

Fox c08.tex V3 - 01/30/2009 5:06pm Page 284

Chapter 8: Bringing It All Together

The next question you’re probably asking yourself is how could we have made this better? As someof you know, you are always faced with time constraints while writing a book. And if we had ourdruthers, we would have certainly spent some or all of our time on building a more complete solu-tion with complex usability and data loading with page refreshes for all components, or even buildingone connected application (i.e., one Silverlight application that combines all of the functionality of thethree separate components). Furthermore, our main method of building and deploying services waswith ASMX, although we did test with WCF as well to make sure that the code worked there. This wasmainly because we deployed the services directly into SharePoint, as opposed to having a separate webapplication domain. This is something you’ll definitely want to investigate more as you learn how to useservices with Silverlight and SharePoint.

All that said, we feel that those that represent the most important takeaways are covered in thischapter — and, indeed, the wider book. For example, understanding how Web Services interact withSharePoint is vital if you’re going to be doing a lot of deep SharePoint integration. You’ll very muchwant to work with the SharePoint object model, potentially even leverage the core SharePoint WebServices as they expose a broader set of relevant and useful functionality. Also, ensuring that we coveredbusiness application functionality (such as charting and data-binding to controls) was also important, asSilverlight can be used for so much more than just playing media. One of the highest requests we havenoticed when interacting with our customers is the need for better reporting — more up-to-date andclean reporting. Not all of this will come from Silverlight, but certainly you’ll garner some great, moreenhanced data visualizations through using it. In addition, data entry is a common way of interactingwith data — not only in lists but also in external data sources. What was shown to you here might bemore user-friendly when it comes to entering data into lists, thus combining the strength of forms withthe power of SharePoint lists as the data repository.

SummaryIn this chapter, you walked through quite a bit. For example, the chapter discussed using lists as a datasource, using services to communicate with that list, and using custom controls and charts as part of yourpresentation layer. The goal was to stitch together a simple example that began to bring together some ofwhat you’ve learned in the rest of the book in one application. We hope you’ve seen how you might dothis and now have some great ideas of your own.

Given that you’re at the end of the book now, one of the key things to take with you, as you put thelearning from this book into action within your own company and projects, is that there is amazingpotential in the integration of SharePoint and Silverlight. You’ll see much more writing on this subjectarea as the two products mature and converge. In some cases, you’ll see SharePoint become the coreinfrastructure of a Silverlight-based presentation layer, which will provide for some very interesting userexperiences within SharePoint.

So what now? We encourage you to check out http: //mssharepointdeveloper.com if you haven’t doneso already. At the time of this writing, we were working on projects to provide even more SharePointand Silverlight tutelage. These will ultimately make their way onto the aforementioned site, so be sure tocheck that link for lots of good resources.

284

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 285

Inde

x

Index

AAdd Existing Item dialog, 160Add method, Silverlight controls, 157–158Add New Item dialog, 64Add New Project dialog, 146, 154Add References dialog, 156Add Service Reference Wizard, 228Advanced category, Web Part Editor, 186Appearance category, Web Part Editor, 186application, building sample, 247–284

in action, 283–284binding data to Silverlight chart, 278–283overview of, 247–248re-skinning training list, 276–278training list. See Training list, sample application

application pages, 111Application_Startup event, 205, 207–212ApplyChanges method, custom Web Part Editor,

192AppManifest.xaml file, 45–46ASMX (ASP.NET Web Service)

adding folders to store Web Service files, 103creating, 75–81deploying to own IIS web application, 87deploying to SharePoint server, 81–86, 250implementing web methods with WCF vs., 259–263testing, 81

ASMX (ASP.NET Web Service), Training list sampleapplication

building to integrate with SharePoint site, 250populating list collection of objects, 256–259using getListIDInfo web method, 252–253using getTrainingListData web method,

255–259using updateList web method, 253–254

ASP, adding controls to custom site page, 115–116ASP-based custom field type, 63–74

creating, 63–65custom field type definition file, 71–72deploying, 72–73developing Silverlight-based vs., 74–75field type class, 65–67hooking field control class to ASP control,

68–71implementing control, 67testing, 73–74

ASP.NET Web Service. See ASMX (ASP.NET WebService)

ASPXadding custom site page, 113–114application pages as, 104Silverlight solution project files, 26–27site pages as, 105Web Service compatibility with SharePoint,

86AssemblyInfo file, 112attributes, XAML, 5

Bbackground color, using HTML cookies,

215–220BaseFieldControl, 65–68, 70baseURI variable, 37–38BDC (Business Data Catalog) Web Service,

276binding data

to Silverlight chart, 278–283to Silverlight control, 276–278

blank solution, creating, 87branding SharePoint sites, 111–144

creating custom site page. See site pages, customcreating Navigation menu, 123–127custom list page. See list pages, customcustomizing master page, 137–143

BrandingSolution.snk fileadding custom site page, 113adding own content, 117–118defined, 112

Browse mode, Web Partscode for BrowseMode.xaml.cs, 239–246creating custom UI for, 195–202defined, 194

browsercreating lists through SharePoint interface, 59creating lists via Visual Studio vs., 60

Browser Bridge, 234Brushes panel, Silverlight controls, 146btnEnterResponse_Click event, 90, 93–94btnGetdata_Click event, 276btnMute_Click event, 38–40, 42–43Business Data Catalog (BDC) Web Service,

276Button, Silverlight controls, 146

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 286

C#

CC#

adding custom Web Part property, 187–189adding Feature Receivers, 170–171adding new contacts list to SharePoint site, 228adding ScriptManager to OnLoad method,

156–157adding Silverlight controls, 157binding data to Silverlight control, 280–281core field type class, 65–66creating custom UI for Web Part Display mode,

196–202creating custom Web Part Editor, 190–191creating data-entry form, 268–270creating server control to write XML Data Island,

220–222, 224creating Web Service, 76–80custom field type code, 95–96deleting feature installed files, 172–177getListIDInfo web method, 252getTrainingListData web method, 255,

257–258hooking field control class to ASP control, 68–69passing parameters to Silverlight control, 206–207registering embedded JavaScript file as web resource,

182registering Silverlight controls, 235–236rendering of custom field type, 97–98retrieving InitParameters, 207–208sample application code-behind, C#, 38–41service-calling code, 106setting ScriptableMethod attribute, 236–246updateList web method, 253–254using customized Web Part Verbs, 182–185using hidden fields, 210–213using HTML cookies, 214–219Web Part host container code, 50XAML code-behind, 91–93

Canvascreating Silverlight application, 28–29creating Silverlight application UI, 87–90positioning controls using, 3–5

charts, Silverlight, 278–279ChildControls method

adding Literal control to write XML Data Island,220–221

adding references to project, 48–51adding Silverlight control, 150, 157–158creating Silverlight control, 188–189display modes for Web Parts, 194–195field type control class, 68–70rendering of custom field type, 97–99using custom Web Part Editor, 190–191using hidden fields, 210using RenderContents to directly inject HTML,

162–163Cider (Visual Studio designer), 2

class library, Silverlight, 25click events, Silverlight applications, 35client access policy file, WCF, 262–263client-side Web Part Verbs, 182–185code-behind

adding to Silverlight application, 37–47ASPX test page, 27creating Silverlight application, 90–95overview of, 9–12updating Slider control, 196–197

color, background, 215–220Column Gallery page, 71, 73–74columns

adding to custom list, 59creating customized, 58–62

contacts list, 227–230containers

lists as. See listspositioning XAML controls, 3–5

ContainsKey method, Dictionary class, 207content

adding to site page, 116–123replacing placeholder controls with, 115–116

Content Editor panel, 150Content Editor Web Part, 149–154

adding Silverlight plug-in, 151–153defined, 145getting application to run, 149–151overview of, 149using JavaScript only, 153using Silverlight Streaming, 154

CONTENTTEMPLATES folder, 64, 67Contoso Pharmaceuticals. See application, building

samplecontrol IDs

implementing control, 67registering Silverlight controls, 235using hidden fields, 211

controlsadding to Silverlight application, 28creating ASP-based custom field type, 67event handlers associated with user, 35Silverlight. See Silverlight controlsusing containers to position XAML, 3–5

cookies, HTML. See HMTL cookiesCreateChildControls method

adding references to project, 50–51adding Silverlight control, 157–158creating ASP-based custom field type, 69–70creating hidden field control, 210creating server control for XML Data Island, 220–221creating Silverlight control, 157, 188–189determining Display mode, 194–195injecting HTML directly into Web Part, 162–163rendering of custom field type, 98–99using custom Web Part Editor, 190–191Web Part code, 275–276

CreateXMLDataIsland method, 221

286

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 287

Inde

xfeature.xml file

currentVideo variable, 37–44custom field types. See field types, customcustom list pages. See list pages, customcustom master pages. See master pagescustom site pages. See site pages, customcustom Web Parts. See Web Parts, advanced custom;

Web Parts, customCustomSitePage module folder, 113

Ddata binding

to ListBox, 230–233to Silverlight chart, 278–283

data connectivity, 205–246calling Web Services, 227–233initialization parameters. See initialization parametersPart-to-Part communication. See Part-to-Part

communicationXML Data Island, 220–226

data-entry form, sample project, 263–274creating for user, 264–268DropDownClosed event, 268–271method to clear user entries, 271–272overview of, 263–264Web Service call, 272–274

debuggingFeature Receivers, 178–180Silverlight application, 45Silverlight controls, 167–168Silverlight Web Parts, 166–167Web Part project, 51–52

deleting, feature installed files, 172–177dependencies, SharePoint custom field types, 100Description property, Web Parts, 165Design mode, Web Parts

creating custom UI for, 195–202defined, 194

designers, developers converging with, 1–2developers

converging with designers, 1–2what Silverlight offers to, 20

development environment, prerequisiteschanging MIME type, 13–14configuring, 13copying Silverlight DLL to your GAC, 19editing web.config file, 14–18

DISCO files, 84–86disco.exe tool, 83–84display modes, Web Parts, 193–202

adding custom Web Part Editor to collection,193

custom UI for, 195–202determining, 194–195overview of, 169passing to Silverlight control, 205types of, 193–194

DLLsadding to Web Part project, 48–51binding data to Silverlight chart, 278–279copying to your GAC, 19creating ASP-based custom field type, 63creating Web Service using, 76deploying Web Service, 81–82XAP files containing, 45

DropDownClosed event, 268–271

EEdit mode, Web Parts, 194–202editing

custom Web Part properties, 186–189displaying Silverlight application in SharePoint,

150–151new Silverlight control, 145–146web.config file, 14–18

EditorPartCollection, 193EnsureChildControls method, 68–70event aggregation model, 234event handlers, 35event receivers, 60–61events, associating with controls, 3–5Expression Blend

creating Silverlight application, 36creating XAML, 2–3editing new Silverlight control, 145–146integration with Visual Studio Developer tool, 1–2opening and loading Silverlight project in, 7–9

Extensible Application Markup Language. See XAML(Extensible Application Markup Language)

FFast Forward button

adding code-behind to Silverlight application, 38sample application code-behind, 40–41, 44

Feature Receiversadding, 170–172debugging, 178–180defined, 170deleting feature installed files, 172–177registering, 178

featurescustomizing Web Parts, 154–155deploying Silverlight within Web Part, 160installing/uninstalling. See Feature Receiverstroubleshooting Web Part deployment, 158

FeatureUninstalling method, 172–177feature.xml file

adding own content in master page, 118–120editing from CustomSitePage feature, 114referencing Feature Receiver, 126registering Feature Receiverin, 178updated, including minimal master file, 133

287

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 288

field control class

field control class, 63–64, 68–71field type class, 65–67field type definition file, 71–72, 101field types, 58–59field types, custom

ASP-based. See ASP-based custom field typecreating, 61–62creating SharePoint, 95–107deploying solution, 107–108lists, columns and, 58–62references, 109Silverlight and SharePoint integration. See Silverlight

and SharePoint integration, custom field typesSilverlight-based. See Silverlight-based custom field

typesummary review, 109

FieldCollection objects, 256–259, 277–278FieldRenderingControl property, field type

class, 65–67form fields, 210forms. See data-entry form, sample project

GGAC (global assembly cache)

copying Silverlight DLL to your, 19deploying custom field type, 72–73deploying new project to SharePoint, 113deploying Web Service, 81–83

GACUTIL utility, 72–73GetCookie method, HTML cookies, 218getListIDInfo web method, 252–253,

260–261GetListItems service call, 229–232GetSLRatingControlsList method, 235–236getTrainingListData web method

binding data to Silverlight control, 276–278overview of, 255–259populating list collection of objects, 257–259

GradientStop, 215–216Group property, Web Parts, 164–165GUID value, Web Parts, 165

Hhelper functions, 270–271HelpUrl property, Web Parts, 165Hex (hexadecimal) values, HTML, 215hidden fields, HTML, 210–214HiddenField control, 210–214high-touch option, 24–25HMTL cookies, 214–220

adding to Cookie collection on server, 215converting HTML color string, 216–217overview of, 214returning value of, 217–218setting background color from, 219

setting Name property of GradientStop, 215–216viewing values of, 219–220

host containercreating/deploying Web Part to SharePoint, 47–52implementing Web Part as, 275–276

HTMLadding support without Silverlight plug-in, 151–153adding to SharePoint site, 149–154displaying Silverlight in SharePoint, 150–151hidden fields, 210–214injecting directly into Web Part, 162–163source code for Web Part, 223–224test page, 26–27

HTMLInputHidden field, 97–100HTMLTextWriter object, 162–163

IID property, Silverlight controls, 157IE (Internet Explorer), 219–220IIS (Internet Information Services)

changing MIME type in, 13–14using WCF to implement web methods, 259, 262

initialization parameters, 205–220overview of, 205–206passing to Silverlight control, 206–207retrieving InitParameters, 207–210using hidden fields, 210–214using HTML cookies, 214–220

InitParameters propertydefined, 205passing Display mode to Silverlight control, 194–195retrieving, 207–210

integration, multiple levels of, 247IntelliSense, 35, 37–38Internet Explorer (IE), 219–220Internet Information Services (IIS)

using MIME type in, 13–14using WCF to implement web methods, 259, 262

IsMuted property, Mute button, 38–39

JJavaScript

adding Silverlight plug-in, 151–152calling functions with customized Verbs in, 182–185connecting Silverlight controls through, 234dynamically creating object tag in, 153embedding in Web Parts, 181–182using custom embedded files, 174–175

LLambda expressions, 218Layout section, Web Part Editor, 186_layouts folder, deploying Web Service to, 83–87

288

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 289

Inde

xQuickAddGroups property, Web Parts

Likert scale responsedefined, 63using ASP control. See ASP-based custom field typeusing Silverlight. See Silverlight-based custom field

typeLINQ for XML

building XML Data Island Literal control, 221–222converting XML Data Island to XElement, 224deleting feature installed files, 174querying XML Data Island, 225

list collection, populating objects of, 256–259list pages, custom, 128–137

adding feature to project, 129–130creating new custom list view, 133–137overview of, 128–129with Silverlight, 130–133

ListBox, data-binding to, 229–233lists

converting registered Silverlight controls to, 236creating custom, 59–61defined, 57re-skinning, 276–278using templates and customer, 58–59

ListService, 228–229Literal control, 220–222low-touch option, 24

Mmaster pages, 137–143

creating basic, 138–141customizing, 141–144overview of, 137

MIME, adding to Silverlight, 13–14Module.xml file

creating custom field type, 100creating custom site page, 113–114deploying Silverlight application within Web Part,

160–161deploying XAP files, 118–119updating to include minimal master file, 140–141

Mute button, 38MyFirstSLApp, 49–51MySilverlightApp.xap file, 26

NName property, GradientStop, 215–216naming conventions, Web Service project, 76Navigation menu, creating, 123–127New Item dialog, 160New Project dialog, 145New Web Site templates dialog, 76Notepad, creating XAML using, 2no-touch option, 23

Oobject tag, 151–153objects

nesting in Silverlight application UI, 28–29populating list collection of, 256–259properties for, 29

online referencescreating custom field types, 109deploying Web Services to own IIS application,

87Signature field type, 62Silverlight, 21Silverlight and SharePoint integration, 56Silverlight Streaming media service, 23WCF Services, 251, 259

OnLoad method, 156–157overloads, 38

Ppage declaration, custom site page, 114–116Page.xaml file

adding code-behind to Silverlight application, 37–44creating custom site page, 120–121creating Silverlight application UI, 87–90defined, 27editing new Silverlight control, 145–146viewing XAML code, 28

Page.xaml.cs file, 27Part-to-Part communication, 233–246

overview of, 233–235registering controls, 235–236setting ScriptableMethod attribute, 236–246

Pause button, 38, 40, 43–44placeholder controls

adding own content to, 116–123replacing with content, 115–116

Play button, 38, 40, 43populating list collection of objects, 256–259project files, Silverlight solution, 26–37

inspecting controls to add, 28nested structure of UI, 28–29opening Page.xaml node, 27set properties for elements, 29–35types of, 26–27viewing XAML code for UI, 28

propertiesdisplaying Web Part in Web Part Gallery, 164–165editing custom Web Part, 186–189for Silverlight controls, 145–146, 157Web part, 165–166

publishing, 150

QQuickAddGroups property, Web Parts, 164–165

289

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 290

rating value, updating Silverlight control

Rrating value, updating Silverlight control, 237–238RatingControlID parameter, 211ReceiverAssembly attribute, 178ReceiverClass attribute, 178references

adding Feature Receiver using, 170–172adding to Web Part project, 48–51creating Web Service to interact with SharePoint list,

76displaying Silverlight control and adding, 155–157

registeringcustom embedded JavaScript files, 182Feature Receivers, 178Silverlight control with HTML page, 235–236

RenderContents method, Web Parts, 162–163RenderingTemplate ID, custom field type, 67reports, binding data to Silverlight chart, 278–283resetTxtValues method, DropDownClosed

event, 270–271re-skinning lists, 276–278resources, loading into Silverlight application, 45Rewind button, adding code-behind, 38, 40, 43Rich Text Editor, 150Run mode, editing custom Web Parts in, 186–189

Ssample application. See application, building sampleScriptableMethod attribute, 236–246

complete listing for BrowseMode.xaml.cs, 239–246setting, 236–237updating rating on Silverlight controls, 237–238

ScriptableType attribute, 235ScriptManager control, 48–51, 156–157ScriptObjectBrowseMode class using, 241–242, 244–245registering controls, 235updating rating value on Silverlight controls, 237–238

security, Silverlight, 20server controls

creating to write XML Data Island, 220–221using hidden fields, 210–214

server-side Web Part Verbs, 182–185service contract, getListIDInfo, 260–261service-calling code, Web references, 104–107services. See ASP.NET Web Service; WCF (Windows

Communication Foundation) ServicesSetAttribute method, hidden fields, 212–213SetRatingValue method, ScriptableMethod,

237–238SetUITextProperties method,

DropDownClosed event, 270–271setup.bat, 162SharePoint

creating custom list with, 59creating/deploying Web Part host container, 47–52

customizing Web Parts, 158–159deploying new projects immediately to, 112–113Silverlight integration with, 19–20

SharePoint Designer (SPD), 116Signature field type, 62Silverlight, introduction to

additional references, 21changing MIME type, 13–14code-behind, 9–12copying Silverlight DLL to your GAC, 19designer and developer convergence, 1–2development environment prerequisities, 13–19editing web.config file, 14–18overview of, 1SharePoint integration with, 19–20summary review, 20XAML overview, 2–9

Silverlight and SharePoint integration, custom fieldtypes, 87–107

creating SharePoint custom field type, 95–107overview of, 87Silverlight application code-behind, 90–95Silverlight application UI, 87–90

Silverlight and SharePoint integration, first, 23–56adding Silverlight video player to SharePoint, 52–55creating Silverlight application. See Silverlight

application, creatingcreating/deploying SharePoint Web Part host, 47–52with low-touch option, 24with no-touch option, 23–24overview of, 25–26references, 56summary review, 56troubleshooting, 55–56

Silverlight application, creating, 25–47beginning new project, 25–26creating code-behind, 37–47working with project files, 26–37

Silverlight controlscreating, 145–148customizing Web Parts. See Web Parts, customdisplaying, 155–157drag-and-drop, 7getting data into. See initialization parametersinserting into placeholder controls, 116–123registering, 235–236transferring data between. See Part-to-Part

communicationusing Content Editor Web Part, 149–154

Silverlight Streaming servicedisplaying Silverlight control from, 162–163overview of, 154Silverlight/SharePoint integration using, 23–24

Silverlight Web Part Editor, 189–193. See also displaymodes, Web Parts

Silverlight-based custom field type, 74–87creating ASP-based vs., 74–75creating Web Service, 75–81

290

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 291

Inde

xVB

deploying Web Service, 81–87testing Web method, 81

site pages, custom, 111–123adding, 113–116adding blank branding solution, 112–113adding own content, 116–123overview of, 111–112viewing available placeholders in, 116

size, setting Silverlight control, 146Slider control

code-behind to update values of, 196–197connecting Silverlight controls on same page, 234setting for hidden fields, 210, 212–213switching UI based on Display mode, 195–196updating value of, 236–237using custom Silverlight Web Part Editor, 192using LINQ for XML to query XML Data Island, 225

solutionscustomizing Web Parts using features, 154–155uninstalling and updating, 162

Source Editor dialog, 150–151Source property, Silverlight controls, 157SPD (SharePoint Designer), 116src property, XML node, 225–226StopColor object, GradientStop, 215–216stsadm.exe, 178–180style, Silverlight controls, 146support, Silverlight, 20SynChanges method, custom Web Part Editor, 192System.Web.Extensions DLL, 48–51System.Web.Silverlight assembly, 116–117System.Web.Silverlight DLL, 48–51

Ttemplates

list, 57–59New Project, 25–26

testingcustom embedded JavaScript files, 182custom field types, 73–74, 81, 101Web Part deployment, 52

Text Box, Silverlight control, 146Timespan objects

adding code-behind to Silverlight application, 37–38sample application code-behind, 39–44setting Play button, 38

Title property, Web Parts, 165TitleUrl property, Web Parts, 165tools, 13–19

changing MIME type, 13–14copying Silverlight DLL to GAC, 19editing web.config file, 14–18overview of, 13

Training list, sample applicationhosting Silverlight application, 274–278overview of, 248–250re-skinning, 276–278

Training list, sample application services, 250–259data entry, 263–274overview of, 250–251populating list collection of objects, 256–259using getListIDInfo web method, 252–253using getTrainingListData web method,

255–259using updateList web method, 253–254using WCF, 259–263

troubleshooting, Silverlight/SharePoint integration,52–55

UUI (user interface), Silverlight application, 87–90uninstallation

cleaning up XAP files during feature, 120of Navigation menu item during deployment, 126of previous code using same feature names, 151of solutions, 162using Feature Receivers. See Feature Receivers

unique IDsgenerated by HiddenField control, 211generating for Web Part Editor, 193

updateList web method, 253–254updates

of custom fields in SharePoint list, 77–81customizing master page, 140–141hidden field values, 212–214Silverlight controls, 120–121slider control label, 225solution, 162using custom Silverlight Web Part Editor, 192XAP file location in Silverlight application, 46, 55

URLadding Web Part properties, 165–166, 179configuring Web Part for deployment, 51–52for navigation menu, 123–127for SharePoint site, 53for Silverlight application code-behind, 37–39, 42, 45for Silverlight control, 157using custom embedded JavaScript files, 181for XML Data Source, 225–226

user forms. See data-entry form, sample projectuser interface (UI), Silverlight application, 87–90UserControl node, editing Silverlight control, 145userResponse web method, 76–81userResponseFromXAML variable, 90–94,

105–107

VVB

adding custom Web Part property, 187–189adding Feature Receivers, 170–172adding new contacts list to SharePoint site, 228–229

291

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 292

VB (continued)

VB (continued)adding ScriptManager to OnLoad method, 158adding Silverlight controls, 158binding data to Silverlight control, 281–282core field type class, 66–67creating custom UI for Web Part Display mode,

197–202creating custom Web Part Editor, 191–192creating data-entry form, 269–271creating server control to write XML Data Island,

221–222, 224–225creating Web Service, 76–78, 80–81custom field type code, 96–97deleting feature installed files, 172–177getListIDInfo web method, 252–253getTrainingListData web method, 255–256,

258–259hooking field control class to ASP control, 69–71page declaration for custom site page, 114passing parameters to Silverlight control, 207registering embedded JavaScript file as web resource,

182registering Silverlight controls, 235–236rendering of custom field type, 98–100retrieving InitParameters, 208–209sample application code-behind, 41–44service-calling code, 106–107setting ScriptableMethod attribute, 236–246updateList web method, 254using customized Web Part Verbs, 182–185using hidden fields, 210–213using HTML cookies, 214–219Web Part host container code, 50–51XAML code-behind, 93–95

Verb event handler, Web Partscustomizing and working with, 182–185defined, 169updating value of hidden fields, 212–213

vidSuffix variable, 37–38Visual Studio

building XAML in, 7–8creating custom list programmatically with, 59–61Developer tool, and Expression Blend, 1–2editing web.config file, 14–18XAML Designer, 146–147

Visual Studio Extensions Version 1.2 (WssVse) tools,145–148

_vti_bin folder, 86–87

WWCF (Windows Communication Foundation) Services,

87WCF (Windows Communication Foundation) Services,

Training list sample applicationconfiguring web methods, 259–263overview of, 250

populating list collection of objects, 256–259using getListIDInfo web method, 252–253using getTrainingListData web method,

255–259using updateList web method, 253–254

web methods, Web Servicescreating Web Service, 78–81testing, 81using getListIDInfo web method, 252–253using getTrainingListData web method,

255–259using updateList web method,

253–254WCF vs. ASP.NET, 261–262

Web Part Editor, customadding to collection, 193creating, 189–193editing custom Web Part properties, 186–189

Web Part Gallery, 162, 164–165Web Part Zones

defined, 145Web Part Gallery display using, 164–165

Web Partsadding references to project, 48–51adding Silverlight video player, 52–55configuring project for deployment, 51–52creating project, 47–48creating Silverlight control, 145–148HTML source code for, 223–224overview of, 145Silverlight integration with SharePoint using,

24–25transferring data between Silverlight controls. See

Part-to-Part communicationusing Content Editor Web Part, 149–154

Web Parts, advanced custom, 169–203adding feature receivers, 170–172creating editor parts, 193–202debugging Feature Receivers, 178–180deleting feature installed files, 172–177editing properties, 186–189overview of, 169registering Feature Receivers, 178summary review, 202using custom embedded JavaScript files,

181–182using custom Web Part Editor, 189–193using customized verbs, 182–185

Web Parts, custom, 145–168creating Silverlight control, 145–148debugging, 166–168deploying Silverlight application, 159–161displaying Silverlight control and adding references,

155–158displaying Web Part in gallery, 164–165properties, 165–166running solution, 158–159SharePoint solution features, 154–155

292

Fox bindex.tex V3 - 01/30/2009 5:10pm Page 293

Inde

xzones, Web Part

starting new Web Part project, 154uninstalling and updating solution, 162using RenderContents to inject HTML into,

162–164Web Services

adding new contacts list to SharePoint site,227–230

ASP.NET. See ASP.NET Web Servicedata binding to ListBox, 230–233data-entry sample project. See data-entry form,

sample projectintegrating into Silverlight-based custom field type,

101–107WCF. See WCF (Windows Communication Foundation)

Servicesweb.config file

editing, 14–18modifying to enable debugging, 45as Silverlight solution project file, 26

Windows Communication Foundation. See WCF(Windows Communication Foundation) Services

Windows Presentation Foundation (WPF),XAML in, 2

WPF (Windows Presentation Foundation),XAML in, 2

WSDL files, 85–86.wsp extension, 155WSP View

creating Web Part, 48integrating Web Service into Silverlight custom field,

104registering Feature Receivers, 178

WssVse (Visual Studio Extensions Version 1.2) tools,145–148

XXAML (Extensible Application Markup Language),

2–9. See also Silverlight application, creatingattributes, 5creating, 2–3custom Silverlight chart, 279–280multiple controls within container, 3–5opening Expression Blend, 7–9Silverlight application code-behind, 91–95simple Silverlight control, 146–147simple user control, 5–7user data-entry form, 264–268views, 7–8

XAML Editor, Visual Studio, 147XAP package files

adding own content, 117–120as archive of built project files, 26, 45defined, 12deploying when project is deployed, 160ensuring location of, 45–47hosting with Silverlight Streaming services, 154

XAP_Bin subfolder, 150x:class property, XAML, 5XML Data Island, 220–226

creating server control, 220–225defined, 220setting URL for XML data source, 225–226

XML files, 113–114

Z.zip extension, appending ZAP file with, 45–46zones, Web Part, 145

293

Take your library wherever you go.Now you can access more than 200 complete Wrox books online, wherever you happen to be! Every diagram, description, screen capture, and code sample is available with your subscription to the Wrox Reference Library. For answers when and where you need them, go to wrox.books24x7.com and subscribe today!

Programmer to ProgrammerTM

• ASP.NET • C#/C++ • Database • General • Java• Mac• Microsoft Office

• .NET • Open Source • PHP/MySQL • SQL Server • Visual Basic • Web• XML

Find books on

www.wrox.com

wrox_24x7_BOB_ad_final.indd 1wrox_24x7_BOB_ad_final.indd 314 9/8/2007 4:26:08 PM9/8/2007 4:26:08 PM