80
ComponentOne Studio for Silverlight QuickStart October 21, 2008 Contents Introduction .................................................................................................................................................. 4 Software Requirements ............................................................................................................................ 4 Licensing .................................................................................................................................................... 4 Running the Samples ................................................................................................................................ 4 Assembly Summary ....................................................................................................................................... 5 Control Summary .......................................................................................................................................... 5 C1.Silverlight.dll ........................................................................................................................................ 5 Description ............................................................................................................................................ 5 Main Classes.......................................................................................................................................... 5 C1.Silverlight.Extended.dll ........................................................................................................................ 7 Description ............................................................................................................................................ 7 Main Classes.......................................................................................................................................... 7 C1.Silverlight.Chart.dll ............................................................................................................................... 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8 C1.Silverlight.Gauge.dll ............................................................................................................................. 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8 C1.Silverlight.Maps.dll .............................................................................................................................. 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8 C1.Silverlight.RichTextBox.dll .................................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9 C1.Silverlight.RichTextBox.Toolbar.dll ...................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9 C1.Silverlight.DataGrid.dll ......................................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9 C1.Silverlight.Uploader.dll ........................................................................................................................ 9 Description ............................................................................................................................................ 9 Main Classes........................................................................................................................................ 10

ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

  • Upload
    vukhanh

  • View
    235

  • Download
    0

Embed Size (px)

Citation preview

Page 1: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

ComponentOne Studio for Silverlight QuickStart October 21, 2008 

Contents Introduction .................................................................................................................................................. 4 Software Requirements ............................................................................................................................ 4 Licensing .................................................................................................................................................... 4 Running the Samples ................................................................................................................................ 4

Assembly Summary ....................................................................................................................................... 5 Control Summary .......................................................................................................................................... 5 C1.Silverlight.dll ........................................................................................................................................ 5

Description ............................................................................................................................................ 5 Main Classes.......................................................................................................................................... 5

C1.Silverlight.Extended.dll ........................................................................................................................ 7 Description ............................................................................................................................................ 7 Main Classes.......................................................................................................................................... 7

C1.Silverlight.Chart.dll ............................................................................................................................... 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8

C1.Silverlight.Gauge.dll ............................................................................................................................. 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8

C1.Silverlight.Maps.dll .............................................................................................................................. 8 Description ............................................................................................................................................ 8 Main Classes.......................................................................................................................................... 8

C1.Silverlight.RichTextBox.dll .................................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9

C1.Silverlight.RichTextBox.Toolbar.dll ...................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9

C1.Silverlight.DataGrid.dll ......................................................................................................................... 9 Description ............................................................................................................................................ 9 Main Classes.......................................................................................................................................... 9

C1.Silverlight.Uploader.dll ........................................................................................................................ 9 Description ............................................................................................................................................ 9 Main Classes........................................................................................................................................ 10

Page 2: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1.Silverlight.Zip.dll ................................................................................................................................. 10 Description .......................................................................................................................................... 10 Main Classes........................................................................................................................................ 10

C1.Silverlight.Data.dll .............................................................................................................................. 10 Description .......................................................................................................................................... 10 Main Classes........................................................................................................................................ 10

Quick‐Start .................................................................................................................................................. 11 Create a project that uses the C1.Silverlight controls ............................................................................ 12

Create a new Silverlight Project .......................................................................................................... 12 Add references to the C1.Silverlight assemblies ................................................................................ 13 Create the initial page layout .............................................................................................................. 14 Create Styles ....................................................................................................................................... 15

C1.Silverlight.dll ...................................................................................................................................... 17 C1ComboBox ....................................................................................................................................... 17 C1MaskedTextBox .............................................................................................................................. 19 C1NumericBox .................................................................................................................................... 20 C1Menu ............................................................................................................................................... 21 C1Window ........................................................................................................................................... 24 C1MessageBox .................................................................................................................................... 25 C1TreeView ......................................................................................................................................... 26 C1HyperPanel ..................................................................................................................................... 31 C1DragDropManager .......................................................................................................................... 33

C1.Silverlight.Extended.dll ...................................................................................................................... 36 C1Expander ......................................................................................................................................... 36 C1Accordion ........................................................................................................................................ 37 C1ImageRotator .................................................................................................................................. 39 C1ImageMagnifier ............................................................................................................................... 43 C1HtmlHost ......................................................................................................................................... 44 C1Book ................................................................................................................................................ 45 C1Cube ................................................................................................................................................ 48

C1.Silverlight.RichTextBox.dll .................................................................................................................. 49 C1RichTextBox .................................................................................................................................... 49

C1.Silverlight.Uploader.dll ...................................................................................................................... 53 C1Uploader ......................................................................................................................................... 53

C1.Silverlight.Gauge.dll ........................................................................................................................... 59 C1RadialGauge and C1LinearGauge .................................................................................................... 60

C1.Silverlight.Maps.dll ............................................................................................................................ 62 C1Maps ............................................................................................................................................... 62

C1.Silverlight.Chart.dll ............................................................................................................................. 65 C1Chart ............................................................................................................................................... 65

DataTemplates ............................................................................................................................................ 70 Create the “Templates” Solution ............................................................................................................ 70

Page 3: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Populate the controls .............................................................................................................................. 71 Defining and using Data Templates ........................................................................................................ 73

Control Templates ....................................................................................................................................... 77  

Page 4: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Introduction This document describes the controls in the ComponentOne Studio for Silverlight library. 

All the controls in the library target the Silverlight 2.0 library, and take full advantage of all the new technologies Microsoft has built into the Silverlight platform. 

The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control libraries for WinForms, ASP.NET, WPF, and Mobile platforms and is the most complete control suite available today. 

Software Requirements In order to use the controls, the following software is required: 

• Microsoft Silverlight 2.0 RTW (2.0.31005.0) 

• Microsoft Visual Studio 2008 (9.0.30729.1 SP or later) 

Licensing The ComponentOne Studio for Silverlight product is a commercial product. It is not shareware, freeware, or open source. If you use it in production applications, please purchase a copy from our web site or from the software reseller of your choice. 

Running the Samples If you just installed Studio for Silverlight, open Visual Studio 2008 and load the "Samples.sln" solution located in the “Program Files\ComponentOne\Studio for Silverlight\Samples” folder. This solution contains all the samples that ship with this release. Each sample has a readme.txt file that describes it, and two projects named as follows: 

• <SampleName>   Silverlight project (client part) 

• <SampleName>Web  ASP.NET project that hosts the Silverlight project (server part) 

To run a sample, right‐click the <SampleName>Web project in the solution explorer, select "Set as Startup Project", and press F5. 

Page 5: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Assembly Summary ComponentOne Studio for Silverlight includes several assemblies. This increases the granularity of the studio and decrease the size of applications that don’t use all the controls available in the studio. 

The table below lists the assemblies in the ComponentOne Studio for Silverlight. The XAP Size column shows the size of the compressed file that has to be deployed with the applications that use the assembly. The Dependencies column shows only the ComponentOne dependencies (Silverlight dlls are not listed). 

#  Assembly  Size (kb) XAP Size (kb) Dependencies 

1  C1.Silverlight  396  113   2  C1.Silverlight.Extended  303  61  C1.Silverlight 3  C1.Silverlight.Data  51  23   4  C1.Silverlight.Zip  78  31   5  C1.Silverlight.Chart  225  78   6  C1.Silverlight.DataGrid  334  84  C1.Silverlight 7  C1.Silverlight.RichTextBox  157  66  C1.Silverlight 8  C1.Silverlight.RichTextBox.Toolbar  224  29  C1.Silverlight.RichTextBox9  C1.Silverlight.Uploader  34  14   10  C1.Silverlight.Maps  76  23  C1.Silverlight 11  C1.Silverlight.Gauge  70  23  C1.Silverlight 

ComponentOne Silverlight Assemblies (build 2.0.20083.6, October 20, 2008) 

Control Summary The table below lists the main controls in each assembly. 

C1.Silverlight.dll 

Description This is the main assembly. It contains several basic controls and utility classes that can be used by themselves and are often used by other controls in the Studio. 

Main Classes • C1ComboBox: Combines a textbox with an auto‐searchable drop‐down list, similar to the ComboBox 

controls in WPF and WinForms. 

• C1DropDown: Provides a generic dropdown control (like a ComboBox or a DateTimePicker). The control has a Header property that determines what the user sees when the drop‐down part of the control is closed, and a Content property that determines what goes into the drop‐down part. 

Page 6: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

• C1FilePicker: A control that shows a file name and allows the user to show a file picker dialog to browse the file system and select one or more files. 

• C1MaskedTextBox: Provides a text box with a mask that automatically validates the input, similar to the MaskedTextBox control in WinForms. 

• C1NumericBox: Provides a text box for displaying and editing formatted numeric values. Includes up/down buttons to increment or decrement the value, and allows you to display a fixed or variable number of decimal places and thousand separators. 

• C1TreeView: Provides a hierarchical view of data items, similar to the TreeView control in WPF and WinForms. The control contains C1TreeViewItem objects, which may contain any type of UI element (text, images, checkboxes, etc), and supports drag drop operations. 

• C1Menu: Provides a hierarchical list of elements associated with event handlers, similar to the Menu control in WPF. 

• C1Window: Shows content in a window inside the Silverlight plug‐in, similar to the Window class in WPF. 

• C1MessageBox: Provides an easy way to show messages and ask simple questions to the user. 

• C1PromptBox: Provides an easy way to get simple input from the user. 

• C1RangeSlider: Lets users select a range by moving two thumbs along a track. Similar to the Slider control in WPF and Silverlight, but provides a range (UpperValue and LowerValue) instead of a single value. 

• C1HyperPanel: A StackPanel that applies a dynamic zoom effect to items near the mouse, similar to the system toolbar seen in the Apple Macintosh. You can place any elements in a C1HyperPanel to achieve carousel‐like effects and display a large number of elements in a relatively small container, without using scrollbars. 

• C1DockPanel: Panel that allows you to dock other panels horizontally and vertically, similar to the DockPanel class available in WPF. 

• C1UniformGrid: Grid panel where all cells have the same width and height, similar to the UniformGrid class in WPF. 

• C1WrapPanel: A panel that wraps its contents vertically or horizontally, similar to the WrapPanel class in WPF. In addition to the automatic wrapping, the C1WrapPanel supports custom breaks so you can customize the layout as needed. 

• C1DragDropManager: Provides support for drag and drop operations in Silverlight applications. It also provides methods for registering UIElement objects to act as drag sources and drop targets automatically, and fires events that allow you to customize the drag‐drop behavior. 

Page 7: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

• C1MouseHelper: Provides additional mouse support for FrameworkElement objects, including mouse wheel support, double‐click events, and element dragging. 

• C1PasswordBox: This control was present in pre‐release versions of the studio but has been removed since Microsoft added a PasswordBox control to the Silverlight core. 

C1.Silverlight.Extended.dll 

Description Provides controls that are more specialized and less commonly used than the ones in the main C1.Silverlight.dll assembly. Most of the controls in the C1.Silverlight.Extended.dll are visually rich controls not available in WinForms or in WPF. 

Main Classes • C1Accordion: An ItemsControl where each item is shown inside a C1Expander control and only one 

is allowed to be expanded at a time. This is similar to the Microsoft Outlook navigation bar. 

• C1Book: Presents UIElement objects as if they were pages in a book. You can see two elements at a time, and turn pages with the mouse, just as you would turn pages in a regular paper book. The control provides page‐turning effects and shadows that make the experience visually interesting and yet familiar. 

• C1ColorPicker: Enables users to browse colors using a palette or to create colors using the RGB and HSB color models.  

• C1Cube: Presents UIElement objects as faces on a rotating cube. The control provides methods for rotating the cube in order to display specific elements. This is a visually attractive and innovative way to present information using a 3D metaphor. 

• C1HeaderedContentControl: Provides the base implementation for all controls that contain single content and have a header, similar to the HeaderedContentControl in WPF.  

• C1Expander: A C1HeaderedContentControl whose content can be collapsed and expanded by clicking on the header. 

• C1HtmlHost: Provides a frame that can host arbitrary Html content. The control can display content from arbitrary URIs (SourceUri property), or it can display HTML documents (SourceHtml property). Note: the C1HtmlHost control requires that the host Silverlight plug‐in have its Windowless property set to true. 

• C1ImageMagnifier: Similar to an Image element with a ‘magnifying glass’ over it. The portion of the image under the magnifying glass is zoomed. The user can move the magnifying glass over the image to easily zoom in on any part of the image, and he can use the keyboard to change the zoom factor. 

Page 8: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

• C1ImageRotator: Provides a pseudo‐3D rotating effect for images, similar to the cover‐flow view used in Apple’s iTunes application. The control can rotate images vertically or horizontally, and it can display a reflection below the image. 

C1.Silverlight.Chart.dll 

Description Contains the C1Chart control and its auxiliary classes. 

Main Classes • C1Chart: A full‐featured charting tool that supports several chart types, built‐in color palettes, and 

special effects including animations, zooming, and panning. 

• C1ChartLegend: A companion control used to display legends that describe the data series in a C1Chart control. 

C1.Silverlight.Gauge.dll 

Description Contains gauge controls that provide an intuitive and attractive way to display information graphically. These controls are often used in dashboard applications that display information summaries. 

Main Classes • C1RadialGauge: Provides a pointer that sweeps along an arc to indicate the current value. You can 

use the object model to add tickmarks, labels, and ranges to indicate special intervals (or customize the built‐in XAML definition to create completely customized gauges). 

• C1LinearGauge: Provides a linear indicator that moves along a straight path to indicate the current value. You can modify the appearance of the control using the object model or by modifying the built‐in XAML definition. 

C1.Silverlight.Maps.dll 

Description Contains the C1Maps control which displays rich geographical information from various sources, including Microsoft Live MapsTM and Google MapsTM. 

Main Classes • C1Maps: Shows maps with rich geographical information. The control supports zooming, panning, 

and mapping between screen and geographical coordinates. It also supports layers that allow you to superimpose elements to the maps. The layers support item virtualization and allow you to display static elements as well as elements that are attached to geographical locations. 

Page 9: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1.Silverlight.RichTextBox.dll 

Description Contains the C1RichTextBox control, a full‐fledged editor with a document‐based architecture similar to the one used in WPF. 

Main Classes • C1RichTextBox: Control used to view and edit C1Document documents. The control can import and 

