Downloads
SilverlightFeatureBrowser.zip

Click here to download the code for this article.

Click here to read "Take a Tour of Silverlight 4's Top 10 New Features: Part 2".


It seems like only yesterday that Microsoft introduced the beta version of Silverlight 3 at the Mix 09 conference in Las Vegas. However, Microsoft amazed everyone when the final version of v3 saw daylight in July 2009. Everyone was expecting Silverlight 3 to be the version we would end the year 2009 with.

Microsoft has been talking about a nine-month release cycle for Silverlight, and the company kept its word. At PDC 09 in November 2009, against all expectations, Silverlight 4 made its appearance. One might think that in the short time span, Microsoft didn't add many new features. However, nothing could be further from the truth: Silverlight 4 is packed with tons of improvements to existing features, and it includes many new features as well.

In this two-part series, I’ll take you on a tour of the 10 most striking new features available in Silverlight 4. This first article in the series will explore 5 of the 10 features; Part II will cover the remaining 5 features.

So that you can see these new features in action, I've created an application called SilverlightFeatureBrowser, which is based on the Navigation Application template introduced with Silverlight 3. A Navigation Application lets you browse pages inside a Silverlight application; in this case, each page contains a Silverlight feature we’ll be looking at. The most important part in such an application is the Frame control, which is comparable to an IFRAME in HTML. To display a page in the Frame, you can specify the URL of the page you want for the Source property of the Frame. The Page is the second most important aspect of this template: Frame controls can’t display a UserControl; they need a Page instead. Not to worry though, because a Page is similar to a UserControl.

One last note about the code: Silverlight 4 is Visual Studio 2010 (VS2010) only. The most recent version of VS2010 is Beta 2, which you can download for free at http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx. Silverlight 4 in VS2010 features a fully functional designer view and many improved dialogs for easier Silverlight development. Let's look at the first 5 of the 10 new features I'm highlighting.

1. Printing in Silverlight

One of the most important capabilities missing in Silverlight 3 is support for printing out-of-the-box. Printing is an important feature for business applications. People want to print overviews, reports, and so on—and not having print support was, for some companies, still a barrier to making the move to Silverlight.

Stating that Silverlight 3 didn’t support printing isn’t entirely correct. You could write content of a control to a WriteableBitmap, which could be printed or saved. Still, printing in this way was quite cumbersome and required more work than it should.

Silverlight 4 introduces a printing API that’s simple to use. You can select which content you want to print, and you can instruct Silverlight to print a specific control, such as a Grid or a Canvas, and its contents. In this way, you're printing what you see on-screen. However, you also can print content that’s not visible. You can hook into the printing process, dynamically add controls from code, and print a document that’s different from the on-screen content. A printer-friendly version of a page is an example of where this functionality can come in handy.

Let’s look at a sample. In Figure 1, a Canvas called PrintCanvas is created with some images inside. When we click on the Print button, we want to print the content of the Canvas. However, let’s say we want to add a title to our work when it's printed. The resulting print output is shown in Figure 2.

The single most important class for performing print is the PrintDocument class, located in the System.Windows.Printing namespace. You can specify what to print by setting the PrintPageEventArgs.PageVisual in the PrintPage event handler to the control you want to print. Finally, you call the Print method, which is shown in Figure 3.

Note that to add the extra title on the printed document, you handle the StartPrint event. It’s called after the Print() method, but before the PrintPage event is called. Therefore, you can use it to add content or hide elements to have complete control over what is printed. Similarly, the EndPrint event is called after printing is done; you can use it to remove content you added dynamically.

2. Dragging Content into a Silverlight Control

In previous versions of Silverlight, the only way you could get content from the local machine into the Silverlight application was to use the OpenFileDialog, which creates a read-only stream to the selected file so Silverlight can read the content. If you wanted to add multiple files, you had to go through the same process several times. While this was a reasonable experience, we've all grown more accustomed to the notion of dragging: selecting a file in, for example, Windows Explorer and “moving” it to its new location.

Silverlight 4 can accept dragged-in files. You can define a control within a Silverlight application as a drop target. You can drag in one file or a list of files, but dragging in a directory is not supported.

