Print Reporting Services reports from Silverlight Applications

(Media-Newswire.com) – Are you a developer? I’m sure you are. So don’t turn and go away! You knocked at the right door! In this article I’m going to talk about your problems and your concerns. And, by the way, where you address yourself if you have ones? I have no doubts that the only place where you can share your worries and difficulties is developer forum. There you can ask all the necessary questions connected with the most important problems giving braking effect to your software development process. And neither any software company nor Perpetuum Software LLC in particularly can stop paying attention to frequent queries regularly appearing in the posts of forum members. So how Perpetuum Software LLC can help inquisitive developers? Let’s start our Q&A session.

Q: Is there a tool intended to work with Reporting Services reports in Silverlight on the software development market? A: Actually, this question can be seen on the forums devoted to Silverlight technology. Perpetuum Software offers you a unique Silverlight Viewer for Reporting Services. This is the first product on the market which allows developers to display Reporting Services reports directly in Silverlight applications.It’s a true Silverlight control easily integrated into any Silverlight application and an up-to-date solution on the base of two powerful technologies: MS SQL Reporting Services и Silverlight 3.0.

Q: What advantages does MS SQL Reporting Services 2005 give to developers and end-users? A: Once I saw the funniest but at the same time the only possible answer: Great ). Probably, the member of the forum who wrote this was quite right. Today SSRS is one of the most widely used components for report creation. This can be explained by the large list of advantages among which are higher developer’s productivity and more opportunities for end-users control. Silverlight Viewer for Reporting Services developed by Perpetuum Software LLC is created on the base of SSRS. It allows developers to use all the advantages of this technology.

Q: Is it possible to print reports from Silverlight? A: At first sight the absence of printing ability in Silverlight 3.0 makes it an impossible thing. That’s why experienced developers may simply ignore this question. But a new version of Silverlight Viewer for Reporting Services 1.1 solves this problem of paramount importance. Printing Reporting Services reports from Silverlight viewer became possible. Now you can print any report you need without applying unnecessary efforts and exporting to other formats. Everything you need is to press printing button.

Q: Can I view reports in Silverlight without referring to MS SQL 2005 Reporting Service server? A: Of course, you can! With a new version of Silverlight Viewer for Reporting Services 1.1 you get an ability to work with reports created in MS SQL RS without setting MS SQL RS server. Now end-users can just open Silverlight viewer and start enjoying their work with reports. As you see a new version of Silverlight Viewer for Reporting Services 1.1 is able to help developers to solve many disturbing problems. Now the whole set of abilities used in desktop applications, out-of-browser mode, extended report abilities: PDF, Excel, Cvs, Xml, Mhtml, TIFF and advanced Html export are at their disposal.

It’s an open secret that Silverlight Viewer for Reporting Services 1.1 is a confident step on the software development market of corporate reporting systems. So why not avoid vain efforts and use the best?! Who knows, may be in this case you won’t post on forums…

QTP support for Silverlight, AJAX, GWT, Dojo, YUI now available

There has been no out-of-the-box support for most of the Web2.0 technologies by any of the tools providers out there. SilverlightLooks like HP has decided to go full force into it and capture all the more commercial functional testing tools market that was already dominated by them.  **HP is now planning to release a Web2.0 pack. The highlights of which will be:

  1. Making Web-Extensibility easier to use : Good to know HP acknowledge this fact. I have not seen much happening around this area, though it has been good 2+ yrs (the release of v9.5) since they made extensibility available. It will be a framework by the name Extensibility Accelerator (EA). AJAX
  2. Tighter support for Web2.0 apps : Till now, QTP had a Flex addin (by Adobe), now QTP is going to support Silverlight and AJAX apps.
  3. Better Object recognition and record/replay capabilities for Web 2.0 apps

Read the full article here

** Update: HP has already released the patch on top of QTP 10.0  This patch provides support for Silverlight 2-3 (under .NET addin),  and various toolkits – like AJAX, Google Web Toolkit (GWT), Dojo Toolkit, and Yahoo User Interface- under Web Extensibility. Once you have the Extensibility Accelerator installed, it can be seen under Tools menu option on QTP’s IDE.