export Html, and supports rich formatting including fonts, foreground and background colors, borders, paragraph alignment, images, hyperlinks, lists, arbitrary UIElement objects, and more. 

• C1Document: Class that represents documents as a hierarchical list of elements that represent document components such as paragraphs, lists, images, etc. The object model exposed by the C1Document object is similar to the one used in the WPF FixedDocument class and in the Html DOM. 

C1.Silverlight.RichTextBox.Toolbar.dll 

Description Contains the C1RichTextBoxToolbar control, a toolbar that attaches to a C1RichTextBox control and provides common formatting commands. The toolbar is packaged in a separate dll because many applications may choose to implement their own custom toolbars (or no toolbars at all) for the C1RichTextBox. These applications don’t have to deploy de standard toolbar. 

Main Classes • C1RichTextBoxToolbar: Toolbar control that attaches to a C1RichTextBox control and provides 

common formatting commands such as bold, italics, underline, font size, alignment, etc. 

C1.Silverlight.DataGrid.dll 

Description Contains the C1DataGrid control, a drop‐in replacement for the Microsoft DataGrid control with many additional features and integration with the controls in the C1.Silverlight.dll assembly. 

Main Classes • C1DataGrid: Grid control with an object model similar to the Microsoft DataGrid, but with additional 

features including (1) an Excel‐like filtering feature and (2) built‐in specialized editors for entering and editing numeric data. 

C1.Silverlight.Uploader.dll 

Description Contains the C1Uploader class, an object that allows uploading files and streams from Silverlight applications to the server. 

Page 10: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Main Classes • C1Uploader: Allows uploading files and streams from Silverlight applications to the server. 

C1Uploader provides a lot of flexibility over how files are uploaded. You can upload one file per request, split large files into multiple requests, or group many small files into a single request. 

C1.Silverlight.Zip.dll 

Description Contains classes that provide data compression services. In Silverlight applications, data compression is especially useful when transferring between client and server, and also when storing application data in isolated storage (which is limited to 100kb by default). 

Main Classes • C1ZipFile: Allows you to create, edit, and manage zip files and streams. The zip format is an open 

standard widely used in all kinds of applications. It provides a convenient way to package any number of files and streams into a single unit that can be easily and efficiently transmitted or stored. 

• C1ZStreamWriter: Writes data into a stream compressing it while writing. You can later de‐compress the data by reading it with a C1ZStreamReader. This class is useful in situations where you don’t need a full‐fledged zip file, only a single compressed stream.  

• C1ZStreamReader: Reads data from a compressed stream de‐compressing it while reading. The compressed stream is usually created with a C1ZStreamWriter. 

C1.Silverlight.Data.dll  

Description Contains classes that implement lightweight versions of the familiar classes in the System.Data namespace (DataSet, DataTable, etc). These classes allow you to build data‐centric Silverlight application using the same logic you have been using in ASP.NET and WinForms applications. In many cases, you will be able to reuse most of the server side code. 

Main Classes • DataSet: Analogous to the System.Data.DataSet class. This class represents an in‐memory cache of 

data, and provides methods for persisting the data as XML so it can be exchanged between client and server. The actual data is stored in DataTable objects, accessible through the Tables property. 

• DataTable: Analogous to the System.Data.DataTable class. This class contains columns that represent database fields and rows that represent the data items.  

Page 11: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Quick­Start This section will help you get started quickly with some of the main controls in the ComponentOne Studio for Silverlight. We will walk you through the process of creating a Silverlight application and then adding ComponentOne Studio controls to it. 

The application is called QuickStart. When finished, it will show several panels, each one demonstrating one control in the C1.Silverlight assembly. (The finished application in included the Samples folder.) 

In order to follow the tutorial, you will need Visual Studio 2008 and the latest Silverlight 2.0 SDK, which you can download from http://silverlight.net/GetStarted/. 

This section focuses on the ComponentOne controls only. For general help on getting started with Silverlight, we recommend the following references: 

1) http://www.silverlight.net The official Silverlight site, with many links to downloads, samples, tutorials, and more. 

2) http://silverlight.net/learn/tutorials.aspx Silverlight tutorials by Jesse Liberty. Topics covered include: Tutorial 0: The Roadmap Tutorial 1: Controls Tutorial 2: Data‐binding Tutorial 3: Styles and Templates Tutorial 4: Accessing data from a SQL database Tutorial 5: User Controls 

3) http://weblogs.asp.net/scottgu/pages/silverlight‐posts.aspx Scott Guthrie’s Silverlight Tips, Tricks, Tutorials and Links Page 

4) http://weblogs.asp.net/scottgu/archive/2008/02/22/first‐look‐at‐silverlight‐2.aspx An excellent eight‐part tutorial by Scott Guthrie, covering the following topics: Part 1: Creating "Hello World" with Silverlight 2 and VS 2008  Part 2: Using Layout Management  Part 3: Using Networking to Retrieve Data and Populate a DataGrid  Part 4: Using Style Elements to Better Encapsulate Look and Feel  Part 5: Using the ListBox and DataBinding to Display List Data  Part 6: Using User Controls to Implement Master/Details Scenarios  Part 7: Using Templates to Customize Control Look and Feel  Part 8: Creating a Digg Desktop Version of our Application using WPF 

5) http://blogs.msdn.com/corrinab/archive/2008/03/11/silverlight‐2‐control‐skins.aspx A practical discussion of skinning Silverlight controls and applications by Corrina Barber. 

Page 12: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Create a project that uses the C1.Silverlight controls In this first project, we will create an empty Silverlight solution that references the C1.Silverlight controls and provides a scrollable area that we will later populate with controls. 

The complete QuickStart project is included in the samples that ship with the ComponentOne Studio for Silverlight. 

The purpose of this application is to show how to instantiate the controls in ComponentOne Studio for Silverlight and how to use their basic functionality. The application does not demonstrate the advanced features in the controls. Those features are demonstrated in the other samples included with the package. 

Create a new Silverlight Project To get started with the ComponentOne Studio for Silverlight, start by opening Visual Studio 2008 and creating a new Silverlight project. The project will be called “QuickStart”: 

 

Visual Studio will prompt you for the type of hosting you want to use for the new project. We will use a Web Application Project and accept the default name, “QuickStartWeb”. 

Page 13: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

The solution will contain two projects: 

1. QuickStart: This is the Silverlight application proper. It will produce a “xap” file that gets downloaded to the client and runs inside the Silverlight plug‐in. 

2. QuickStartWeb: This is the host application. It runs on the server and provides support for the Silverlight application. 

Add references to the C1.Silverlight assemblies Next, select the QuickStart project in the Solution Explorer and add a reference to the ComponentOne Silverlight assemblies. This will allow you to add the ComponentOne controls to the page. 

The QuickStart application will demonstrate all the ComponentOne controls, so we will add references to all C1.Silverlight assemblies. Most applications will use only a few of the controls, and should reference only a few of the dlls. Here is a list of the assemblies we will use in the QuickStart application: 

• C1.Silverlight.dll 

• C1.Silverlight.Extended.dll 

• C1.Silverlight.RichTextBox.dll 

• C1.Silverlight.Uploader.dll 

• C1.Silverlight.Gauge.dll 

• C1.Silverlight.Chart.dll 

• C1.Silverlight.Maps.dll 

Note: The default install location for the ComponentOne assemblies is C:\Program Files\ComponentOne\Studio for Silverlight\bin\ 

At this point, the solution should look like this: 

Page 14: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

After adding the references, we can create ComponentOne Silverlight controls in C# code and also in Blend. If you create the controls in Blend, it will add a namespace statement to the XAML, similar to this: 

xmlns:C1_Silverlight="clr-namespace:C1.Silverlight;assembly=C1.Silverlight"

In most applications, you would let Blend create the namespace statements for you as needed. To simplify later steps of our QuickStart application, we will add all the namespaces at once (and use namespaces that are shorter than the default ones created by Blend): 

<UserControl x:Class="QuickStart.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c1="clr-namespace:C1.Silverlight;assembly=C1.Silverlight" xmlns:c1x="clr-namespace:C1.Silverlight.Extended;assembly=C1.Silverlight.Extended" xmlns:c1t="clr-namespace:C1.Silverlight.RichTextBox;assembly=C1.Silverlight.RichTextBox" xmlns:c1g="clr-namespace:C1.Silverlight.Gauge;assembly=C1.Silverlight.Gauge" xmlns:c1m="clr-namespace:C1.Silverlight.Maps;assembly=C1.Silverlight.Maps" xmlns:c1c="clr-namespace:C1.Silverlight.Chart;assembly=C1.Silverlight.Chart" >

Once these statements are added to the page, you can use the specified prefixes to create the objects in each assembly. For example: 

<StackPanel> <c1:C1ComboBox /> <!-- C1.Silverlight.dll --> <c1x:C1Book /> <!-- C1.Silverlight.Extended.dll --> <c1m:C1Maps /> <!-- C1.Silverlight.Maps.dll --> </StackPanel>

Create the initial page layout Now we have an application that consists of a blank page. To start adding content to the page, we have three options: 

1. Code: Open the Page.xaml.cs file and create the application using code. This is an easy way to quickly create test applications, but is not normally used for real Silverlight development. 

Page 15: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

2. Visual Studio: Use the Visual Studio designer to edit the Page.xaml file by typing some XAML code and seeing the results in the preview window. This is possible but not practical. The Visual Studio designer is slow and limited, and is suited only for minor modifications to the XAML code. 

3. Expression Blend: Create the page using Microsoft Expression Blend. This is the preferred way of creating Silverlight and WPF applications. 

We will choose option 3. Right‐click the Page.xaml file in the Solution Explorer and select “Open in Expression Blend”. This will bring up the project in Blend. You can design the page, adding controls and setting their properties. When you are happy with the design, closing Blend will take you back to Visual Studio where you can add code and debug the application. 

Because the project contains references to the ComponentOne Silverlight assemblies, the ComponentOne controls will be available from within Blend. 

We want to create a scrollable area where we will later add several C1.Silverlight controls to experiment with. If you are familiar with Blend, you can use the control palette and add a ScrollViewer to the page, and then a StackPanel within the ScrollViewer. This is much easier to do than to describe step by step, so we’ll take a shortcut here and provide the XAML code (you can paste this into the Blend XAML editor): 

<Grid x:Name="LayoutRoot" Background="White"> <ScrollViewer> <StackPanel x:Name="_mainPanel" Margin="6" > <TextBlock Text="Content will go here" /> </StackPanel> </ScrollViewer> </Grid>

You can now close Blend and run the application from within Visual Studio. It’s not very interesting at this point, but if you do run it, notice how the Silverlight plug‐in automatically resizes to fill the page. As the plug‐in resizes, the content within it also resizes to fill it. This is the default behavior when you don’t specify the panel dimensions explicitly. 

Notice that we assigned a name to the StackPanel element. Any element that is given a name can be referred to from code, if desired. Otherwise the elements are usually left unnamed. 

Create Styles We will create many similar elements, one for each control type. Instead of formatting each one independently, let’s create some styles that can be applied to all elements. This will save some work and more importantly, will make it easier to modify the appearance of the application later if we decide to do that. 

Here’s the XAML that defines the styles: 

Page 16: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<UserControl x:Class="QuickStart.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" …> <UserControl.Resources> <Style x:Key="ControlBorder" TargetType="Border"> <Setter Property="BorderThickness" Value="3" /> <Setter Property="Background" Value="#FFC2F5CB" /> <Setter Property="BorderBrush" Value="#FF257004" /> <Setter Property="CornerRadius" Value="6" /> <Setter Property="Margin" Value="5" /> <Setter Property="Padding" Value="5" /> </Style> <Style x:Key="ControlTitle" TargetType="TextBlock"> <Setter Property="FontSize" Value="14" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="FontFamily" Value="Courier New" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="Foreground" Value="#FF1F6900" /> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> …

Note that Silverlight (and WPF) Styles are just collections of property names and values. Each member of the collection specifies a value to be applied to a property. They don’t necessarily have to be visual properties at all. 

To see what the styles we just created look like, modify the content of the _mainPanel element as follows: 

<StackPanel x:Name="_mainPanel" Margin="6" > <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="Control Name" Style="{StaticResource ControlTitle}" /> <TextBox Width="200"/> </StackPanel> </Border> </StackPanel>

You can see the effect of the changes right in Visual Studio: 

 

Page 17: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1.Silverlight.dll The C1.Silverlight.dll is the core assembly in the ComponentOne Studio for Silverlight. It implements all the basic controls that are necessary in most applications but are not part of Silverlight itself. 

C1ComboBox In this step, we will add some C1ComboBox controls to the application.  

To do this, open the page in Blend and click the “Asset Library” button (last item in the toolbox, highlighted in the image below). Then select the “Custom Controls” tab. Notice that the C1.Silverlight controls appear on the list. That happens because the project has a reference to the C1.Silverlight.dll assembly. 

 

Click the C1ComboBox control on the list. This will add the C1ComboBox to the toolbox, right above the “Asset Library” button. 

Now, double‐click the _mainPanel item in the “Objects and Timeline” pane to make it the default container. Then, double‐click the C1ComboBox in the toolbox. This will add a new C1ComboBox to the page, as a child of the _mainPanel. 

Rather than repeat these steps for the other elements we want to add to the page, we’ll just give you the revised section of XAML that you can paste directly into Blend: 

Page 18: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<StackPanel x:Name="_mainPanel" Margin="6" > <!-- C1ComboBox --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1ComboBox" Style="{StaticResource ControlTitle}" /> <c1:C1ComboBox x:Name="_cmb1" Width="200" /> <c1:C1ComboBox x:Name="_cmb2" Width="200" /> </StackPanel> </Border> </StackPanel>

We added a TextBlock element to work as a header and two C1ComboBox elements named _cmb1 and _cmb2. The names are important because we will reference these controls from code. 

We will now add some code to populate the combo boxes. Close Blend and return to Visual Studio. Double‐click the Page.xaml.cs file and add the following using statements: 

using System.Diagnostics; using System.Reflection; using C1.Silverlight; using C1.Silverlight.RichTextBox; using C1.Silverlight.Extended; using C1.Silverlight.Uploader; using C1.Silverlight.Maps; using C1.Silverlight.Chart; using SamplesCommon;

Then modify the page constructor as follows: 