You can easily see the dragging support by making some changes to the application we looked at when we were talking about printing. So that a UIElement will support items being dropped on it, you must set the AllowDrop to True. Several events have been added to support dragging, namely DragEnter, DragLeave, DragOver, and Drop. You can use the first three, for example, to highlight a control when content is being dragged over it. The fourth event fires when an object is dropped onto the UIElement. Here’s the Canvas called DropCanvas, extended so you can drop files on it:

<Canvas Height="400" x:Name="DropCanvas" AllowDrop="True" Drop="DropCanvas_Drop" > 

In code, you can now handle the Drop event.  This event has DragEventArgs, which contains a Data property that is of type IDataObject. If the drop was valid (meaning what was dropped on the control was indeed a file), you can access the file or the list of files that were dropped using the GetData method. This in turn returns an array of FileInfo objects, which you can then read out. The code in Figure 4 performs these actions. This code determines whether the file is an image (it checks for the file extension) and if it is, creates a new BitmapImage, passing in the dropped file. After that, a new Image control is created and its source is set to the BitmapImage instance.

3. Rich Text Area

You can now allow users to enter more than plain text by using the RichTextArea control. As the name of the control implies, it's possible to enter rich text, including bold, italic, and underline. It doesn’t stop there though; it's also possible to embed images inline, add XAML content for richer markup, and add hyperlinks to the text in the control. The control also offers BiDi support so you can use the control for right-to-left editing and access the clipboard to support cut, copy, and paste operations.

The text is entered as XAML behind the scenes, so the control is rendering the result of that XAML. It uses typical XAML elements for its text markup, such as the Paragraph, the Run, and the LineBreak. There is no real Text property on the control to get the entered text without the markup. To get the contents, you can use the Blocks collection to loop through the content.

By default, the control does not have any buttons attached to it. Let’s create a simple text editor with just a few options. Figure 5 shows a screenshot of the editor. All actions on the rich text area are quite similar, so we’ll look only at the action that sets the selected text to bold.

When clicking on the bold button, you need to check that the text selection isn’t empty. If it isn’t, check if the text is already bold. If yes, set it back to normal; if not, set it to bold. The following code shows these actions:

private void BoldButton_Click(object sender, RoutedEventArgs e)

\\{

            if (rtb.Selection.Text.Length > 0)

       \\{

       if (rtb.Selection.GetPropertyValue(Run.FontWeightProperty) is FontWeight &&

                        ((FontWeight)rtb.Selection.GetPropertyValue(Run.FontWeightProperty)) ==                      FontWeights.Normal)

                        rtb.Selection.SetPropertyValue(Run.FontWeightProperty, FontWeights.Bold);

            else

                        rtb.Selection.SetPropertyValue(Run.FontWeightProperty, FontWeights.Normal);

                        rtb.Focus();

            \\}

\\}

4. Data Binding Improvements in Silverlight 4

Data binding is the infrastructure that makes it possible to bind the value of an object's property to the value of a control's property. For example, using data binding you can create a link between the FirstName property of an Employee instance and the Text property of a TextBlock control. Or you can bind a collection of Employee instances to a ListBox. Data binding in Silverlight allows for easier and faster development of data-driven applications.

While already powerful in Silverlight 3, the data binding platform still had a few missing options compared to WPF, from which it inherited the data binding mechanism in the first place. In Silverlight 4, more options have been added: TargetNullValue, StringFormat, and FallbackValue.

In the sample application, a class Employee is created in the Model directory. We're binding to an instance of this class and we will see the new options in action. This is the instance of the class that was created, which is set as DataContext for the entire Page:

employee = new Employee() \\{ FirstName = "Gill", LastName = "Cleeren", Salary = 2000, Department = "IT", Manager = null, BirthDate = new DateTime(1979, 1, 1) \\};

this.DataContext = employee;

The TargetNullValue allows you to specify in the data binding expression a value that will be shown when the property's value evaluated by the data binding engine returns null. In previous versions of Silverlight, we had to create a converter to catch this. As you can see, the Manager property is null, so when displayed, the value specified for the TargetNullValue binding extension property will be shown instead.

