Only 4 months have passed since 10 July 2009 - when Silverlight 3.0 has been released - and the last 18th November at the PDC the first beta of Silverlight 4.0 has been launched to the world. In this short time great work has been accomplished by the Silverlight team, adding some impressive new features, tuning some others and fixing a lot of bugs.
During this short time the development has been driven from people which have sent more then 12000 votes on a special site created to collect the preferences (http://silverlight.uservoice.com/). If you take a look at this list you will see that many of the votes are now marked as "planned for Silverlight 4.0" and in fact you can discover the corresponding feature in the beta bits.
In this article I've decided to select five significant features that add a great value to the platform. Curiously if you scan the list of the site you will find them in the first positions. They include Printing and Webcam support, HTML embedding, rich text edit and full trust application in out of browser mode.
Download source
Webcam and Microphone
The capability of capturing a webcam is for sure one of the most expected news in Silverlight and also is the source for one of the most hilarious gag during the keynote at the Professional Developer Conference 2009. But if the webcam can easily become popular and amusing there are a lot of applications that can take advantage of it. I'm thinking at barcode scanning, useful for e-commerce and kiosk applications and at communication platforms that transmit the captured video and audio using the new UDP multicast.
Capturing the webcam is pretty simple and does not require any special knowledge about video encoding. Remember that all you can do for the video is also available for audio devices so you can capture the microphone as well. The first thing to do is to discover video (and audio) devices installed on the client. There is a dedicated class that does all the work exposing both the video devices collection and the default device.
VideoCaptureDevice videoDevice =
CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
The VideoCaptureDevice class gives you some information about the attached device. You can get a FriendlyName and the size of the video. After this you need to create an instance of CaptureSource and to assign the device to it. CaptureSource is the class responsible for pumping data from the device to a target VideoBrush that shows the captured stream.
CaptureSource source = new CaptureSource();
source.VideoCaptureDevice = device;
Now you are ready to start the capture, but you have to ask the user to grant to the plugin the access to the device. This is an obvious security concern to avoid unwanted captures to be spreaded to the web. When the access has been granted you can connect the CaptureSource with the VideoBrush and start capturing.
if (CaptureDeviceConfiguration.AllowedDeviceAccess
|| CaptureDeviceConfiguration.RequestDeviceAccess())
{
targetBrush.SetSource(source);
source.Start();
}
These three simple steps let you publish the stream coming from the cam to the plugin surface in order to show the live output to the user. When the streaming has begun you can take a snapshot of the source in a bitmap. To do this you have to invoke the AsyncCaptureImage and wait the callback to be called:
source.AsyncCaptureImage(
bmap =>
{
// do what you want with captured bitmap
});
In a scenario where you need to send the stream to the network you have another couple of classes supporting your needs. VideoSink lets you catch the frames pulled by the cam just before it renders to the brush. This class needs to be inherited by your class. For the audio there is a similar AudioSink.
WebBrowser & HTMLBrush
One of the most requested features is the capability to load HTML into a Silverlight application. Many current applications are written in HTML so it is an understandable request. The answer of the Silverlight team to this need is the addition of two components: the WebBrowser and an HtmlBrush. The WebBrowser control is almost similar to the Windows Forms's component. It can be added to a xaml page but you have to be aware that it works only when the plugin is installed in Out of Browser. This is a security concern to avoid cross-site scripting issues. So when the plugin runs into the browser, the WebBrowser component will show only a placeholder.
<WebBrowser x:Name="BrowserControl" />
Once the component has been put into a page there are two methods to start navigation. The Navigate() method opens an Uri on the web and the NavigateString() method injects an HTML string into the control. While the NavigateString does not have any limitations, the Navigate method can navigate only on the server from where the XAP comes, unless you have requested a full trust installation.
You also have to be aware that the WebBrowser control does not render the transformations and plane projections and is not subject to the Opacity property. To apply these effects to the plugin you need to render the content to an HtmlBrush. If you have already used a VideoBrush you know how the HtmlBrush works. It must be used in conjunction with a WebBrowser control that is the source for the brush but unlike the VideoBrush you have to create the association in the code-behind of the page. This is because the HtmlBrush is unable to detect the download of the page so the correct way is to attach the LoadCompleted event of the WebBrowser and to create the brush in the event handler. Here is a short snippet:
public MainPage()
{
InitializeComponent();
this.BrowserControl.LoadCompleted += new EventHandler(BrowserControl_LoadCompleted);
}
void BrowserControl_LoadCompleted(object sender, EventArgs e)
{
HtmlBrush brush = new HtmlBrush();
brush.SetSource(this.BrowserControl);
areaToPaint.Fill = brush;
}
Again, the brush is not able to update itself when the browser navigates to another address. You have to update the brush by yourself using the Redraw() method. In the sample provided in the download, I've used a timer to keep the brush in sync with the WebBrowser.
Full Trust in Out of browser
The last release of Silverlight 3.0 introduced a new feature called "Out of Browser experience". It allows a developer to install locally a Silverlight application enabling the user to quick access. This was one of the most appreciated news in this release but it was affected by some limitations due to the fact that the plugin runs in the same sandbox of the browser so it is difficult to create applications taking advantage of this mode.
With Silverlight 4.0 we can easily configure an application to request full trust permissions when it is installed on the client computer. This configuration, which has to be added to the AppManifest.xml, can be configured with a checkbox in the project settings.
What you get when this checkbox is flagged is a relaxed security model that allows you to:
- Access Cross Domain locations without a policy file
- Get a full file path from Open/SaveFileDialog and File Manipulation API
- Enter fullscreen and Open/SaveFileDialogs without user-initiation requirement
- Use the keyboard input while in full-screen
- Access to My Documents folder
- Access to COM interop (Windows only)
In the example code of this article you will find a small application that shows the disk drives of the client and shows the drive letter, the volume name and the total and available space accessing a COM component which is often used in classic ASP applications. When the application is installed, the user will be asked to accept the full trust mode with a special form:
Printing
On the top of the list of requests on the user voices website there stands one of the most important features required to create a real world line of business applications. It is the capability to send content to the printer that does really matter when you need to create charts, reports and invoices.
The printing support of Silverlight 4.0 is very slim in this beta and is very close to what we can do in Windows Forms applications. The trick is done by the PrintDocument class that can take a portion of the visual tree, rasterize it and then send it to the printer as a bitmap. The code is simple and lets you know the progress of the printing attaching a couple of events.
private void Print()
{
PrintDocument document = new PrintDocument();
document.DocumentName = "People";
document.StartPrint += new EventHandler<StartPrintEventArgs>(document_StartPrint);
document.EndPrint += new EventHandler<EndPrintEventArgs>(document_EndPrint);
document.PrintPage += new EventHandler<PrintPageEventArgs>(document_PrintPage);
document.Print();
}
void document_EndPrint(object sender, EndPrintEventArgs e)
{
LogTextBlock.Text = "Print completed";
}
void document_StartPrint(object sender, StartPrintEventArgs e)
{
LogTextBlock.Text = "Print started";
}
void document_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageVisual = this.printImage;
}
As you can see there are only a few properties to set. Particularly when you catch the PrintPage event you have to set the PageVisual that is the element of the visual tree where the rendering will start.
RichText edit
The last feature for which I would like to speak about is the new RichTextArea control. This control enables you to edit some rich text inside the plugin and has some interesting capabilities. First of all you have to be aware that the content to be edited is a rendering of XAML code. There are a number of tags like Paragraph, Run, LineBreak and Hyperlink which you can use to render the text inside the control.
<RichTextArea x:Name="rta" TextWrapping="Wrap" HorizontalAlignment="Stretch" BorderThickness="0">
<Paragraph FontFamily="Georgia" FontSize="24" TextAlignment="Center">
This is some text...
<LineBreak />
</Paragraph>
...
</RichTextArea>
The control does not have any buttons or commands to let the user edit the styles of the content. These have to be added by the developer that can programmatically change the properties of the tags using a Selection object.
This line sets a Bold style on the selected text:
rta.Selection.SetPropertyValue(Paragraph.FontWeightProperty, FontWeights.Bold);
Obviously you can also read the current style for each property with the GetPropertyValue method. Another way to insert elements is the usage of the Insert() method of the Selection object, but in this release it allows the developer to only add Hyperlinks to the text.
Hyperlink link = new Hyperlink();
link.Inlines.Add(rta.Selection.Text);
link.NavigateUri = dialog.Uri;
rta.Selection.Insert(link);
There isn’t a simple way to read the content of the edited text. The only way I found is by using the Blocks collection of the control. Unfortunately this requires the manual deserialization of the elements in a string. My hope is that the control will be strongly improved in the next releases. In the attached code you will find a basic sample of a manual decode of the blocks.
Final Remarks
My feel is that there is some additional work to bring Silverlight 4.0 to become really useful, but this may sound obvious because the current bits are only the first beta release. The added features are very impressive and it is astounding how great is the work done in so little time. The sure thing is that Silverlight is growing very fast but this growing is going through a path of real needs thanks to the listening of Microsoft for its users.