public Page() { InitializeComponent(); // initialize the C1ComboBoxes _cmb1.IsEditable = false; _cmb1.SelectedItemChanged += _cmb_SelectedItemChanged; PopulateCombo(_cmb1); _cmb2.IsEditable = true; _cmb2.SelectedItemChanged += _cmb_SelectedItemChanged; PopulateCombo(_cmb2); }

And add the event handler and PopulateCombo method right below the constructor: 

Page 19: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void _cmb_SelectedItemChanged(object sender, PropertyChangedEventArgs<object> e) { C1ComboBox cmb = sender as C1ComboBox; Debug.WriteLine("SelectedItemChanged on {0}: new value is '{1}'", cmb.Name, cmb.Text); } void PopulateCombo(C1ComboBox cmb) { foreach (PropertyInfo pi in cmb.GetType().GetProperties()) cmb.Items.Add(pi.Name); }

The code is straightforward. For each combo, it simply adds some strings to the Items collection and attaches a handler to the SelectedItemChanged event. 

Run the project to see the C1ComboBox in action. Notice how both combos provide auto‐completion, but only the bottom one allows you to enter items that are not on the list. Check the Visual Studio output window to see when the SelectedItemChanged event fires. 

This is the simplest way to populate and use C1ComboBox controls. But you can do a lot more with the C1ComboBox, by using data templates and binding. We will cover these more advanced topics in later sections. 

C1MaskedTextBox In this step, we will add some C1MaskedTextBox controls to the application. The C1MaskedTextBox allows you to display and edit formatted string values. The Mask property is used to specify which type of character is allowed at each position. 

To add the new controls, add the following code to the Page.xaml file, right after the last Border element: 

<!-- C1MaskedTextBox --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1MaskedTextBox" Style="{StaticResource ControlTitle}" /> <C1:C1MaskedTextBox Width="200" Watermark="Phone Number" Mask="(999) 000-0000"/> <C1:C1MaskedTextBox Width="200" Watermark="Short Date" Mask="00/00/0000"/> <C1:C1MaskedTextBox Width="200" Watermark="Social Security Number" Mask="000-00-0000"/> </StackPanel> </Border>

That’s all we need to demonstrate the C1MaskedTextBox. Notice the following: 

• The C1MaskedTextBox supports a Watermark property. This makes it easy to prompt the user for the type of information that is expected. 

Page 20: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

• The Mask property uses the same syntax as the MaskedTextBox control in WinForms. This makes it easier to re‐use masks across applications and platforms. 

• Formatting this new block was easy; we simply re‐used the styles defined earlier. A designer could take this XAML file and modify the styles very easily, without touching the controls themselves. 

If you run the application now and type into the C1MaskedTextBox controls, you will notice that only valid characters are accepted at each position. 

The Text property of the C1MaskedTextBox exposes the control’s full content. The Value property exposes only the values typed by the user, excluding template characters specified in the Mask. For example, if the Mask property is set to “99‐99” and the control contains the string “55‐55”, the Text property would return “55‐55” and the Value property would return “5555”. 

C1NumericBox In this step, we will add some C1NumericBox controls to the application. The C1NumericBox allows you to display and edit formatted numeric values. 

To add the new controls, add the following code to the Page.xaml file, right after the last Border element: 

<!-- C1NumericBox --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1NumericBox" Style="{StaticResource ControlTitle}" /> <C1:C1NumericBox Width="200" Format="F2" Value="3.1416" /> <C1:C1NumericBox Width="200" Format="#,##0.00" Increment="100" MinimumValue="0" MaximumValue="10000" Value="3.1416" /> <C1:C1NumericBox Width="200" Format="F2" Value="3.1416" ShowButtons="False" AllowNull="True" Watermark="No value specified" /> </StackPanel> </Border>

The main properties in the C1NumericBox control are Value and Format. 

The Value property contains the value being edited, represented as a double. The control fires the ValueChanged event when the value of this property changes. 

The Format property is used to format the value for display in the control. It specifies the number of decimal places and whether thousand separators should be used. The Format property is specified using the same format strings used by the .NET framework. For example, “F2” displays the value as a floating point number with two decimals, and “#,##0.0000” displays the value with a thousand separator and four decimal places. Note that not all formats are supported (for example, percentages, hexadecimals, 

Page 21: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

scientific notation and multi‐part formats). If you try to use an unsupported format, the control will throw an exception. 

Other useful properties include: 

Increment: Determines the amount added or removed from the value when the user clicks the up/down buttons in the control or when the up/down keys are pressed. 

MaximumValue/MinimumValue: Constrains the value to a specified range. 

ShowButtons: Determines whether the up/down buttons should be displayed. 

AllowNull: Determines whether the control should allow the user to clear the entire content of the control. In this case, the Value property is set to double.NaN, which indicates the value is null. 

C1Menu The C1Menu is a control that allows hierarchical organization of elements associated with event handlers. The C1Menu control is similar to the Menu control in WPF. You can create and populate it entirely in XAML, and that is how we will get started. 

Add the following code to the Page.xaml file, right after the last Border element: 

<!-- C1Menu --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1Menu" Style="{StaticResource ControlTitle}" /> <C1:C1Menu x:Name="_menu" Width="Auto" Height="40" > <C1:C1MenuItem Header="File" > <C1:C1MenuItem Header="New" > <C1:C1MenuItem Header="Project" /> <C1:C1MenuItem Header="File" /> </C1:C1MenuItem> <C1:C1MenuItem Header="Open" /> </C1:C1MenuItem> <C1:C1MenuItem Header="Edit" > <C1:C1MenuItem Header="Cut" /> <C1:C1MenuItem Header="Copy" /> <C1:C1MenuItem Header="Test" /> </C1:C1MenuItem> <C1:C1MenuItem Header="Window" > <C1:C1MenuItem Header="Floating" IsCheckable="True" /> <C1:C1MenuItem Header="Dockable" IsCheckable="True" /> </C1:C1MenuItem> </C1:C1Menu> </StackPanel> </Border>

We just added a new C1Menu control to the page, with three first‐level menu items and some submenus. 

Page 22: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

If you run the sample now, you will notice that the new control only shows the top‐level menu items and allows you to open its associated submenus by clicking on them. It also supports keyboard navigation. 

There are some practical applications where you won’t be able to create the whole C1Menu at design time. For example, many applications have a “Recent Files” submenu, where the files that were recently open are listed; that data is not available at design time. To populate a C1Menu using code, open the Page.xaml.cs file and add the following to the page constructor: 