<TextBlock x:Name="ManagerTextBlock" Text="Manager"></TextBlock>

<TextBlock x:Name="ManagerValueTextBlock" Text="\\{Binding Manager, TargetNullValue=None\\}"></TextBlock> 

StringFormat allows us, in the data binding expression, to pass in how the string should be formatted. For example, if we're returning a double value that represents a salary, we can pass in using the StringFormat that the value should be displayed as a currency. Again, normally we would have written a converter for this. In the code below, we're using the StringFormat to format the value into a currency.

<TextBlock x:Name="SalaryTextBlock" Text="Salary"></TextBlock>

<TextBlock x:Name="SalaryValueTextBlock" Text="\\{Binding Salary, StringFormat=C\\}"></TextBlock> 

Also, formatting into a date is possible, as shown below:

<TextBlock x:Name="BirthDateTextBlock" Text="Birthdate" ></TextBlock>

<TextBlock x:Name="BirthDateValueTextBlock" Text="\\{Binding BirthDate, StringFormat=MM/dd/yyyy\\}"></TextBlock>

The FallbackValue property allows us to pass in a value that will be displayed when the data binding operation is not successful. For example, let’s say we would like to bind to the ManagerOf property. However, our Employee instance does not define this property. The value specified in the FallbackValue is used in this case:

<TextBlock x:Name="ManagerOfTextBlock" Text="Manager of" ></TextBlock>

<TextBlock x:Name="ManagerOfValueTextBlock" Text="\\{Binding ManagerOf, FallbackValue=NA\\}"></TextBlock>

Figure 6 shows the new data binding features in action. One last word on the data binding experience: Visual Studio 2010 really enhances the way we can create data bindings. First, there’s the much improved dialogs part of the Properties window. Second, when creating bindings manually in XAML code, you now get IntelliSense within the markup extensions. 

5. Right-clicking

Traditionally, when right-clicking in a Silverlight application, the default Silverlight context menu is shown, giving access to the Microsoft Silverlight Configuration dialog, as shown in Figure 7.

 Up until Silverlight 4, this could not be overridden out-of-the-box. However, many applications would benefit from this option, such as an editor where we can right-click in the text area and select cut, copy, or paste.

In Silverlight 4, a MouseRightButtonDown and MouseRightButtonUp event is now available on all UIElement controls. These events let you perform an action to handle the right mouse-click, most of the time displaying a context menu. Both events use MouseButtonEventArgs, the same class used for left mouse-clicks.

Let’s apply this to the image sample we already used a couple of times. When right-clicking, we want to display a context menu in which we can select to delete the image from the canvas, as shown in Figure 8. The first thing that we need to do is add the two events on the Image control:

<Image Canvas.Left="17" Canvas.Top="98" Height="195" MouseRightButtonDown="Image_MouseRightButtonDown" MouseRightButtonUp="Image_MouseRightButtonUp" x:Name="Image1" Source="/SilverlightFeatureBrowser;component/images/Tulips.jpg" >

</Image>

In the MouseRightButtonDown, we set e.Handled to true. Doing so will cause Silverlight not to show the default context menu:

private void Image_MouseRightButtonDown(object sender, MouseButtonEventArgs e)

\\{

            e.Handled = true;

\\}

The code in the MouseRightButtonUp event handler can then call out to show a custom control (the full code for this control is available in the sample application):

private void Image_MouseRightButtonUp(object sender, MouseButtonEventArgs e)

\\{

            Image image = sender as Image;

       if (image != null)

 

       \\{

                        ContextMenu contextMenu = new ContextMenu(PrintCanvas, image);

                        contextMenu.Show(e.GetPosition(LayoutRoot));

            \\}

\\}

Looking Ahead

In this article, we looked at what I personally believe are 5 of the 10 most interesting new features in the new version of Silverlight 4. Part II will look at an additional 5 features. Remember, this list is far from complete. There’s both a long number of enhancements to existing features as well as more new features than explored here. With a release so close to its predecessor, Microsoft surely has many surprises coming in the next months for Silverlight developers.