The patch is released in two flavors:

  1. Web 2.0 Feature Pack with PreRequisites – In case you do not have MS Studio 2008 SP1 and .NET framework
  2. Web 2.0 Feature Pack without PreRequisites – In case you already have the above two softwares installed.

Silverlight User Interface Controls : Tutorial

Summary

Silverlight has over 3 dozen User Interface (UI) controls. .NET programmers already familiar with ASP.Net or (especially) WPF, will find using the Silverlight controls very natural and straight forward.

Figure 1-1. Silverlight Controls

Figure 1-1. Silverlight Controls (split in two to make it easier to view)

Silverlight controls were created to look great and provide extensive and customizable functionality right out of the box. Moreover, all of the standard controls can be modified in numerous ways to meet your needs.

The look and feel of the control can be tweaked through styles or can be entirely redesigned through templates, and the behavior of the controls can be modified through event handlers. In the rare cases when none of that is enough, you can create (or derive) your own customized controls as well.

This tutorial will cover event handlers. Styles, Templates and Custom Controls will be covered in future tutorials. .

A Note On The Design Surface

The current Visual Studio design surface is read-only. That is, you can drag and drop controls into the markup (or write the Xaml by hand) and the effects are seen immediately in the design surface, but you cannot yet drag or otherwise manipulate controls directly in design mode.

That is a temporary limitation. For now, one alternative is to use Expression Blend, and we have a full tutorial on Blend for Programmers that shows how to work with the two environments together.

Note that controls can also be created dynamically (in code, at run time) as explained at the end of this tutorial.

Layout Controls

The use of layout controls is both straight-forward and essential to the creation of Silverlight applications. Layout controls are used to manage the placement of other controls (including other layout controls!) in your Silverlight application. You can think of the layout controls as “containers.”

The three Layout controls you’ll use most often are:

  • Grid – essentially a table used for positioning objects in rows and columns.
  • StackPanel – used to position objects next to one another, or atop one another.
  • Canvas – used for absolute positioning (and unchanged from Silverlight 1.0)

They are listed in the order of how frequently they are used. And to be honest, if you learn Grid and StackPanel, you can probably program for a long time on just those two.

Grids

Grids (not to be confused with DataGrids) offer easy and exact placement by providing a table-like structure. You declare rows and columns, and then place controls into a specific row/column location (spanning across rows or columns as needed).

While you can tweak your grids to achieve very precise placement, the basic use of grids is extremely straight forward.

You typically declare a grid, declare its rows and columns and then start placing controls into specific cells (e.g., column 1, row 3). To see this at work, let’s create our first Silverlight Application: Easy Grid.

Creating The First Example – A Grid With Controls

Open Visual Studio 2008 and click on Create Project and then in the new project window you’ll want to create a C# project using the Silverlight Application Template.

Pick a location for your application and give it a meaningful name; be sure that you are building against the latest framework.

Figure 1-2. Creating A New Silverlight Project

Figure 1-2. Creating A New Silverlight Project (Click to view full-size image)

When you click OK you will next be asked if you’d like to generate a Web Site or a Web Application (using the top radio button) or just a test page (using the bottom radio button) or if you’d like to link to an existing web site; all as shown in the next figure.

Figure 1-3. Choose Simple HTML Test Page

Figure 1-3. Choose Simple HTML Test Page

If you create just a test page, the project is kept very simple, but if you generate a Web Site or Web Application Project, then Visual Studio creates two projects in your new solution; the Silverlight Application and a test application; excellent for test-based programming but more than we need right now.