public Page() { InitializeComponent(); // no changes here… // initialize the C1Menu InitializeMenu(); }

Next, add the implementation of the InitializeMenu method: 

private void InitializeMenu() { // remove items that were added at design time _menu.Items.Clear(); // create File menu C1MenuItem fileMenu = new C1MenuItem(); fileMenu.Header = "File"; CreateSubMenu("New", fileMenu); CreateSubMenu("Open", fileMenu); CreateSubMenu("Add", fileMenu); CreateSubMenu("Close", fileMenu); CreateSubMenu("Save", fileMenu); CreateSubMenu("Save As", fileMenu); CreateSubMenu("Save All", fileMenu); // create Window menu when the page loads C1MenuItem windowMenu = new C1MenuItem(); windowMenu.Header = "Window"; windowMenu.Loaded += windowMenuLoaded; // populate main menu _menu.Items.Add(fileMenu); _menu.Items.Add(windowMenu); }

Page 23: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

private void CreateSubMenu(string header, C1MenuItem parent) { C1MenuItem menuItem = new C1MenuItem(); menuItem.Header = header; parent.Items.Add(menuItem); }

These methods create two first‐level menus: File and Window, then add some submenus to the File menu through its Items collection. 

Instead of populating the Window menu directly, the code above hooks up a handler to the Loaded event. This illustrates how you can populate menus in response to events (such as when a file is opened for example). 

void windowMenuLoaded(object sender, RoutedEventArgs e) { C1MenuItem windowMenu = sender as C1MenuItem; windowMenu.ItemsSource = GetSubmenus(); } private IList GetSubmenus() { List<object> menuList = new List<object>(10); for (int i = 0; i < 10; i++) { C1MenuItem menuItem = new C1MenuItem(); menuItem.Header = "Submenu " + i; menuList.Add(menuItem); } return menuList; }

This implementation creates some dummy submenus in a for loop. In a real application, the GetSubmenus method would retrieve a list of recently used files from isolated storage or from the server. 

You can now run the application to see the C1Menu in action. 

Page 24: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

C1Window The C1Window control shows content in a floating window within the Silverlight plug‐in. 

C1Window objects are not children of any elements on the page. Because of this, they are defined in separate XAML files whose root element is a C1Window object. 

To create a new C1Window object, right‐click the project in the Visual Studio Project Explorer and select the "Add | New Item…" option. Next, pick the "Silverlight User Control" option and name the new control “MyWindow”. 

Open the MyWindow.xaml file and make sure it contains this XAML: 

<c1:C1Window x:Class="QuickStart.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c1="clr-namespace:C1.Silverlight;assembly=C1.Silverlight" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <TextBlock Text="We can put any control inside the window" /> </Grid> </c1:C1Window>

This is a simple window; it contains only a Grid and a TextBlock. But you can edit this file in Blend and add any elements you want. Creating and maintaining C1Window objects is very easy. 

Next, modify the MyWindow.xaml.cs file to make the MyWindow class inherit from C1Window: 

Page 25: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

public partial class MyWindow : C1Window { public MyWindow() { InitializeComponent(); } }

Now that the C1Window object is ready, we will go back to the main project and add two buttons to the main page. Clicking the buttons will show the C1Window, either as a modeless window or as a dialog. 

Here is the code that needs to be added to the Page.xaml file, below the last Border element: 

<!-- C1Window --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1Window" Style="{StaticResource ControlTitle}" /> <Button Click="OpenWindow" Width="300" Content="Open window (modeless)" /> <Button Click="ShowDialog" Width="300" Content="Open window (modal)" /> </StackPanel> </Border>

The XAML above specifies event handlers for the Click event of each button. The event handlers must be defined in the Page.xaml.cs file: 

void OpenWindow(object sender, RoutedEventArgs e) { var window = new MyWindow(); window.CenterOnScreen(); window.Show(); } void ShowDialog(object sender, RoutedEventArgs e) { var window = new MyWindow(); window.CenterOnScreen(); window.ShowModal(); }

Run the project and click the button to see the C1Window. You can drag the window by its caption bar as well as maximize, restore, and close it using the system buttons. 

You can open as many modeless windows as you want, but only one modal window at a time. 

C1MessageBox The C1MessageBox class is similar to the MessageBox classes in WPF and WinForms. It provides an easy way to display a message to the user and optionally ask a simple question. 

Page 26: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The C1MessageBox class is a handy time‐saver so you don't have to create C1Window objects for performing this simple task. 

To see how it works, add the following XAML below the last Border element in the Page.xaml file: 

<!-- C1MessageBox --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1MessageBox" Style="{StaticResource ControlTitle}" /> <Button Click="ShowMessageBox" Width="300" Content="Show C1MessageBox" /> </StackPanel> </Border>

And add the following code to the Page.xaml.cs file: 

void ShowMessageBox(object sender, RoutedEventArgs e) { C1MessageBox.Show("To be, or not to be?", "The question", C1MessageBoxButton.YesNoCancel, C1MessageBoxIcon.Question, MessageBoxResult); } void MessageBoxResult(C1MessageBoxResult result) { switch (result) { case C1MessageBoxResult.Yes: C1MessageBox.Show("You are!"); break; case C1MessageBoxResult.No: C1MessageBox.Show("You are not!"); break; case C1MessageBoxResult.Cancel: C1MessageBox.Show("OK, I won't ask again ;-)"); break; } }

Notice that the first call to C1MessageBox uses all the available parameters. It’s possible to customize the message, title, buttons, and the icon to be displayed. There are overloads available that allow you to omit most of these parameters. 

Notice also that the Show method is asynchronous. Instead of waiting until the message box is dismissed and then returning a value, the method calls a delegate that is supposed to handle the result. In this example, the delegate is the MessageBoxResult method listed above. 

C1TreeView We will now add a C1TreeView control to the application. The C1TreeView control is similar to the TreeView control in WPF. 

Page 27: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

You can create and populate it entirely in XAML, and that is how we will get started. 

Here is the XAML that you should add to the Page.xaml file, right after the last Border element: 

<!-- C1TreeView --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1TreeView" Style="{StaticResource ControlTitle}" /> <c1:C1TreeView x:Name="_tv" Width="400" Height="300" > <c1:C1TreeViewItem Header="Item 1" > <c1:C1TreeViewItem Header="Item 1.1" /> <c1:C1TreeViewItem Header="Item 1.2" /> </c1:C1TreeViewItem> <c1:C1TreeViewItem Header="Item 2" > <c1:C1TreeViewItem Header="Item 2.1" /> <c1:C1TreeViewItem Header="Item 2.2" /> <c1:C1TreeViewItem Header="Last Item" /> </c1:C1TreeViewItem> </c1:C1TreeView> </StackPanel> </Border>

This is all it takes to add a new C1TreeView control to the page, complete with two top‐level nodes and some child nodes. 

If you run the sample now, you will notice that the new control allows you to collapse and expand nodes by clicking on them as you would expect. It also supports the keyboard for navigation, expanding and collapsing nodes, and auto‐searching. 

In most practical applications, you won’t be able to populate the C1TreeView at design time. The control is normally used to display hierarchical data that is not available at design time. To show how you can populate a C1TreeView using code, open the Page.xaml.cs file and add the following to the page constructor: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1TreeView InitializeTreeView(); }

Next, add the implementation of the InitializeTreeView method: 

Page 28: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void InitializeTreeView() { // remove items that were added at design time _tv.Items.Clear(); // scan every type in the assembly foreach (Type t in _tv.GetType().Assembly.GetTypes()) { if (t.IsPublic && !t.IsSpecialName && !t.IsAbstract) { // add node for this type C1TreeViewItem node = new C1TreeViewItem(); node.Header = t.Name; node.FontWeight = FontWeights.Bold; node.Tag = type; _tv.Items.Add(node); // add subnodes for properties, events, and methods node.Items.Add(CreateMemberNode("Properties", t, MemberTypes.Property)); node.Items.Add(CreateMemberNode("Events", t, MemberTypes.Event)); node.Items.Add(CreateMemberNode("Methods", t, MemberTypes.Method)); } } } C1TreeViewItem CreateMemberNode(string header, Type type, MemberTypes memberTypes) { C1TreeViewItem node = new C1TreeViewItem(); node.Header = header; return node; }

This first version of the code enumerates the types in the C1.Silverlight.dll assembly and adds one node for each type. Each of these nodes has three child nodes that will contain the properties, events, and methods declared by the type. 

The code does not fill the sub‐nodes yet, so if you run the sample you will see all the types but none of their members. Instead of fully populating each node when the application starts, we will implement a technique called “delayed loading”, where nodes are populated on demand, when the user expands them. This allows the application to load faster and use resources more efficiently (maybe the user is interested in one type only, so we will never even load the information for the types the user is not interested in). 

To implement the delayed loading nodes, replace the CreateMemberNode code above with this implementation: 

Page 29: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1TreeViewItem CreateMemberNode(string header, MemberTypes memberTypes) { // create the node C1TreeViewItem node = new C1TreeViewItem(); node.Header = header; node.Foreground = new SolidColorBrush(Colors.DarkGray); // hook up event hander to populate the node before expanding it node.Expanding += node_Expanding; // save information needed to populate the node node.Tag = memberTypes; // add a dummy node so this node can be expanded node.Items.Add(new C1TreeViewItem()); node.IsExpanded = false; // done return node; }

This implementation hooks up an event hander for the Expanding event, so we can populate the node when the user tries to expand it. We also save the information we will need to populate the node in the Tag property. Finally, we add a dummy child node so the user will be able to expand this node and trigger the Expanding event that will populate the node. 

Note that instead of using the Tag property, we could also have derived a custom class from C1TreeViewNode and built all the delay‐load logic into that class. This would be a more elegant approach, but unfortunately Silverlight doesn’t support template inheritance. If you derive a class from a class that has a template (such as Button or C1TreeViewNode), the template is not inherited, and you have to provide a template yourself or your derived class will be just an empty control. This seems to be a bug in Silverlight; hopefully it will be corrected before the final release. 

Finally, here is the code that actually populates the node. It only gets called once for each node, when the user expands the node for the first time: 

Page 30: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void node_Expanding(object sender, RoutedEventArgs e) { // get the node that fired the event C1TreeViewItem node = sender as C1TreeViewItem; // unhook event handler (we'll populate the node and be done with it) node.Expanding -= node_Expanding; // remove dummy node node.Items.Clear(); // populate the node Type type = (Type)node.Parent.Tag; MemberTypes memberTypes = (MemberTypes)node.Tag; BindingFlags bf = BindingFlags.Public | BindingFlags.Instance; foreach (MemberInfo mi in type.GetMembers(bf)) { if (mi.MemberType == memberTypes) { if (!mi.Name.StartsWith("get_") && !mi.Name.StartsWith("set_")) { C1TreeViewItem item = new C1TreeViewItem(); item.Header = mi.Name; item.FontSize = 12; node.Items.Add(item); } } } }

Run the application to see the C1TreeView in action. You will notice that it loads quickly, since the child nodes are not created until you expand an object node to see its properties, methods, or events. When each node is expanded the first time, you may notice a short delay as the node is populated. Expanding and collapsing the node after that happens instantaneously. 

Notice that you can use the keyboard to navigate the tree and to search for items. You can also use the AllowDragDrop property to enable automatic drag‐drop support within the tree, so users can drag items into new positions. The image below shows the C1TreeView control during a drag‐drop operation. The item being dragged is shown in its selected state, and the exact drop location is highlighted with a horizontal bar. 

Page 31: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

This sample barely scratches the surface of the C1TreeView control. The distribution package includes more specific samples that show advanced features. 

Every node header is a ContentControl, which means you can easily add elements such as images and checkboxes to the node headers. 

You can use the ItemsSource property to bind the control to your data. You can use DataTemplates to define the visual representation of each item. And you can use template selectors to create different visuals for each type of element on the tree. For example, you could have parent nodes display product categories with images and complete descriptions, and subnodes that display products with prices and stock availability. 

C1HyperPanel The C1HyperPanel is a similar to a StackPanel, except it applies a dynamic zoom effect to elements that are closer to the mouse. 

To demonstrate the C1HyperPanel, we will define two instances of it in the Page.xaml file. Here is the code that needs to be pasted below the last Border element: 

<!-- C1HyperPanel --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1HyperPanel" Style="{StaticResource ControlTitle}" /> <C1:C1HyperPanel x:Name="_hp1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="8" Distribution="0.4" /> <C1:C1HyperPanel x:Name="_hp2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="8" Distribution="0.1" MinElementScale="0.2" ApplyOpacity="False" /> </StackPanel> </Border>

This code creates two empty panels named _hp1 and _hp2, and initializes their main properties: 

Distribution is a value between zero and one that determines how much zooming should be applied when the mouse moves over the panel. Smaller values cause a more pronounced zoom factor. 

Page 32: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

MinElementScale determines the minimum scale factor that is applied to elements that are far from the mouse. When Distribution is set to a small value, you may want to set this property to a value greater than zero to prevent elements from being scaled down to zero. 

ApplyOpacity determines whether elements away from the mouse should also be made semi‐transparent, adding to the distance effect. 

The values used here cause the top panel to apply a moderate zoom factor. The second panel applies a more pronounced zoom factor, and prevents elements from becoming too small by setting the MinElementScale property. 

Instead of populating the panels in the XAML file, we will do it in code. Open the Page.xaml.cs file and add this code to the page constructor: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1HyperPanels FillHyperPanel(_hp1); FillHyperPanel(_hp2); }

Next, add the FillHyperPanel method below the page constructor: 

Page 33: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void FillHyperPanel(C1HyperPanel hp) { for (double p = 0; p <= 1; p+= 0.05) { // create Color byte red = (byte)(255 * p); byte green = (byte)((red + 255/3) % 255); byte blue = (byte)((green + 255 / 3) % 255); Color c = Color.FromArgb(255, red, green, blue); // create Rectangle element Rectangle r = new Rectangle(); r.Fill = new SolidColorBrush(c); r.Width = r.Height = 30; r.Margin = new Thickness(2); r.RadiusX = r.RadiusY = 4; r.Stroke = new SolidColorBrush(Colors.Black); r.StrokeThickness = 1; r.VerticalAlignment = VerticalAlignment.Bottom; // add rectangle to C1HyperPanel hp.Children.Add(r); } }

Run the project and scroll to the bottom of the main panel. Move the mouse over the two C1HyperPanels to see the dynamic zooming effect. Note that the rectangles are aligned along the bottom of the panels, honoring the setting of their VerticalAlignment property. The effect is similar to the one seen in the Apple Macintosh toolbar. 

 

You can achieve interesting variations by modifying the value of the Distribution and MinElementScale properties. 

Note that you can add any UIElement object to a C1HyperPanel, including any type of control. You can use the C1HyperPanel as a toolbar for example, or as a stack panel that can display a large number of elements without resorting to scrollbars.  

C1DragDropManager The C1DragDropManager is a class that provides drag‐ drop services on behalf of other elements. It is not a control and has no visual representation at design time. 

Page 34: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The C1DragDropManager class follows the patterns found in the WinForms drag‐drop implementation. It provides a DoDragDrop method that is called to initiate the drag‐drop operations, and fires events that allow you to customize the whole process (DragStart, DragEnter, DragOver, DragLeave, DragDrop). 

The event parameters provide information on what item is being dragged (e.DragSource) and where it is about to be dropped (e.DropTarget). The event handlers are responsible for checking this information and setting the value of the e.Effect parameter to indicate whether the operation is valid or not. The handler for the DragDrop event is responsible for actually moving or copying the source element to the target location. 

The C1DragDropManager class also provides two helper methods that simplify the whole process. The methods are called RegisterDragSource and RegisterDropTarget. They provide a simple generic implementation that handles most common drag‐drop scenarios with very little code. Once you have registered elements as sources and targets with these methods, the C1DragDropManager will monitor the mouse to automatically initiate and manage the drag‐drop operation. In this case, all you have to do is handle the DragDrop event to perform the move or copy operation. 

To demonstrate the C1DragDropManager, we will add a Grid with some child elements to the page. Later, we will use a C1DragDropManager to allow users to drag elements from one grid cell to another. 

Here is the code that should be added to the Page.xaml file, below the last Border element: 

<!-- C1DragDropManager (new in M3) --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1DragDropManager (NEW)" Style="{StaticResource ControlTitle}" /> <Grid x:Name="_ddGrid" Background="LightGray" ShowGridLines="True" Width="400" Height="300"> <Grid.RowDefinitions> <RowDefinition/><RowDefinition/> <RowDefinition/><RowDefinition/> <RowDefinition/><RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/><ColumnDefinition/> <ColumnDefinition/><ColumnDefinition/> <ColumnDefinition/><ColumnDefinition/> </Grid.ColumnDefinitions> <TextBlock Text="Drag Me" Grid.Row="1" Grid.Column="2" /> <TextBlock Text="Or Me" Grid.Row="3" Grid.Column="4" /> <Rectangle Fill="Red" Grid.Row="2" Grid.Column="0"/> <Rectangle Fill="Blue" Grid.Row="0" Grid.Column="4"/> </Grid> </StackPanel> </Border>

Next, open the Page.xaml.cs file and add this code to the page constructor: 

Page 35: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1DragDropManager C1DragDropManager dd = new C1DragDropManager(); dd.RegisterDropTarget(_ddGrid, true); foreach (UIElement e in _ddGrid.Children) { dd.RegisterDragSource(e, DragDropEffect.Move, ModifierKeys.None); } dd.DragDrop += dd_DragDrop; }

The code starts by instantiating a new instance of a C1DragDropManager. Then it calls the RegisterDropTarget method to indicate that the grid should act as a drop target by default. It also calls the RegisterDragSource method to indicate that users should be allowed to drag the elements in the grid. Finally, the code attaches an event handler to the DragDrop event so the application can receive a notification and move the element being dragged into its new position. 

Here is the code for the DragDrop event handler: 

void dd_DragDrop(object source, DragDropEventArgs e) { // get mouse position Point pMouse = e.GetPosition(_ddGrid); // translate into grid row/col coordinates int row, col; Point pGrid = new Point(0, 0); for (row = 0; row < _ddGrid.RowDefinitions.Count; row++) { pGrid.Y += _ddGrid.RowDefinitions[row].ActualHeight; if (pGrid.Y > pMouse.Y) break; } for (col = 0; col < _ddGrid.ColumnDefinitions.Count; col++) { pGrid.X += _ddGrid.ColumnDefinitions[col].ActualWidth; if (pGrid.X > pMouse.X) break; } // move the element to the new position e.DragSource.SetValue(Grid.RowProperty, row); e.DragSource.SetValue(Grid.ColumnProperty, col); }

Page 36: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The event handler starts by converting the mouse coordinates into row/column values. Then it uses the SetValue method to update the Grid.RowProperty and Grid.ColumnProperty values on the element that was dragged. Similar logic could be used to drag elements within other types of panel or list‐type controls, or from one panel to another. 

If you run the project now, you should be able to drag the Rectangle and TextBlock objects from one grid cell to another. The image below shows the drag process in action. The extra border around the first TextBlock shows that it is the element being dragged, and the transparent rectangle follows the mouse and shows where the element will be dropped. 

 

C1.Silverlight.Extended.dll The C1.Silverlight.Extended.dll provides additional controls that leverage Silverlight to display information in visually appealing, unusual ways. The controls are less common than the ones found in the core assembly (C1.Silverlight.dll). 

C1Expander The C1Expander control has a header and a single content. The content can be expanded and collapsed by clicking on the header. The C1Expander control is similar to the WPF Expander class. 

Here is the XAML that should be added to the Page.xaml file below the last Border element: 

Page 37: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<!-- C1Expander --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1Expander" Style="{StaticResource ControlTitle}" /> <!-- simplest expander, show content below header --> <c1x:C1Expander Margin="2" HeaderFontWeight="Bold" Header="Click me" Content="Collapsible Content" /> <!-- show content to the right of the header --> <c1x:C1Expander Margin="2" ExpandDirection="Right" HeaderFontWeight="Bold" Header="Click me" Content="Collapsible Content" /> <!-- show content above header, add red border around the header --> <c1x:C1Expander Margin="2" ExpandDirection="Up" Content="Collapsible content"> <c1x:C1Expander.Header> <Border BorderThickness="2" BorderBrush="Red"> <TextBlock Text="Click Me!"/> </Border> </c1x:C1Expander.Header> </c1x:C1Expander> <!-- show content to the left of the header --> <c1x:C1Expander Margin="2" ExpandDirection="Left" HeaderFontWeight="Bold" Header="Click Me!" Content="Collapsible Content" /> </StackPanel> </Border>

The C1Expander can be configured to expand in four directions using the ExpandDirection property. The default ExpandDirection is Down, so we don’t need to specify it in the first C1Expander. 

C1Expander is a C1HeaderedContentControl, so its Font and Content properties work exactly like their counterparts in a ContentControl. 

C1Accordion The C1Accordion is an ItemsControl where each item is shown inside a C1Expander control and only one is allowed to be expanded at a time. 

To see a C1Accordion in action, add the following XAML to the Page.xaml file, below the last Border element: 

Page 38: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<!-- C1Accordion --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Accordion" Style="{StaticResource ControlTitle}" /> <StackPanel Orientation="Horizontal"> <!-- traditional accordion (items expand below headers) --> <c1x:C1Accordion Height="200" Fill="True" Margin="10" AllowCollapseAll="False"> <c1x:C1Expander Header="Beverages" Content="Tea, Coffee, Milk"/> <c1x:C1Expander Header="Dairy" Content="Milk, Cheese, Cream"/> <c1x:C1Expander Header="Desserts" Content="Pies, Fruit, Ice-cream"/> </c1x:C1Accordion> <!-- horizontal data-bound accordion --> <c1x:C1Accordion x:Name="templatedAccordion" Margin="10" ExpandDirection="Right"> <c1x:C1Accordion.ItemTemplate> <DataTemplate> <c1x:C1Expander <!-- root must be a C1Expander --> Header="{Binding Key}" Content="{Binding Value}" /> </DataTemplate> </c1x:C1Accordion.ItemTemplate> </c1x:C1Accordion> </StackPanel> </StackPanel> </Border>

The first C1Accordion in the code shows how items can be added to the C1Accordion in XAML. Notice how AllowCollapseAll is set to False. This means that one C1Expander will be expanded at all times. If we didn't set that property, the user would be able to collapse all items. 

Also notice that we set the Fill property set to True. This causes the C1Accordion to fill all the space available. If we didn't set this property, the C1Accordion would automatically resize to fit its content. 

The second C1Accordion demonstrates two additional properties, ExpandDirection and ItemTemplate. 

ExpandDirection indicates the direction where the C1Expander items expand. The default is "Down", which causes content to be displayed below each header. Other options are the same as in the C1Expander control. In this case, we are setting the property to "Right", causing items to expand in the horizontal direction. 

Page 39: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Because C1Accordion inherits from ItemsControl, you can add objects of any data type to its Items collection and use a DataTemplate to create a visual representation of the items (in this case, the root of the DataTemplate must be a C1Expander object). The XAML above creates C1Expander objects and binds the Header and Content properties of each element to properties called "Key" and "Value". 

In order to populate the second C1Accordion, add the following code to the page's constructor in the Page.xaml.cs file: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1Accordion PopulateAccordion(); } void PopulateAccordion() { for (int i = 1; i <= 4; i++) { string key = string.Format("Key {0}", i); string value = string.Format("This is value {0}", i); _templatedAccordion.Items.Add( new KeyValuePair<string, string>(key, value)); } }

If you run the project now, you will see the second accordion populated by KeyValuePair instances. 

 

C1ImageRotator The C1ImageRotator control provides a pseudo 3D effect used for displaying images with a perspective transformation and optional image reflection, similar to the effect seen in Apple’s iTunes application. 

Page 40: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Note that the C1ImageRotator control can only display images, not arbitrary UIElement objects. This limitation is imposed by the lack of a VisualBrush class in Silverlight (like the one in WPF). 

Also note that the C1ImageRotator will size itself automatically to fit the image and angle it is displaying. As you rotate a 200 pixel‐wide image from zero to 60 degrees, the control width will decrease from 200 to 100 pixels. If you rotate it to 90 degrees, the width will become zero. This make it easy to fill a StackPanel with C1ImageRotators set to arbitrary angles and have them fill up the stack with no empty gaps between them. Setting the control’s Width and Height properties to explicit values disables this auto‐sizing behavior. 

To demonstrate the C1ImageRotator, start by adding some images to the application. Right‐click the QuickStart project node in the project explorer and select the “Add | Existing Item” option. Then select five images and add them to the project. Name the images “cover1.jpg”, “cover2.jpg”, and so on until “cover5.jpg”. Select the newly added images and make sure the BuildAction property is set to “Resource”. The image below shows what the project should look like after you add the images: 

 

Once you’ve added the images to the project, add the following XAML snippet to the Page.xaml file, below the last Border element: 

Page 41: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<!-- C1ImageRotator --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1ImageRotator" Style="{StaticResource ControlTitle}" /> <StackPanel x:Name="_spRotator" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,30,0,30"> <c1x:C1ImageRotator Source="cover1.jpg" Angle="-70" /> <c1x:C1ImageRotator Source="cover2.jpg" Angle="-45" /> <c1x:C1ImageRotator Source="cover3.jpg" Angle="0" /> <c1x:C1ImageRotator Source="cover4.jpg" Angle="45" /> <c1x:C1ImageRotator Source="cover5.jpg" Angle="70" /> </StackPanel> </StackPanel> </Border>

This XAML is enough to show the five images in a layout similar to the one in iTunes. The next step is to add code that will allow users to select an item by clicking on it. The selected item should be displayed flat, and the ones around it should be more rotated the further they are from the selected one. 

To implement this, open the Page.xaml.cs file and add the code below to the Page constructor: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1ImageRotators InitializeImageRotators(); UpdateImageRotation(2); }

The InitializeImageRotators method adds a few extra images to the panel (just to make the sample more visually appealing), then attaches an event handler to each C1ImageRotator in order to select it when the user clicks it with the mouse. Here is the implementation: 

Page 42: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void InitializeImageRotators(StackPanel sp) { // add a few extra image rotators StackPanel sp = _spRotator; int cnt = sp.Children.Count; for (int i = 0; i < cnt; i++) { C1ImageRotator ir = new C1ImageRotator(); ir.UriSource = ((C1ImageRotator)sp.Children[i]).UriSource; sp.Children.Add(ir); } // attach event handlers to all image rotators foreach (C1ImageRotator ir in sp.Children) { ir.ShowReflection = true; ir.MouseLeftButtonDown += ir_MouseLeftButtonDown; } } void ir_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // update rotations around the item that was clicked C1ImageRotator ir = sender as C1ImageRotator; int index = _spRotator.Children.IndexOf(ir); UpdateImageRotation(index); }

The only piece still missing is the code that will rotate all the covers when the user clicks one: 

void UpdateImageRotation(int selectedIndex) { // rotate all images in the stack panel for (int i = 0; i < _spRotator.Children.Count; i++) { int delta = i - selectedIndex; C1ImageRotator ir = _spRotator.Children[i] as C1ImageRotator; double angle = Math.Sqrt(Math.Abs(delta)) * 45 * Math.Sign(delta); ir.Angle = Math.Max(-90, Math.Min(90, angle)); ScaleTransform st = new ScaleTransform(); st.CenterX = st.CenterY = 0.5; st.ScaleX = st.ScaleY = 1 + 0.15 / (1.0 + Math.Abs(delta)); ir.RenderTransform = st; ir.SetValue(Canvas.ZIndexProperty, 1000 - Math.Abs(delta)); } }

The code loops through the C1ImageRotator objects in the panel and applies a rotation and scale that are proportional to the difference between the element’s index and the currently selected index. 

Page 43: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

If you run the application now, you will see that the effect is pretty similar to the one seen in iTunes. The main difference is that the rotations happen instantly, instead of with a smooth animation effect. To improve the application, you could create a Storyboard and use it to modify the Angle and Scale property on each element instead of changing the values directly. That is left as an exercise for the reader (or check out the SilverTunes sample). 

 

Notice how the reflections “spill out” of the control boundaries. That is by design, they are intended to look like real reflections, not as part of the main image. Any UIElement can do this simply by setting its Clip property to null. 

C1ImageMagnifier The C1ImageMagnifier control is similar to an Image element with a ‘magnifying glass’ over it. The portion of the image under the magnifying glass is zoomed. The user can move the magnifying glass over the image to easily zoom in on any part of the image, and he can use the keyboard to change the zoom factor. 

The control is useful in situations where you have a high‐resolution image and want to allow users to zero‐in on important details. It is a simple alternative to a deep zoom image. 

Here is the XAML that needs to be added to the Page.xaml file below the last Border element: 

<!-- C1ImageMagnifier (new in M4) --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1ImageMagnifier (C1.Silverlight.Extended)" Style="{StaticResource ControlTitle}" /> <c1x:C1ImageMagnifier Width="400" Height="200" Source="cover2.jpg" Zoom="2" /> </StackPanel> </Border>

Page 44: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

If you run the project now, the C1ImageMagnifier will look like the image below. You can drag the magnifying glass with the mouse to see the details of the album cover. You can also use the arrow keys to move the magnifier over the image, and the plus/minus keys to change the zoom factor. 

You can customize the appearance of the magnifying glass using the Zoom property, which gets or sets the current zoom factor, and the Magnifier property, which returns a reference to the Border element that holds the zoomed image. 

C1HtmlHost The C1HtmlHost control behaves like an HMTL “iframe” tag, and allows you to show HTML content within your Silverlight pages. This is a reversal of the typical scenario, where Silverlight plug‐ins are islands in the HTML that makes up the page. The C1HtmlHost control allows you to create HTML islands in your Silverlight pages. 

This concept is useful because in many cases your Silverlight applications may want to display existing HTML content within the Silverlight plug‐in itself (as opposed to controlling elements in the host page’s DOM, which Silverlight also allows). 

Here is the XAML that needs to be added to the Page.xaml file below the last Border element: 

<!-- C1HtmlHost --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1HtmlHost" Style="{StaticResource ControlTitle}" /> <c1x:C1HtmlHost Width="400" Height="20" SourceHtml="This is &lt;b&gt;HTML&lt;/b&gt; hosted in a Browser!"/> <c1x:C1HtmlHost Width="400" Height="200" SourceUri="http://www.componentone.com" /> </StackPanel> </Border>

The C1HtmlHost can be populated in two ways: 

1) Use the SourceHtml property to specify an HMTL string that should be displayed in the control. This option is useful if your application builds or loads the HTML content. 

2) Use the SourceUri property to specify the URL that will be displayed in the control. This option is useful if your application needs to display content that is already available at a given URL. 

The C1HtmlHost control has an important requirement. In order to display the HTML content within the Silverlight plug‐in, the plug‐in must have its Windowless property set to true. If you run the application now, you will see an error message that explains this: 

To use this control the Silverlight plug‐in must have its 'Windowless' parameter set to true. 

Page 45: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The control cannot modify the properties of the plug‐in, the page author must to that instead. To make the necessary change, open the page that creates the plug‐in (in our case QuickStartTextPage.aspx, which is part of the QuickStartWeb project) and add a line to set the Windowless property to true: 

<%@ 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>ComponentOne Studio for Silverlight QuickStart</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" Windowless="true" Source="~/ClientBin/QuickStart.xap" Version="2.0" Width="100%" Height="100%" /> </div> </form> </body> </html>

If you run the project now, you should see the HTML content hosted within the Silverlight page: 

 

C1Book The C1Book control presents UIElement objects as if they were pages in a book. You can see two elements at a time and turn the pages with the mouse, just as you would turn pages in a regular paper book. 

Page 46: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The C1Book is an ItemsControl, so you can define it entirely in XAML, including its contents. 

Here is the XAML that needs to be added to the Page.xaml file, right after the last Border element on the page: 

<!-- C1Book (new in M3) --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Book (NEW, C1.Silverlight.Extended)" Style="{StaticResource ControlTitle}" /> <c1x:C1Book x:Name="_book" Width="500" Height="300" > <!-- template for left pages --> <c1x:C1Book.LeftPageTemplate> <ControlTemplate> <Border BorderThickness="1,1,2,2" BorderBrush="Gray" Background="WhiteSmoke"> <StackPanel Margin="10,10,25,10"> <TextBlock Text="C1Book Sample" FontSize="9" Margin="0,0,0,10" HorizontalAlignment="Left" /> <ContentPresenter /> <!-- content goes here --> </StackPanel> </Border> </ControlTemplate> </c1x:C1Book.LeftPageTemplate> <!-- template for right pages --> <c1x:C1Book.RightPageTemplate> <ControlTemplate> <Border BorderThickness="1,1,2,2" BorderBrush="Gray" Background="White"> <StackPanel Margin="25,10,15,10"> <TextBlock Text="C1.Silverlight.Extended.dll" FontSize="9" HorizontalAlignment="Right" Margin="0,0,0,10" /> <ContentPresenter /> <!-- content goes here --> </StackPanel> </Border> </ControlTemplate> </c1x:C1Book.RightPageTemplate> <!-- book content: each element is a page --> <TextBlock Text="This is Page 1"/> <TextBlock Text="This is Page 2"/> <TextBox Text="This is Page 3 (type here)" AcceptsReturn="True"/> <Button Content="This is Page 4 (click it)"/> <Image Source="cover1.jpg" /> <Image Source="cover2.jpg" /> <Image Source="cover3.jpg" /> <Image Source="cover4.jpg" /> <TextBlock Text="This is the last page..."/> </c1x:C1Book> </StackPanel> </Border>

Page 47: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

This is a fair amount of XAML, but the C1Book control itself only required one line. 

After declaring the C1Book, the XAML defines two templates (LeftPageTemplate and RightPageTemplate). These templates are optional. If present, they are used to determine how the content should be laid out within each page, and should contain a ContentPresenter element that determines where the actual content will be displayed. 

In this sample, we use the templates to apply a border, margins, and a simple header to each page.  

After the templates comes the content of each page in the book. These are just regular elements, which may include controls, images, videos, even other C1Book elements. 

If you run the application now, you should be able to browse through the pages by flipping them with the mouse. 

 

The C1Book control has a CurrentPage property that gets or sets the index of the page that is currently being displayed. Setting this property displays the selected page immediately, without any animations. To turn pages with animation, use the TurnPage method. 

The C1Book control also has properties that determine whether it should show shadows on each page (ShowInnerShadows, ShowOuterShadows) and on the page corners when the mouse passes over them (ShowFold). 

By default, the first page is displayed on the left side, the second on the right, and so on. This prevents the control from being half empty when showing the first page. You can change this behavior by setting the IsFirstPageOnTheRight property to true. In this case, the first page is displayes on the right side of the control, as the cover of a closed book. 

C1Book is an ItemsControl, which allows you to bind it to data sources. As usual, each item I nthe data source can be a UIElement or a generic object that gets converted into a UIElement using templates. 

Page 48: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1Cube The C1Cube control allows you to attach UIElement objects to faces on a rotating cube. The control provides methods for rotating the cube in order to display specific elements, or you can allow users to spin the cube with the mouse. 

C1Cube is an ItemsControl, so you can define it entirely in XAML, including its contents. 

Here is the XAML that needs to be added to the Page.xaml file, right after the last Border element on the page: 

<!-- C1Cube (new in M3) --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Cube" Style="{StaticResource ControlTitle}" /> <c1x:C1Cube x:Name="_cube" Margin="5" Width="200" Height="200" > <Image Source="cover1.jpg" c1x:C1Cube.Face="Front" /> <Image Source="cover2.jpg" c1x:C1Cube.Face="Back" /> <Image Source="cover3.jpg" c1x:C1Cube.Face="Left" /> <Image Source="cover4.jpg" c1x:C1Cube.Face="Right" /> <Image Source="cover5.jpg" c1x:C1Cube.Face="Top" /> <Button Content="Click Me ;-)" c1x:C1Cube.Face="Bottom" /> </c1x:C1Cube> <Button Content="Next Face..." Click="Button_Click" Width="200"/> </StackPanel> </Border>

This XAML creates and populates the C1Cube, and adds a button below it with an event handler that turns the cube to show the next face. Here is the implementation for the event handler: 

int _currentFace = 0; private void Button_Click(object sender, RoutedEventArgs e) { _cube.ShowFace((CubeFace)(++_currentFace % 6)); }

The code defines a variable to keep track of the face currently being displayed, and calls the ShowFace method to show the next face each time the button is clicked. 

Page 49: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

This sample uses the cube as container for other controls, somewhat similar to a tab or a wizard. Each tab or wizard page corresponds to a cube face, and the cube rotates only to switch from one face to another. 

If you set the IsDraggable property to true, users can rotate the cube with the mouse. However, in this case the content presented on the cube faces will no longer receive the mouse events. 

Finally, you can take complete control over the cube rotation in code, using the RotationX, RotationY, and RotationZ properties. For example, you could use these properties to create a cube that spins continuously, displaying your company logo. 

C1.Silverlight.RichTextBox.dll The C1.Silverlight.RichTextBox.dll contains a single control, the C1RichTextBox. 

The C1RichTextBox provides rich editing including multiple fonts and colors, images, lists, hyperlinks, per‐paragraph alignment, HTML import and export. 

In addition to rich formatting, the C1RichTextBox provides automatic line wrapping and several types of HTML export (with CSS style sheets, inline styles, or simple tags only). 

The latest version of the C1RichTextBox control has a document‐oriented architecture similar to the one found in WPF. The control has a Document property that gets or sets the C1Document object displayed in the control. C1Document objects can be persisted as HTML documents, and can also be created and manipulated in code using a rich object model. 

C1RichTextBox In this step, we will add a C1RichTextBox control to the application. In order to demonstrate the control, we will also add a small toolbar so users can change the style of the selected text. 

To keep the sample short and simple, we will expose only the bold, italic, and underline properties of the selected text (the control supports many other styles and attributes). 

Page 50: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Here is the XAML that needs to be added to the Page.xaml file, right after the last Border element on the page: 

<!-- C1RichTextBox --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1RichTextBox" Style="{StaticResource ControlTitle}" /> <StackPanel Orientation="Horizontal" Width="400" > <ToggleButton x:Name="_btnBold" Padding="4,0,4,0" Content="B" FontWeight="Bold"/> <ToggleButton x:Name="_btnItalics" Padding="4,0,4,0" Content="I" FontStyle="Italic"/> <ToggleButton x:Name="_btnUnderline" Padding="4,0,4,0" Content="U" TextDecorations="Underline"/> </StackPanel> <C1_Silverlight:C1RichTextBox x:Name="_rtb" Width="400" Height="100" TextWrapping="Wrap" Html="This is a &lt;b&gt;C1RichTextBox&lt;/b&gt; control."/> </StackPanel> </Border>

Note that the content of the C1RichTextBox can be specified in two ways. The Text property is used to assign and retrieve the control content as plain text. The Html property is used to assign and retrieve formatted text as HTML. The HTML text needs to be encoded in the XAML file, so instead of “<b>”, tags are encoded as “&lt;b&gt;”. 

The C1RichTextBox exposes a TextWrapping property that specifies whether the control should wrap long lines or whether it should keep the lines together and provide a horizontal scrollbar instead. 

Now that the controls have been defined, we need to add some code to handle the buttons. To do that, open the Page.xaml.cs file in Visual Studio and add the following code to the page constructor: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the C1RichTextBox _btnBold.Click += _btnBold_Click; _btnItalics.Click += _btnItalics_Click; _btnUnderline.Click += _btnUnderline_Click; _rtb.SelectionChanged += _rtb_SelectionChanged; }

The new code attaches event handlers to each button in the toolbar (so the styles can be applied to the C1RichTextBox) and to the SelectionChanged event on the C1RichTextBox (so we can toggle the buttons to reflect the formatting of the current selection). 

Page 51: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Next, we need to add the event handlers to the Page class: 

void _btnBold_Click(object sender, RoutedEventArgs e) { if (_btnBold.IsChecked.HasValue) { _rtb.Selection.FontWeight = _btnBold.IsChecked.Value ? FontWeights.Bold : FontWeights.Normal; } } void _btnItalics_Click(object sender, RoutedEventArgs e) { if (_btnItalics.IsChecked.HasValue) { _rtb.Selection.FontStyle = _btnItalics.IsChecked.Value ? FontStyles.Italic : FontStyles.Normal; } } void _btnUnderline_Click(object sender, RoutedEventArgs e) { if (_btnUnderline.IsChecked.HasValue) { _rtb.Selection.TextDecorations = _btnUnderline.IsChecked.Value ? TextDecorations.Underline : null; } }

 

These event handlers execute when the user clicks one of the Bold, Italic, or Underline buttons. They all start by checking whether the button’s IsChecked property has a value (it may be in a mixed state). If the button has a value, it is applied to the corresponding property of the editor’s Selection. Selection is a property of the C1RichTextBox control that allows you to modify the content and style of the current selection. 

These handlers take care of button clicks. But we also want to change the state of the buttons as the user changes the selection. For example, if he selects some text that is bold, we would like the Bold button to appear pressed automatically. To do this, we need to add the following event handler: 

Page 52: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void _rtb_SelectionChanged(object sender, EventArgs e) { // get current selection var sel = _rtb.Selection; // update state of bold button FontWeight? fw = sel.FontWeight; if (fw.HasValue) _btnBold.IsChecked = fw.Value == FontWeights.Bold; else _btnBold.IsChecked = null; // update state of italics button FontStyle? fs = sel.FontStyle; if (fs.HasValue) _btnItalics.IsChecked = fs.Value == FontStyles.Italic; else _btnItalics.IsChecked = null; // update state of underline button TextDecorationCollection td = sel.TextDecorations; _btnUnderline.IsChecked = td != null; }

 

The code starts by getting a reference to the Selection object. It then checks the value of the style properties that correspond to each button and updates their state to reflect the state of the current selection. 

Note that the Bold and Italic buttons can be in three states (if the selection contains mixed states, the button is put is an undefined state). This is accomplished easily because the corresponding properties in the selection (FontWeight and FontStyle) return nullable values. The Underline button, however, is never put in an undefined state. This is because the TextDecorations property returns an object, and there is no way to differentiate between a “null” that indicates there are no decorations and a “null” that indicates the selection is in a mixed state. It would be easy to work around this small limitation in a real application, but the behavior described is good enough for this sample. 

Run the sample again to see the C1RichTextBox in action, along with its fully functional (albeit simple) toolbar: 

 

Page 53: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1.Silverlight.Uploader.dll The C1.Silverlight.Uploader.dll contains a single component, the C1Uploader. 

The C1Uploader component uploads files and streams from Silverlight applications running on the client to the server. 

C1Uploader To see the C1Uploader in action, start by adding the following XAML below the last Border element in the Page.xaml file: 

<!-- C1Uploader --> <Border Style="{StaticResource ControlBorder}"> <StackPanel> <TextBlock Text="C1Uploader" Style="{StaticResource ControlTitle}" /> <StackPanel Orientation="Horizontal" Height="250"> <Button Content="Upload Photos..." Height="30" VerticalAlignment="Top" Margin="5" Click="Upload_Click" /> <ScrollViewer Width="400" Margin="5" Background="White"> <StackPanel x:Name="_spPictures" /> </ScrollViewer> </StackPanel> </StackPanel> </Border>

This creates a button that the user will click in order to upload image files to the server, and a panel where the images will be displayed. 

In order to make this work, add the event handler below to the Page.xaml.cs file, below all the other methods in the Page class: 

Page 54: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

private void Upload_Click(object sender, RoutedEventArgs e) { // configure OpenFileDialg OpenFileDialog dlg = new OpenFileDialog(); dlg.Filter = "All|*.*|Images|*.jpg;*.png;*.gif"; dlg.FilterIndex = 2; dlg.Multiselect = true; // show OpenFileDialg if ((bool)dlg.ShowDialog()) { try { // check that the files really are images foreach (FileDialogFileInfo fdi in dlg.SelectedFiles) { System.Windows.Media.Imaging.BitmapImage img = new System.Windows.Media.Imaging.BitmapImage(); img.SetSource(fdi.OpenRead()); } } catch { C1MessageBox.Show( "Sorry, at least one of these files doesn't look like an image...", "Upload Canceled", C1MessageBoxButton.OK, C1MessageBoxIcon.Warning); return; } // create and configure uploader Uri uri = BuildAbsoluteUri("photoUpload.ashx"); C1Uploader uploader = new C1UploaderPost(uri); uploader.UploadProgressChanged += uploader_UploadProgressChanged; uploader.UploadCompleted += uploader_UploadCompleted; // upload selected files uploader.AddFiles(dlg.SelectedFiles); uploader.BeginUploadFiles(); } }

The event handler starts by showing an OpenFileDialog to the user so he can select the files that will be uploaded. Silverlight runs in a secure sandbox environment, and you can't get direct access to the file system. But the OpenFileDialog class grants access to specific files explicitly selected by the user. You can also get access to files in the IsolatedStorage area. 

Once the files have been selected, the code checks that the files really are images. It does this by creating BitmapImage objects and loading the files into the objects. If the file does not contain an image, then an exception is thrown and the process is aborted. This check prevents users from uploading files 

Page 55: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

of the wrong type, either by mistake or with malicious intent. Later, we will also perform a similar security check on the server. 

After the files have been validated, the code creates a new C1UploaderPost object. There are two types of C1Uploader object, the C1UploaderPost and C1UploaderWebService. The difference between the two is how files are received on the server. C1UploaderPost uses a multipart POST protocol that is very easy to use, as you will see below. 

The C1UploaderPost constructor requires a parameter that specifies the Uri of the handler that will process the files on the server. Silverlight requires an absolute Uri, so the code uses a helper method called BuildAbsoluteUri that works whether the application is running on a development machine or on a production server. Here is the code: 

public static Uri BuildAbsoluteUri(string relativeUri) { // get current absolute Uri; this depends on where the app is deployed Uri uri = System.Windows.Browser.HtmlPage.Document.DocumentUri; string uriString = uri.AbsoluteUri; // replace page name with relative service Uri int ls = uriString.LastIndexOf('/'); uriString = uriString.Substring(0, ls + 1) + relativeUri; // return new Uri return new Uri(uriString, UriKind.Absolute); }

The code also attaches event handlers to the UploadProgressChanged and UploadCompleted events of the new C1UploaderPost. We will use the first to check the progress of the upload process, and the second to display the files that were uploaded. Here is the code: 

void uploader_UploadProgressChanged(object sender, C1.Silverlight.Uploader.UploadProgressChangedEventArgs e) { Debug.WriteLine("uploaded {0} of {1} bytes, {2}%", e.BytesUploaded, e.TotalBytesToUpload, e.ProgressPercentage); }

Page 56: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

void uploader_UploadCompleted(object sender, UploadCompletedEventArgs e) { if (e.Success) { foreach (string fileName in e.Files) { // holder for picture and title StackPanel picHolder = new StackPanel(); picHolder.Background = new SolidColorBrush(Colors.LightGray); picHolder.Margin = new Thickness(10); picHolder.Width = 200; // create Image to show the picture System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage(); bmp.UriSource = BuildAbsoluteUri("Pictures/" + fileName); Image img = new Image(); img.Source = bmp; img.Margin = new Thickness(10, 10, 10, 0); picHolder.Children.Add(img); // create image title TextBlock tb = new TextBlock(); tb.Text = fileName; tb.FontSize = 12; tb.HorizontalAlignment = HorizontalAlignment.Center; tb.Margin = new Thickness(10, 0, 10, 10); picHolder.Children.Add(tb); // add picture holder to panel _spPictures.Children.Add(picHolder); } } else { Debug.WriteLine("Upload failed: {0}", e.Error != null ? e.Error.Message : "??"); } }

The code checks that the upload was successful, and then loops through the files to create a new Image element for each one. The Image elements are configured to show the images, assuming they are stored under a "Pictures" folder on the server. 

If you run the project now and try to upload some pictures, you will get an error. That is because the C1Uploader is sending files to the server, but we haven't implemented the server code yet. 

To implement the server part of the code, right‐click the QuickStartWeb solution in the Visual Studio Solution Explorer and select the "Add | New Item…" option. Then pick the "Generic Handler" template and call the new class "photoUpload.ashx" (this is the Uri we used when creating the C1Uploader object earlier). This is what you should be seeing now: 

Page 57: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

Once you're done creating the "photoUpload.ashx" file, open it and replace the default implementation of the ProcessRequest method with the following code: 

Page 58: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

public void ProcessRequest(HttpContext context) { const int MAXFILES = 30; // clean up string path = context.Request.MapPath("Pictures"); string[] files = System.IO.Directory.GetFiles(path); if (files.Length >= MAXFILES) { foreach (string fileName in files) System.IO.File.Delete(fileName); } // get files being uploaded for (int i = 0; i < context.Request.Files.Count && i < MAXFILES; i++) { HttpPostedFile file = context.Request.Files[i]; try { // check that it really is an image by loading it into an Image object System.Drawing.Image img = System.Drawing.Image.FromStream(file.InputStream); // save file to the Pictures folder string fileName = context.Request.MapPath("Pictures/" + file.FileName); file.SaveAs(fileName); } catch { // doesn't look like a valid image, skip request break; } } }

The code starts by cleaning up the images folder in case there are more than 30 images in it. A real application would do this differently, possibly by compressing old images or enforcing a per‐user storage limit. 

After the clean‐up, the code loops through the files in the context.Request.Files collection and checks that they really are image files. We already added a similar check when implementing the server part of the code, but it is important to protect both ends of the application. 

Finally, the code saves each image into the "Pictures" folder. This is a good time to create the "Pictures" folder under the QuickStartWeb application's main folder. 

After you create the Pictures folder, you have to set up its permissions so the application can save the pictures into the folder. To do that, follow these steps: 

Page 59: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

1. Right‐click the “Pictures” folder and select “Properties”. 2. Click the “Security” tab. 3. Make sure NETWORK SERVICE has Read and Write permissions checked. 4. If not then click “Edit” 5. Select NETWORK SERVICE and check the boxes next to Read and Write. 6. Click “Apply”, then “OK” 

Run the sample now and try uploading some pictures. Notice that you can select many pictures at a time. They will be uploaded to the server, saved in the "Pictures" folder, then downloaded back to the client by the Image elements that we are creating in response to the UploadCompleted event. The result is a simple picture album that looks like this: 

 

C1.Silverlight.Gauge.dll The C1.Silverlight.Gauge.dll assembly contains the C1Gauge, C1RadialGauge, and C1LinearGauge controls (C1Gauge is an abstract class that serves as a base for the other two). 

Gauge controls provide an intuitive and attractive way to display information graphically. They are often used in dashboard applications that display information summaries. 

Page 60: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The C1RadialGauge and C1LinearGauge controls have properties that provide extensive customization without requiring any changes to the XAML template. 

C1RadialGauge and C1LinearGauge To see the C1RadialGauge and C1LinearGauge controls in action, start by adding the following XAML below the last Border element in the Page.xaml file: 

<!-- C1RadialGauge and C1LinearGauge --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Gauge (NEW, C1.Silverlight.Gauge)" Style="{StaticResource ControlTitle}" /> <!-- simple RadialGauge --> <c1g:C1RadialGauge x:Name="_gauge1" Width="300" Height="250"

StartAngle="0" SweepAngle="270" Radius="0.9" Minimum="0" Maximum="270" Value="50">

<c1g:C1RadialGauge.Decorators> <c1g:C1GaugeMark From="0" To="270" Interval="30" ShowLabels="True" ShowMarks="True" MarkLocation="0.8" LabelLocation="0.9" /> <c1g:C1GaugeMark From="0" To="270" Interval="5" ShowLabels="False" ShowMarks="True" MarkLocation="0.75" /> <c1g:C1GaugeRange From="0" To="60" Location="0.4" StrokeThickness="0.3" Background="#A000F000" /> <c1g:C1GaugeRange From="60" To="120" Location="0.4" StrokeThickness="0.3" Background="#A0F0F000" /> <c1g:C1GaugeRange From="120" To="180" Location="0.4" StrokeThickness="0.3" Background="#A0F0A000" /> <c1g:C1GaugeRange From="180" To="270" Location="0.4" StrokeThickness="0.3" Background="#A0F00000" /> </c1g:C1RadialGauge.Decorators>

</c1g:C1RadialGauge> <!-- simple LinearGauge --> <c1g:C1LinearGauge x:Name="_gauge2" Width="300" Height="20" Minimum="0" Maximum="270" Value="50"/> <!-- Slider used to set Gauge values --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <TextBlock Width="80" /> <Slider x:Name="_slider" Width="300" Minimum="0" Maximum="270" Value="50" ValueChanged="_slider_ValueChanged" /> <TextBlock x:Name="_txtGaugeValue" Width="80" Text="50" TextAlignment="Center"/> </StackPanel> </StackPanel> </Border>

This XAML adds two gauges to the page. Below the gauges, it adds a Slider used to modify the value displayed in the gauges, and and a TextBlock used to display the current value. 

Page 61: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The first gauge is a RadialGauge, and it includes several “Decorators“ that customize its appearance. The first two decorators are GaugeMark objects used to show tick marks and scale values. The remaining decorators are GaugeRange objects used to highlight ranges of values.  

The code below implements the event hander that will be called when the user modifies the value of the Slider: 

private void _slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { double value = ((Slider)sender).Value; if (_gauge1 != null && _gauge2 != null) { _gauge1.Value = _gauge2.Value = value; } if (_txtGaugeValue != null) { _txtGaugeValue.Text = value.ToString("n0"); } }

The code starts by retrieving the current value of the Slider control, then applies the value to both gauges and to the TextBlock element. 

If you run the application now, you will an image like the one below. Move the Slider to change the value and see how the gauges change also. 

 

 

Page 62: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1.Silverlight.Maps.dll The C1.Silverlight.Maps.dll assembly contains the C1Maps control. 

The C1Maps control displays rich geographical information from various sources, including Microsoft Live MapsTM and Google MapsTM. It supports zooming, panning, and mapping between screen and geographical coordinates. It also supports layers that allow you to superimpose elements to the maps. 

C1Maps To see C1Maps in action, add the XAML below to the Page.xaml file, below the last Border element: 

<!-- C1Maps --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Maps" Style="{StaticResource ControlTitle}" /> <c1m:C1Maps Width="500" Height="350" Center="-79.924706, 40.458833" Zoom="3" MouseMove="C1Maps_MouseMove"> <c1m:C1MapItemsLayer> <Ellipse Width="15" Height="15" Fill="Yellow" Opacity="0.5" c1m:C1MapCanvas.LatLong="-79.924706, 40.458833"/> </c1m:C1MapItemsLayer> </c1m:C1Maps> <TextBlock x:Name="_tbMapCoords" Width="500" Text="" /> </StackPanel> </Border>

This XAML creates the C1Maps control and initializes its Center and Zoom properties to show the ComponentOne head office in Pittsburgh, PA. It also adds a yellow Ellipse to the C1MapsItemsLayer and positions it at the same geographical position used as the center. The ellipse is attached to that geographical position and will move with the map as the user zooms and pans with the mouse. 

Finally, the code specifies a handler for the MouseMove event so we can show the coordinates under the mouse. Here is the event handler that should be added to the Page.xaml.cs file: 

private void C1Maps_MouseMove(object sender, MouseEventArgs e) { C1Maps map = sender as C1Maps; Point p = map.ScreenToGeographic(e.GetPosition(map)); _tbMapCoords.Text = string.Format("{0:f6},{1:f6}", p.X, p.Y); }

The code converts the mouse (screen) coordinates into geographical coordinates and shows them below the map. 

If you run the application now, you should see a display similar to the image below. You can use the mouse to drag the map to a new position and the mouse wheel to zoom in and out. As you move the mouse over the map, the current geographical coordinates are displayed below. 

Page 63: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

You can now zoom in using the mouse wheel or the zoom bar on the left. Get close enough and you will see the ComponentOne building and the new Borders store across the freeway. 

 

Page 64: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

C1Maps can display geographical information from several sources. By default it uses Microsoft LiveMapsTM as the source, but you can change that using the Source property, which takes an object of type MultiScaleTileSource. The following sources are included: 

map1.Source = new VirtualEarthAerialSource(); // Virtual Earth Aerial map2.Source = new VirtualEarthRoadSource(); // Virtual Earth Road map3.Source = new VirtualEarthHybridSource(); // Virtual Earth Hybrid map4.Source = new GoogleMapsMapSource(); // Google Maps Road map5.Source = new GoogleMapsSatelliteSource(); // Google Maps Satellite

The portion of the map that is currently visible is determined by the Center and Zoom properties, and by the size of the control. 

The Center property is of type Point but it actually represents a geographic coordinate, in which the X property is longitude and the Y property is latitude. The user can change the value of the Center property by dragging the map with the mouse, or by using the navigator control shown on the left top corner. 

The Zoom property indicates the current resolution of the map. A zoom value of 0 has the map totally zoomed out, and each increment of 1 doubles the map resolution. The user can change the value of the Zoom property using the mouse wheel, or the zoom control on the left side of the control. 

C1Maps uses three coordinate systems: 

• Geographic coordinates mark points in the world using latitude and longitude. This coordinate system is not Cartesian, which means the scale of the map may change as you pan. 

• Logical coordinates go from 0 to 1 on each axis for the whole extent of the map, and they are easier to work with because they are Cartesian coordinates. 

• Screen coordinates are the pixel coordinates of the Control relative to the top‐left corner. These are useful for positioning items within the control and for handling mouse events. 

C1Maps provides four methods for converting between these coordinate systems: ScreenToGeographic, ScreenToLogic, GeographicToScreen, and LogicToScreen. 

In addition to the geographical information provided by the source, you can add layers of information to the map. C1Maps includes four layers by default: 

• C1MapItemsLayer is the layer used to display arbitrary items, positioned geographically on the map. This layer is an ItemsControl, so it supports directly adding UIElement objects or generic data objects with a DataTemplate that can convert them into visual items. 

• C1MapVirtualLayer displays items that are virtualized, so they are only present in the visual tree when they need to be displayed on the map. 

• C1MapToolsLayer is the next layer, used to display tools for panning and zooming, and a scale. 

Page 65: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

• C1MapTilesLayer is the background layer where the map tiles are displayed. You normally don’t have to use this layer because it is managed by C1Maps automatically. 

Note: C1Maps only works in solutions that include a web site or web application project. If you use it in a standalone, single‐project Silverlight solution, it will not display anything. 

C1.Silverlight.Chart.dll The C1.Silverlight.Chart.dll assembly contains the C1Chart control. 

The C1Chart control is a full‐featured charting tool that supports several chart types, built‐in color palettes, and special effects including animations, zooming, and panning.  

C1Chart To see C1Chart in action, add the XAML below to the Page.xaml file, below the last Border element: 

Page 66: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<!-- C1Chart --> <Border Style="{StaticResource ControlBorder}" > <StackPanel> <TextBlock Text="C1Chart (C1.Silverlight.Chart)" Style="{StaticResource ControlTitle}" /> <!-- controls to customize the chart --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <TextBlock Text="Chart Type: " FontSize="11" VerticalAlignment="Center" /> <c1:C1ComboBox x:Name="_cbChartType" FontSize="11" Width="120" SelectedItemChanged="_cbChartType_SelectedItemChanged" SelectedIndex="0" > <c1:C1ComboBoxItem Content="Line"/> <c1:C1ComboBoxItem Content="Area"/> <c1:C1ComboBoxItem Content="Column"/> </c1:C1ComboBox> <TextBlock Text="Palette: " FontSize="11" VerticalAlignment="Center" Margin="20,0,0,0"/> <c1:C1ComboBox x:Name="_cbPalette" FontSize="11" Width="120" SelectedItemChanged="_cbPalette_SelectedItemChanged" SelectedIndex="0" > <c1:C1ComboBoxItem Content="Default"/> <c1:C1ComboBoxItem Content="Standard"/> <c1:C1ComboBoxItem Content="Office"/> <c1:C1ComboBoxItem Content="GrayScale"/> <c1:C1ComboBoxItem Content="Apex"/> <c1:C1ComboBoxItem Content="Aspect"/> <c1:C1ComboBoxItem Content="Civic"/> <!-- actual sample includes over 20 color schemes… --> </c1:C1ComboBox> <Button x:Name="_btnChart" Content="Generate" Margin="20,0,0,0" Padding="5,0,5,0" Click="_btnChart_Click" /> </StackPanel> <!-- chart and legend --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <c1c:C1Chart x:Name="_chart" Width="500" Height="350" /> <Border CornerRadius="5" BorderThickness="2" BorderBrush="DarkGray" Background="WhiteSmoke" Padding="5" VerticalAlignment="Center" > <c1c:C1ChartLegend x:Name="_legend" /> </Border> </StackPanel> </StackPanel> </Border>

This XAML starts by creating a C1Chart and a C1ChartLegend. C1Chart does not display the legend within the control. Instead, you must create a separate C1ChartLegend control and connect it to the chart using the legend’s Chart property. This design provides maximum flexibility when styling and positioning the legend. 

Page 67: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Below the chart and legend, the XAML adds some controls that will be used to select the chart type, color scheme, and to generate some random data. 

Now that the controls have been defined, we need to add some code to handle the buttons. To do that, open the Page.xaml.cs file in Visual Studio and add the following code to the page constructor: 

public Page() { InitializeComponent(); // initialize other controls // no changes here… // initialize the chart _legend.Chart = _chart; // connect legend to chart GenerateChart(); // show the chart }

The code starts by connecting the legend to the C1Chart, then calls the GenerateChart method to populate the chart. This is the code for the GenerateChart method, it should be added to the Page.xaml.cs file: 

// populate chart with some random series void GenerateChart() { // don't repaint while creating the chart _chart.BeginUpdate(); // clear existing content if any _chart.Data.Children.Clear(); // configure X axis _chart.View.AxisX.IsTime = true; _chart.View.AxisX.AnnoFormat = "MMM dd"; // configure Y axis _chart.View.AxisY.AnnoFormat = "0 "; // add a few data series foreach (string seriesName in "North;East;South;West;Center;Overseas".Split(';')) { AddSeries(_chart, seriesName + " Region"); } // done _chart.EndUpdate(); }

The code sets up the chart, then calls the AddSeries method a few times to populate the chart. Here’s the code for AddSeries: 

Page 68: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

// add a series with some random data Random _rnd = new Random(0); void AddSeries(C1Chart chart, string name) { // create some random data to plot int len = 50; DateTime[] x = new DateTime[len]; double[] y = new double[len]; double lastY = 0; for (int i = 0; i < len; i++) { x[i] = DateTime.Today.AddDays(i); y[i] = Math.Max(0, lastY + (_rnd.NextDouble() - 0.45) * 10); lastY = y[i]; } // create the series XYDataSeries ds = new XYDataSeries(); ds.XValuesSource = x; ds.ValuesSource = y; ds.Label = name; ds.ConnectionStrokeThickness = 3; // add series to chart chart.Data.Children.Add(ds); }

The code generates two arrays with data for the X and Y axis, then creates a new data series and populates is using the ValuesSource and XValuesSource properties. Finally, it adds the new series to the chart. 

The only part still missing are the event handlers for the controls that determine the chart appearance. Here they are: 

// change chart type void _cbChartType_SelectedItemChanged(object sender, C1.Silverlight.PropertyChangedEventArgs<object> e) { switch (_cbChartType.SelectedIndex) { case 0: _chart.ChartType = ChartType.LineSymbols; break; case 1: _chart.ChartType = ChartType.AreaStacked; break; case 2: _chart.ChartType = ChartType.ColumnStacked; break; } }

Page 69: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

// change chart palette void _cbPalette_SelectedItemChanged(object sender, C1.Silverlight.PropertyChangedEventArgs<object> e) { _chart.Palette = (Palette)_cbPalette.SelectedIndex; } // re-generate chart void _btnChart_Click(object sender, RoutedEventArgs e) { GenerateChart(); }

That concludes this part of the sample. If you run the application again and scroll all the way to the bottom of the screen, you should see this: 

 

Use the combo boxes to change the chart type and palette, or click the “Generate” button to generate a new set of random data. 

Page 70: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

DataTemplates 

The previous sections focused on the ComponentOne Silverlight controls. This section focuses on DataTemplates, and how they are applied to Silverlight controls in general (including the ones provided by Microsoft). If you are an experienced Silverlight developer, this information may be of no interest to you. 

DataTemplates are a powerful feature in Silverlight 2.0. They are virtually identical to the DataTemplates in WPF, so if you know WPF there’s nothing really new about them. 

On the other hand, if you have never used WPF and have seen pieces of XAML that contain styles and templates, you may be confused by the concepts and notation. The good news is DataTemplates are very powerful and are not too complicated. Once you start using them, the concept will make sense in a couple of minutes and you will be on your way. Remember, just reading the tutorial probably won’t be enough to fully grasp the concept. After reading, you should play with the projects. 

Create the “Templates” Solution To illustrate the power of DataTemplates, let us create a new Silverlight solution. Call it “Templates”. 

Next, select the Templates project in the Solution Explorer and add a reference to the C1.Silverlight.dll assembly like we did before. This is required since we will be adding C1.Silverlight controls to the page. 

Now, open the Page.xaml file in the Templates project and paste the code below. This creates a page with two columns. The left column has a standard ListBox control and the right has two C1ComboBoxes. These are the controls we will populate and style later. 

<UserControl x:Class="Templates.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:C1_Silverlight="clr-namespace:C1.Silverlight;assembly=C1.Silverlight"> <Grid x:Name="LayoutRoot" > <Grid.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF7EB9F0"/> <GradientStop Color="#FF284259" Offset="1"/> </LinearGradientBrush> </Grid.Background> <!-- grid layout --> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions>

Page 71: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<!-- page title --> <TextBlock Text="Silverlight Templates" Grid.Column="0" Grid.ColumnSpan="2" TextAlignment="Center" FontSize="18" FontWeight="Bold" /> <!-- ListBox on the left --> <StackPanel Grid.Row="1" Margin="5" > <TextBlock Text="ListBox Control" /> <ListBox x:Name="_listBox" /> </StackPanel> <!-- C1ComboBoxes on the right --> <StackPanel Grid.Column="2" Grid.Row="1" Margin="5" > <TextBlock Text="C1ComboBox Controls" /> <C1_Silverlight:C1ComboBox x:Name="_cmb1" Margin="0,0,0,5" /> <C1_Silverlight:C1ComboBox x:Name="_cmb2" Margin="0,0,0,5" /> </StackPanel> </Grid> </UserControl>

Populate the controls Before we start using templates and styles, let us populate the controls first. To do that, open the Page.xaml.cs file and paste the following code into the page constructor: 

public Page() { InitializeComponent(); // get list of items IEnumerable list = GetItems(); // add items to ListBox and in C1ComboBox _listBox.ItemsSource = list; _cmb1.ItemsSource = list; // show fonts in the other C1ComboBox FontFamily[] ff = new FontFamily[] { new FontFamily("Default font"), new FontFamily("Arial"), new FontFamily("Courier New"), new FontFamily("Times New Roman"), new FontFamily("Trebuchet MS"), new FontFamily("Verdana") }; _cmb2.ItemsSource = ff; }

Page 72: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

The code populates the ListBox and both C1ComboBoxes by setting their ItemsSource property. ItemsSource is a standard property present in most controls that support lists of items (ListBox, DataGrid, C1ComboBox, etc). 

Before running the project, we need to implement the GetItems() method in the Page class. Here it is: 

List<DataItem> GetItems() { List<DataItem> members = new List<DataItem>(); foreach (MemberInfo mi in this.GetType().GetMembers()) { members.Add(new DataItem(mi)); } return members; }

And finally, here’s the definition of the DataItem class. You can add this to the Page.xaml.cs file, below the Page class definition: 

public class DataItem { public string ItemName { get; set; } public MemberTypes ItemType { get; set; } public DataItem(MemberInfo mi) { ItemName = mi.Name; ItemType = mi.MemberType; } }

If you run the project now, you will see that the controls are being populated. However, they don’t do a very good job of showing the items: 

Page 73: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

The controls simply convert the DataItem objects into strings using their ToString() method, which we didn’t override and by default returns a string representation of the object type (“Templates.DataItem”). 

The bottom C1ComboBox displays the font family names correctly. That’s because the FontFamily class implements the ToString() method and returns the font family name. 

It is easy to provide a ToString() implementation that would return a more useful string, containing one of more properties. For example: 

public override string ToString() { return string.Format("{0} {1}", ItemType, ItemName); }

If you add this method to the DataItem class and run the project again, you will see a slightly more satisfying result. But there’s only so much you can do with plain strings. To represent complex objects effectively, we need something more. Enter Data Templates! 

Defining and using Data Templates Data Templates are objects that map regular .NET objects into UIElement objects. They are used by controls that contain lists of regular .NET objects to convert these objects into UIElement objects that can be displayed to the user. 

For example, the Data Template below can be used to map our DataItem objects into a StackPanel with two TextBlock elements that display the ItemName and ItemType properties of the DataItem. This is what the template definition looks like in XAML: 

Page 74: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<UserControl x:Class="Templates.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:C1_Silverlight="clr-namespace:C1.Silverlight;assembly=C1.Silverlight"> <!-- data template used to convert DataItem objects into UIElement objects --> <UserControl.Resources> <DataTemplate x:Key="DataItemTemplate" > <StackPanel Orientation="Horizontal" Height="30" > <TextBlock Text="{Binding ItemType}" Margin="5" VerticalAlignment="Bottom" Foreground="Red" FontSize="10" /> <TextBlock Text="{Binding ItemName}" Margin="5" VerticalAlignment="Bottom" /> </StackPanel> </DataTemplate> </UserControl.Resources> <!-- page content (same as before)… -->

This template tells Silverlight (or WPF) that in order to represent a source data object, it should do this: 

1) Create a StackPanel with two TextBlocks in it,  

2) Bind the Text property of the first TextBlock to the ItemType property of the source data object, and 

3) Bind the Text property of the second TextBlock object to the ItemName property of the source object. 

That’s it. The template does not specify what type of control can use it (any control can, we will use it with the ListBox and also with the C1ComboBox), and it does not specify the type of object it should expect (any object will do, as long as it has public properties named ItemType and ItemName). 

To use the template, add an ItemTemplate attribute to the controls where you want the template to be applied. In our example, we will apply it to the ListBox declaration in the Page.xaml file: 

<!-- ListBox on the left --> <StackPanel Grid.Row="1" Margin="5" > <TextBlock Text="ListBox Control" /> <ListBox x:Name="_listBox" ItemTemplate="{StaticResource DataItemTemplate}" /> </StackPanel>

And also to the top C1ComboBox: 

<!-- C1ComboBox on the right --> <StackPanel Grid.Column="2" Grid.Row="1" Margin="5" > <TextBlock Text="C1ComboBox Controls" /> <!-- C1ComboBox 1 -->

Page 75: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<C1_Silverlight:C1ComboBox x:Name="_cmb1" Margin="0,0,0,5" ItemTemplate="{StaticResource DataItemTemplate}" />

Note that we can now change the appearance of the DataItem objects by modifying the template in one place. Any changes will automatically be applied to all objects that use that template, making application maintenance much easier. 

Before you run the application again, let’s add a template to the second C1ComboBox as well. This control contains a list of font families. We can use templates to display each item using the actual font they represent. 

This time, we will not define the template as a resource. It will only be used in one place, so we can insert it inline, as shown below: 

<!-- C1ComboBox 2 --> <C1_Silverlight:C1ComboBox x:Name="_cmb2" FontSize="12" Margin="0,0,0,5" > <C1_Silverlight:C1ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" FontFamily="{Binding}" Margin="4" /> </DataTemplate> </C1_Silverlight:C1ComboBox.ItemTemplate> </C1_Silverlight:C1ComboBox>

Don’t let the XAML syntax confuse you. This specifies that in order to create items from data, the control should use a DataTemplate that consists of a single TextBlock element. The TextBlock element should have two of its properties (Text and FontFamily) bound to the data object itself (as opposed to properties of that object). 

In this case, the data object is a FontFamily object. Because the template assigns this object to the Text property and also to the FontFamily property, the TextBlock will display the font name and will use the actual font. 

If you run the project now, you should see this result: 

Page 76: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

 

Note that if you assign a DataTemplate to the C1ComboBox, it will no longer be able to perform text‐related tasks such as auto‐search and editing. If you want to re‐enable those features, you should provide your own ItemConverter that is a standard TypeConverter. 

Styles and Templates are extremely powerful concepts. We encourage you to play and experiment with this sample. Try modifying the templates to show the data in different ways. The more you experiment, the more comfortable you will feel with these concepts and with the Silverlight/WPF application architecture. 

Page 77: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Control Templates Data Templates allow you to specify how to convert arbitrary data objects into UIElement objects that can be displayed to the user. But that’s not the only use of templates in Silverlight and WPF. You can also use templates to modify the visual structure of existing UIElement objects such as controls. 

Most controls have their visual appearance defined by a native XAML resource (typically contained within the assembly that defines the control). This resource specifies a Style which assigns values to most of the control’s properties, including its Template property (which defines the control’s internal “visual tree”). 

For example: 

<Style TargetType="HyperlinkButton"> <Setter Property="IsEnabled" Value="true" /> <Setter Property="IsTabStop" Value="true" /> <Setter Property="Foreground" Value="#FF417DA5" /> <Setter Property="Cursor" Value="Hand" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="HyperlinkButton"> <Grid x:Name="RootElement" Cursor="{TemplateBinding Cursor}"> <!-- Focus indicator --> <Rectangle x:Name="FocusVisualElement" StrokeDashCap="Round" ...=""/> <!-- HyperlinkButton content --> <ContentPresenter x:Name="Normal" Background="{TemplateBinding Background}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"...=""/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>

This is a very simplified version of the XAML resource used to specify the HyperlinkButton control. It consists of a Style that begins by setting the default value of several simple properties, and then assigns a value of type ControlTemplate to the control’s Template property. 

The ControlTemplate in this case consists of a Grid (RootElement) that contains a Rectangle (FocusVisualElement) used to indicate the focused state, and a ContentPresenter (Normal) that represents the content portion of the control (and itself contains another ContentTemplate property). 

Note the TemplateBinding attributes in the XAML. These constructs are used to map properties exposed by the control to properties of the template elements. For example, the Background property of the hyperlink control is mapped to the Background property of the Normal element specified in the template. 

Page 78: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Specifying controls this way has some advantages. The complete visual appearance is defined in XAML and can be modified by a professional designer using Expression Blend, without touching the code behind it. In practice, this is not as easy as it sounds, because there are logical relationships between the template and the control implementation. 

Recognizing this problem, Silverlight introduced a TemplatePart attribute that allows control classes to specify the names and types it expects its templates to contain. In the future, this attribute will be added to WPF as well, and used by designer applications such as Blend to validate templates and ensure they are valid for the target control. 

For example, the Microsoft Button control contains the following TemplatePart attributes: 

/// <summary> /// Represents a button control, which reacts to the Click event. /// </summary> [TemplatePart(Name = Button.ElementRootName, Type = typeof(FrameworkElement))] [TemplatePart(Name = Button.ElementFocusVisualName, Type = typeof(UIElement))] [TemplatePart(Name = Button.StateNormalName, Type = typeof(Storyboard))] [TemplatePart(Name = Button.StateMouseOverName, Type = typeof(Storyboard))] [TemplatePart(Name = Button.StatePressedName, Type = typeof(Storyboard))] [TemplatePart(Name = Button.StateDisabledName, Type = typeof(Storyboard))] public partial class Button : ButtonBase

These six template parts constitute a contract between the control implementation and the design specification. They tell the designer that the control implementation expects to find certain elements in the template (defined by their name and type). 

Well‐behaved controls should degrade gracefully, not crashing if some non‐essential elements are missing from the template. For example, if the control can’t find a Storyboard named Button.StateMouseOverName in the template, it should not do anything when the mouse hovers over it. 

Well‐implemented templates should fulfill the contract and provide all the elements that the control logic supports. Designer applications such as Blend can enforce the contract and warn designers if they try to apply invalid templates to controls. 

For the time being, the easiest way to create new templates for existing controls is to start with the original XAML and customize it. 

We will not show any actual examples of how to create and use custom control templates here. Instead, we suggest you download the examples developed by Corrina Barber: 

http://blogs.msdn.com/corrinab/archive/2008/03/11/silverlight‐2‐control‐skins.aspx 

The link contains previews and downloads for three ‘skins’ (bubbly, red, and flat). Each skin consists of a set of Style specifications, similar to the one shown above, which are added to the application’s global XAML file (App.xaml). The format is similar to this: 

Page 79: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

<Application xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Styles_Red.App" <Application.Resources> <!-- Button --> <Style x:Key="buttonStyle" TargetType="Button"> <Setter Property="IsEnabled" Value="true" /> <Setter Property="IsTabStop" Value="true" /> <Setter Property="Foreground" Value="#FF1E2B33" /> <Setter Property="Cursor" Value="Hand" /> <Setter Property="TextAlignment" Value="Center" /> <!-- a lot more xaml follows… -->

Once these styles are defined in the App.xaml file, they can be assigned to any controls in the application: 

<Button Content="Button" Style="{StaticResource buttonStyle}"/>

If you are curious, this is what the Button control looks like after applying each of the skins defined in the reference above: 

Default 

 

Bubbly 

 

Red 

 

Flat 

 

 

This mechanism is extremely powerful. You can change what the controls look like and even the parts used internally to build them. 

Unlike data templates, however, control templates are not trivial to create and modify. Creating or changing a control template requires not only design talent but also some understanding of how the control works. 

It is also a labor‐intensive proposition. In addition to their normal appearance, most controls have Storyboards that are applied to change their appearance when the mouse hovers over them, when they gain focus, get pressed, get disabled, etc. (see the C1ComboBox example above). 

Furthermore, all controls in an application should have a consistent look. You probably wouldn’t want to mix bubbly buttons with regular scrollbars on the same page for example. So each ‘skin’ will contain styles for many controls. 

It is likely that professionally designed skin packages will become commercially available as soon as Silverlight 2.0 ships. 

Page 80: ComponentOne Studio for Silverlight - MicroWay · The ComponentOne Studio for Silverlight library is included in the ComponentOne Studio Enterprise product, which also includes control

Some controls are designed with custom templates in mind. For example, the C1ComboBox has an ItemsPanel property of type ItemsPanelTemplate. You can use this property to replace the default drop‐down ListBox element with any other UIElement you like. 

We will not demonstrate the ItemsPanel property here. Instead, we suggest you check the ControlExplorer sample distributed with the ComponentOne Studio for Silverlight.