Choose the second radio button (Test Page) and let Visual Studio create a simple application for you. If Page.xaml doesn’t open automatically, double click on it in the Solution Explorer. You should find that Visual Studio has guessed that you want a grid as your main container, and has created one for you and named it LayoutRoot. (Also note that the very first declaration in each “page” is a UserControl.

<UserControl x:Class="EasyGrid.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">

In fact a Page is a UserControl, and we’ll return to that relationship in a later tutorial.

The Grid definition created by Visual Studio 2008 looks like this:

<Grid x:Name="LayoutRoot" Background="White">
</Grid>

Many times, your entire application will go between the opening and closing Grid tags; other times you’ll replace the Grid with another container.

Defining Rows And Properties

You define the Rows for a table inside the Grid.RowDefinitions element. For each Row, you add a RowDefinition element, which itself may have various properties, including a specific height, or if you prefer you may set the height to be proportional to the available space or to take all the space not taken by other rows.

<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="30*" MaxHeight="70" />
<RowDefinition Height="40*" MaxHeight="70" />
<RowDefinition Height="*" MinHeight="30" MaxHeight="50" />
<RowDefinition Height="Auto" MinHeight="5" MaxHeight="30" />
</Grid.RowDefinitions>
</Grid>

Height=”Auto”

With Auto, the Grid’s space is distributed evenly based on the size of the content within the row.

Star or Proportional Sizing

In proportional sizing the value of a column or row is expressed in Xaml as *.

<RowDefinition Height="*"

However, you can give twice the space to one column or row as another by using 2* (or a 5:7 ration by using 5* and 7*).

<RowDefinition Height="30*"
<RowDefinition Height="40*"

If you combine this with a Minimum or Maximum Height you get finer control over the limits of the row’s range of sizes,

<RowDefinition Height="30*" MaxHeight="70" />
<RowDefinition Height="40*" MaxHeight="70" />
<RowDefinition Height="*" MinHeight="30" MaxHeight="50" />

Minimal or Controlled space

By default child elements of grid take up the least amount of space necessary to to accommodate the largest content within a cell in a given row or column. You can take greater control over positioning, however, by using the margin and alignment properties as described below

Sizing Units

To provide the most flexibility, Grid columns and rows are sized by GridLength objects which use the GridUnitType, which in turn allows you to choose among:

  • Auto (size based on the size properties of the object being placed in the grid)
  • Pixel (size in pixels)
  • Star (size based on a weighted proportion of the available space)

designating, if we choose, the minimum and maximum dimensions of each.

To see the effect of all this we’ll create five rows using different sizing rules. We’ll also create three columns with no sizing rules at all (!). We’ll then fill our grid with controls and take a look at some of the effects. Here is the code, which we’ll take apart piece by piece.

Example 1-1. The Xaml for EasyGrid

<UserControl x:Class="EasyGrid.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="30*" MaxHeight="70" />
<RowDefinition Height="40*" MaxHeight="70" />
<RowDefinition Height="*" MinHeight="30" MaxHeight="50" />
<RowDefinition Height="Auto" MinHeight="5" MaxHeight="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<TextBlock x:Name="FirstNamePrompt "
Grid.Row="0" Grid.Column="0" Text="First Name:" Margin="5"/>
<TextBox x:Name="FirstName"
Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"
Width="150" Background="Bisque" Margin="5" />

<TextBlock x:Name="LastNamePrompt "
Grid.Row="1" Grid.Column="0" Text="First Name:" Margin="5"/>
<TextBox x:Name="LastName"
Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
Width="150" Background="Beige" Margin="5" />

<TextBlock x:Name="SubscriberPrompt"
Grid.Row="2" Grid.Column="0"
Text="Subscriber?" VerticalAlignment="Bottom" />
<CheckBox x:Name="PlanA" Grid.Row="2" Grid.Column="1"
Content="Plan A" IsChecked="true"
VerticalAlignment="Bottom" />
<CheckBox x:Name="PlanB" Grid.Row="2" Grid.Column="2"
Content="Plan B" VerticalAlignment="Bottom" />

<TextBlock x:Name="Hello" Text="Hello"
Grid.Row="3" Grid.Column="2" VerticalAlignment="Bottom"/>

<TextBlock x:Name="World" Text="World"
Grid.Row="4" Grid.Column="2" VerticalAlignment="Bottom"
FontFamily="Comic Sans MS" FontSize="24"
FontWeight="Bold" Margin="0,20,0,0"/>
</Grid>
</UserControl>

The result of the Xaml code is shown in

Figure 1-4. The Xaml as Design

Figure 1-4. The Xaml as Design

First, it is important to understand that the Xaml shown in Example 1-1 is all that is needed to produce the Silverlight control shown in Figure 1-4. It is true that you can’t see the rows and columns, but that is easily remedied. Find the declaration of the Grid and set its ShowGridLines property to True (Intellisense will help as shown inFigure 1-5

Figure 1-5. Adding Property ShowGridLines and setting it True

Figure 15. Adding Property ShowGridLines and setting it True (Click to view full-size image)

When you do, the grid lines become visible; which can be very useful during design, as long as you remember to set the property to false before you post your Silverlight application!

Figure 1-6. ShowGridLines Makes The Alignment Very Visible

Figure 1-6. ShowGridLines Makes The Alignment Very Visible (Click to view full-size image)


Unpacking the Xaml

The first lines create the Grid and define how the rows will share the space.

<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="30*" MaxHeight="70" />
<RowDefinition Height="40*" MaxHeight="70" />
<RowDefinition Height="*" MinHeight="30" MaxHeight="50" />
<RowDefinition Height="Auto" MinHeight="5" MaxHeight="30" />
</Grid.RowDefinitions>

As described above, the RowDefinitions define five rows. The first has a fixed height of 50. The second and third will float, but in a 3:4 proportion with one another, but each with a maximum height of 70. The next row will take all the remaining space, but will never be allowed to shrink to less than 30 nor grow to more than 50. The final row will size itself to the object placed in the row, but yet is constrained to no less than 5 and no more than 30.

After the column definitions we define a TextBlock and a TextBox. We’ll discuss these controls in more depth later, but the former is typically used as a label and the latter is used to allow the user to put in text.

<TextBlock
x:Name="FirstNamePrompt "
Grid.Row="0"
Grid.Column="0"
Text="First Name:"
Margin="5"/>

The TextBlock has five parameters. They can be aligned one below the other, or strung out all in a line, any way you like. The first parameter is the name (FirstNamePrompt) and is used to allow you to address the object in code. If you give an object in Xaml a name, and save the file, that object is available with no further declaration in your methods

Thus, if you save this file, you will be free to write

FirstNamePrompt.Text=”Hello”

From any method of this class, and the compiler will know exactly what you mean!

The Grid.Row and Grid.Column properties are called extended properties and are really “borrowed” from the immediately surrounding grid to position the TextBlock inside the appropriate cell.

The Text property does just what you expect, it fills the TextBlock with that text.

Margin is a fascinating property, and we’ll return to it a couple times. For now, I’ll mention that it takes three forms:

  • A single value, which gives a margin of that value “all around” – that is left, right, top and bottom
  • Two values in which case the first is divided evenly among the left and right margin and the second is divided evenly among the top and bottom
  • Four values, in the order Left, Top, Right, Bottom.

The TextBlock label in the first column is followed by an (input) TextBox in the second column. The properties are very similar except that you must declare the width of your TextBox and we choose here to give the TextBox a background color.

The next pair are much like the first.

The third row is filled by a TextBlock and two CheckBox controls. Note that they are aligned by setting their VerticalAlignment properties and that the first CheckBox has its IsChecked property set to True so it will be checked when the page is first shown.

The fourth row has a TextBlock that displays Hello and the final row has a TextBlock that displays World, but does so setting the FontFamily, FontSize and FontWeight.

StackPanels

StackPanels are typically combined with other layout controls. They allow you to stack objects one on top of the other, or next to each other (like books on a shelf).

One convenience of a StackPanel is that you do not have to provide the position of the objects held by a StackPanel, they are positioned relative to the object declared earlier in the Stack..

In the following example, you will stack a TextBlock on top of a TextBox which in turn will sit on top of a Button that will sit on top of a CheckBox (shades of Yertle the Turtle!)

<StackPanel Background="Beige" Orientation="Vertical" >
<TextBlock Text="Your name?"
HorizontalAlignment="Left" Margin="10,2,0,1"/>
<TextBox Width="150" Height="30"
HorizontalAlignment="Left" Margin="10,2,0,1"/>
<Button Content="Submit this information"
HorizontalAlignment="Left"
Margin="10,2,0,1" Height="30" Width="150" />
<CheckBox Content="With Zing!" HorizontalAlignment="Left"
Margin="10,2,0,1" />
</StackPanel>

There is quite a bit of information in this code snippet, so let’s unpack it piece by piece.

The top and bottom lines show the declaration of the StackPanel in the Xaml file. The StackPanel is declared with two attributes: a BackgroundColor (Beige) and an Orientation (which must be either Vertical or Horizontal).

There are many other attributes you can set, as will be true for nearly all the controls These, along with the methods are conveniently listed in the documentation,

Figure 1-7. Documentation Showing Stack Panel Members

Figure 1-7. Documentation Showing Stack Panel Members (Click to view full-size image)

By setting the Orientation to Vertical we are stacking its contents one on top of another rather than side by side.

Within the StackPanel, the four objects are declared, and the order of their declaration will determine the order in which they are stacked. Each is set with its TextAlignment property set to Left so that they will align, and each has its Margin property set. Let’s dig just a bit deeper into the Margin property by looking up its definition in the documentation,

public Thickness Margin { get; set; }

The Margin property is actually an object of type Thickness. As noted earlier, when you are declaring a Thickness object in Xaml you may do so in one of three ways:

First, you may provide a double that will be the margin for the margin on all four sides (left, top, right, and bottom) uniformly around the object. Thus, you might write

<Button Content="Submit this information"
HorizontalAlignment="Left"
Margin="100" Height="30" Width="150" />

Thereby isolating the button with a margin of 100 on either side and above and below,

Figure 1-8. Button Margins

Figure 1-8. Button Margins

Notice that to accommodate the oversided margin, the width of the button was compromised!

The second way to declare a Thickness (and in this case, a Margin) is to provide the sum of the sides and the sum of the top and bottom (thus, the sides must be equal and the top and bottom must be equal,

<Button Content="Submit this information"
HorizontalAlignment="Left"
Margin="50,20" Height="30" Width="150" />

The effect of this declaration is that the left and right margins are 25, and the top and bottom margins are each 10.

Finally, you may declare each independently, as long as you do so in the required order:

Figure 1-9. Margins are a Thickness Object

Figure 1-9. Margins are a Thickness Object

That is: Left, Top, Right, Bottom; or in this case, the Left margin is 10, the Top margin is 2, the Right margin is 0 and the Bottom margin is 1.

Once the four controls are placed in the stack Panel, and aligned, the stack panel is responsible for their placement,

Figure 1-10. Stack Panel At Work

Figure 1-10. Stack Panel At Work

Notice that the StackPanel is responsible for its own background color, and for stacking its contents (the four controls) but each control is responsible for its own alignment and margins.

Horizontal Stack Panels

If we want to shift the stack panel to align all the controls into a single row, we’ll want to make a few additional changes. Not all controls default to aligning in the same way (top, center or bottom) so we’ll explicitly set their vertical alignment to “Center,” just as we previously set their horizontal alignment to “Left”. Let’s also set the margins to provide a bit of space between each object as the default is to abut each object.

<StackPanel Background="Beige" Orientation="Vertical" >
<TextBlock Text="Your name?"
HorizontalAlignment="Left" Margin="10,2,0,1"/>
<TextBox Width="150" Height="30"
HorizontalAlignment="Left" Margin="10,2,0,1"/>
<Button Content="Submit this information"
HorizontalAlignment="Left"
Margin="10,2,0,1" Height="30" Width="150" />
<CheckBox Content="With Zing!" HorizontalAlignment="Left"
Margin="10,2,0,1" />
</StackPanel>

Note that I set the left margin on the text box to 5 (rather than 10) to bring it a bit closer to the TextBlock that serves as its label.

Figure 1-11. Stack Panel in Horizontal Orientation

Figure 111. Stack Panel in Horizontal Orientation (Click to view full-size image)


Control Events and Event Handlers

In Silverlight each class declares whether it is supported by managed code or not, by including (or not including) the x:Class attribute in its root element. These tutorials will assume you are working in managed code, and that this attribute is therefore present.

When you create a managed code Silverlight application in Visual Studio, the Class attribute is placed for you. Create a new application and call it EventHandler, and then examine the first few lines, as shown here,

<UserControl x:Class="EventHandler.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">

Declaring Event Handlers

There are two ways to declare event handlers in Silverlight: in the Xaml file or in the code-behind. If you declare event handlers in Xaml you cannot add parameters. A typical event handler declaration in XAMl might look like this

<Canvas Loaded="Canvas_Loaded">
<Button x:Name="myButton" Content="Hello"
Canvas.Left="10" Canvas.Top="10" />
</Canvas>

Here I’ve deleted the Grid created by Visual Studio, and declared a Canvas object. I’ve also assigned an event handler named “Canvas_Loader” to the Loaded event (a pre-existing event common to all canvases that fires when the Canvas is loaded (created).

I then declare a button in the Xaml and set its content to Hello.

This code appears in Page.xaml. In the code behind file, Page.xaml.cs, I must now implement the event handler with the name I’ve promised to use,

private void Canvas_Loaded(object sender, RoutedEventArgs e)
{
myButton.Content = "Please Click Me";
}

The first thing to notice is that the name of the method is identical to that as declared in the Xaml. The second is that this method follows the pattern of all .NET event handlers: it returns void and takes two parameters: the first of type object (and containing a reference to the object that raised the event) and the second of type EventArgs or a type that derives from EventArgs; in this case RoutedEventArgs. We’ll come back to RoutedEventArgs in just a moment.

The implementation is that when the Canvas is loaded it grabs the button declared in the Xaml file and changes its Content property from “Hello” to “Please push me”,

Figure 1-12. Content Property Changed

Figure 1-12. Content Property Changed

Even in this incredibly simple example there are two important things to notice:

  1. You did not have to declare myButton in the code behind; it was known simply by declaring it in the Xaml.

  2. The button adjusted its size to accommodate the larger string.

Declaring Event Handlers In Code

I admit it, I have a strong preference for declaring all event handlers in code. I believe it is better encapsulation, making for more scalable and more maintainable code. But this is a personal opinion.

In any case, if you want to declare your event handlers correctly in code, Visual Studio makes it very easy to do so. The most common way is to wire up the event handlers in the OnLoaded event handler, with that event (Loaded) wired up in the Page’s constructor.

To see this, return to your previous code and remove the event handler from the Xaml. While you’re there, add a check box as shown here,

<!-- <Canvas Loaded="Canvas_Loaded"> -->
<Canvas >
<Button x:Name="theButton" Content="I'm Indented!"
Canvas.Left="150" Canvas.Top="20" />

<CheckBox x:Name="RushOrder" Content="Rush"
Canvas.Left="50" Canvas.Top="20" FontSize="18" />
</Canvas>

Notice that the original Canvas is commented out, and replaced by a Canvas that does not have an event.

Save the Xaml file and open the code behind.

In the constructor, type Lo. Intellisense will pop up and offer to help you create the EventHandling code, landing on the event Loaded, which is exactly what you want. The tip (next to the Intellisence box) shows the type of the event.

Figure 1-13. Intellisense Helps Create Event Handler

Figure 1-13. Intellisense Helps Create Event Handler (Click to view full-size image)

We’ll return to the fact that Loaded is a RoutedEventHandler shortly. Press tab to accept Loaded and type += to begin adding the delegate. (If delegates and events are new to you, you may want to read this article. It’s a bit old, but still accurate. You can also read extensively about delegates and events in any book on .NET 3.5 or C# or VB.

Intellisense will walk you through each step of wiring up the event handler, and if you let it, will also create the stub of the event handler method, ultimately placing your cursor in the method which it prefills with an exception (in case you forget to add a meaningful implementation.

public Page()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);

}

void Page_Loaded(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}

Delete the exception and register event handlers for the common events for your button (click) and your checkbox (Checked and Unchecked)

void Page_Loaded(object sender, RoutedEventArgs e)
{
myButton.Click += new RoutedEventHandler( myButton_Click );
RushOrder.Checked += new RoutedEventHandler( RushOrder_Changed );
RushOrder.Unchecked += new RoutedEventHandler(RushOrder_Changed);

}

Be careful here, Intellisense will want to name the methods for Checked and Unchecked RushOrder_Checked and RushOrder_Unchecked respectively, but there is no need for two methods. We’ll override that by typing in the name we want, RushOrder_Changed, which will cause both events to use a shared event handler.

In the shared event handler, we’ll check the IsChecked status of the checkbox and if it is checked, we’ll change its text to all upper case (just so we know the event handler is working).

void RushOrder_Changed(object sender, RoutedEventArgs e)
{
if (RushOrder.IsChecked == true)
{
RushOrder.Content = "RUSH";
}
else
{
RushOrder.Content = "Rush";
}
}

Note to C# programmers, we must write

if (RushOrder.IsChecked == true)

and not

if (RushOrder.IsChecked)

because IsChecked is of the new C# 3.0 type nullable bollean ( bool?) which indicates that it may have three states, not two: true, false or null.

Creating Controls Dynamically

In Silverlight, all Xaml controls are isomorphic with CLR objects. That is, anything you can create in Xaml you can create in code.

Where you might write,

<Button x:Name="myButton" Content="Hello" />

You can also write

Button myButton = new Button();
myButton.Content = "Hello";

While it is possible to create all your controls and objects in code, best practices dictate that it is usually better to do so in Xaml. The most compelling reason is that Xaml is highly “toolable” – that is, it lends itself to round-trip modification in tools such as Visual Studio and Expression and thus is easier to scale, modify and maintain.

On the other hand, there are times that you can’t know at design time which or how many objects you’ll need, and the ability to create objects dynamically can be a fundamental requirement.

We can make a minor modification to our existing program to add another button on the user’s request. Add the following button to the Xaml file (note that we also name the canvas!)

<Canvas x:Name="myCanvas">
<Button x:Name="myButton" Content="Hello"
Canvas.Left="10" Canvas.Top="10"/>
<Button x:Name="Another" Content="Add Another"
Canvas.Left="10" Canvas.Top="50" />
<CheckBox x:Name="rushOrder" Content="Rush"
Canvas.Left="50" Canvas.Top="10" />

The effect is to add a button to the page with the words “Add Another.” When the user clicks on this button, we want to add a button to the UI and we want that button to have its own size, position and behavior.

We do all of that in the code behind.

Creating a Button Dynamically

Save the .xaml file and open Page.xaml.cs

The first thing to do is to add an event handler for the new button,

Another.Click += new RoutedEventHandler(Another_Click);

And to add its implementation, in which you’ll create a new button and set its properties,

void Another_Click(object sender, RoutedEventArgs e)
{
Button b = new Button();
b.Content = "I live!";
b.SetValue(Canvas.LeftProperty, 10.0);
b.SetValue(
Canvas.TopProperty,
this.newButtonPosition);
this.newButtonPosition += 30.0;
b.Width = 100;
b.Height = 20;
b.Click +=new RoutedEventHandler(new_button_click);
myCanvas.Children.Add(b);
}

Because the canvas’s Left and Top are not actually properties of the Button (but are extended properties) you set them with the SetValue method, which takes two parameters. The first is the actual name of the property you want to set (Canvas.LeftProperty and Canvas.TopProperty) which is not difficult to find as Intellisense will supply it) and the second is the value (in this case a double).

Because I want to be able to click this button more than once, and I don’t want the new buttons overwriting each other, I need a member variable to keep track of the top value,

private double newButtonPosition = 100.0;

After I set it, I can then increment it so the next button will fall below the previous,

b.SetValue(
Canvas.TopProperty,
this.newButtonPosition);
this.newButtonPosition += 30.0;

The result is very satisfying,

Figure 1-14. Adding Dynamic Buttons

The second thing to notice about the Button we are adding is that we are also adding an event handler registration,

b.Click +=new RoutedEventHandler(new_button_click);

This means that every button that is added (each of the three shown in Figure 1-8) is registered to call new_button_click when it is clicked. You’ll need to write that event handler into your Page.xaml.cs file,

void new_button_click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
btn.Content = "Don't do that!";
btn.IsEnabled = false;
}

As the buttons are clicked, they change their message and become disabled,

Figure 1-15. Disabled Dynamic Buttons

Finally, none of this will work if you don’t add the buttons to the page. In this case, however, you don’t want to add them to LayoutRoot as their positioning is in terms of a specific canvas, so you’ll add them to that canvas,

myCanvas.Children.Add(b);

When you run the program, they are members of that canvas, just as surely as if you had added them individually in the Xaml file.