Silverlight Tips provides simple and useful tutorials and tips with real life examples, live demos and sample codes to download.
About authors:
Damon Serji
Damon Serji,
Silverlight developer working at Metia in London.
Gavin Wignall
Gavin Wignall,
Interactive Design Lead, working in design for over 10 years, the last 3 being in Silverlight.
Allan Muller
Allan Muller,
Developer, working on various types of Silverlight and WCF projects.
Recent comments

Before I started writing this post I had a quick search on the internet about Silverlight Preloader (Silverlight progressbar) and noticed a few good posts that already exist and explain how to do this.

However, one thing I noticed from most of the tutorials about creating Silverlight progressbar is that they all replace the standard Silverlight preloader animation with a simple rectangle progressbar! Although displaying your logo with a standard progressbar in shape of rectangle is much better and professional than leaving the standard Silverlight preloader to be displayed, but I think it is not that cool!

To test this project I added a large file to the project in order to slow down the process of loading for us to see the effect. To view the live demo click here.

The code can be downloaded from CodePlex here.

As a result, I want to explain how to take your logo and with a bit use of maths do something cool to it, like filling it with color to display the progress of loading.

1.  Add new xaml and js files to your Web project
this xaml file will include your custom progress bar, you can call this anything you like, here we call it preloader.xaml. To add a new xaml file: right click on your .Web project from the menu find ‘Add’ and click on ‘New Item...’, from the left side (Categories) select ‘Silverlight’, and then from the right side (Templates) choose ‘Silverlight JScript Page’. Once you add the xaml file Visual Studio will add a new .js file for you too.

2. Add splashscreensource and onSourceDownloadProgressChanged parameters to your Silverlight object

on your Default.aspx, or any page that hosts your Silverlight application (in our case SilverlightPreloaderTestPage.aspx), add the splashscreensource parameter i.e.:


<object data="data:application/x-silverlight," type="application/x-silverlight"
id="SL">
    <param name="splashscreensource" value="loading.xaml" />
    <param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />

The first parameter simply loads the loading.xaml while loading the main components of the Silverlight application.

The second parameter calls the onSourceDownloadProgressChanged  function from or preloader.js file.

3. Create a new progress bar in preloader.xaml using Blend
Since we want to fill a logo or a shape with color instead of just creating a rectangle progressbar, we need to draw the shape manually in Expression Blend. You might notice Blend doesn’t open the preloader.xaml file from our .Web project. To solve this issue I simply open a new xaml file in Blend and once I am happy with my changes I copy and paste the code to my preloader.xaml file.

To demonstrate the filling of a shape we need to use Path Clipping technique. Basically we need to create a rectangular Canvas and then cut the shape we want out from it. Then we can move another coloured rectangular, which is inside the canvas but positioned outside it by adding a high margin to it, to the left/right/up/down towards inside the canvas according to the percentage of loading. This way user will see the shape we draw earlier getting filled with color as the percentage of loading increases. To learn about Path Clipping visit Clipping paths in canvas using Expression Blend by Gavin Wignall.

4. Do the calculation in Java Script file
copy this code to your preloader.js file:

function onSourceDownloadProgressChanged(sender, eventArgs) {
    if (sender.findname("loadingStatus") != null) {
        var loaded = Math.round(eventArgs.progress * 10) / 10;
        sender.findName("loadingStatus").Text = "Loading: " + (Math.round(eventArgs.progress * 1000)) / 10 + "%";
        var newValue = 79 - (79 * loaded);
        sender.findName("LoadFill")["Canvas.Top"] = newValue;
    }
}

onSourceDownloadProgressChanged is the name of function which we call from our object in .aspx page (<param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />).

loadingStatus is a name we have given to a TextBlock in our preloader.xaml. Here we find the TextBlock loadingStatus and then assign the current loading percentage to it.

eventArgs.progress  is a very long number like 0.3452345234232 and shows the percentage of loading, 1 is 100%. So we need to change this to something like 34.5 and 100 as 100%. To do this we first multiply eventArgs.progress  by 1000, this way we get 345.2345234232 and to remove the .2345234232 we use Math.round()function which is a Java Script built-in function. Now we should have 345. To get 34.5 which is the actual percentage of loading we simple divid

e the number by 10. At the end we add a bit of text to the result and insert it to our loadingStatus TextBlock.

In order to show our logo is getting filled by color we need to move the rectangular inside by changing its “Canvas.Top” property which acts just like Margin. As we want to keep the rectangular outside the visible area we position it 79 pixels, which is just the actual height of our rectangular, away from the top, so it sits just below the visible area.

If you follow the maths as I explain above you will understand that ‘loaded’ variable will have a value like 0.34 (this time we multiplied it by 10 instead of 1000). Lets say if we had 99 percent loaded then the ‘loaded’ variable would have a value of 0.99. times that by 79 and you get 78.21, now if we follow the equation: 79 – (78.21) =  0.79. If we set the Canvas.Top to 0.79 then our clipped area will be almost completely filled with color because the rectangular is sitting right at the top and that is exactly what we wanted to achieve.

Please note, if your rectangular is larger or smaller than 79 pixels you need to change both 79 to actual height of your rectangular to get this working correctly.

Posted by Damon Serji on 30. December 2009 12:47 under: Intermediate
 with 9 Comments

Sometimes you need to cut a shape out from your canvas to produce a special effect by showing another object from behind the canvas appearing in the clipped area. This mainly is used in making animations to for instance display a text appearing in the clipped area.

In order to achieve this all you need is a canvas, another object inside the canvas, i.e. text or a rectangular to work as a color panel, and a path in your desired shape:

1. Add a canvas to your page

2. Add a rectangular inside the Canvas and fill it with a color

3. Draw a path

make sure you clicked on the LayoutRoot level before drawing the path, so your path doesn’t appear inside the canvas. You can draw a path using Pen tool. Select the Pen tool from tools panel and click on different places on the page to see the shape been drawn, to end the path click on the start point.

4. Clipping the path out from the canvas
you can choose which object to be clipped from the other by the order of selecting them. In this case we want our shape which we created using path method to be clipped from the canvas. Therefore, we need to click and select our path first, and then holding the Ctrl button on the keyboard click on the canvas.

We should now have both our path and canvas selected. Go to ‘Object’ menu in Blend and from ‘Path’ click on ‘Make Clipping Path’ (shortcut key is Ctrl + 7).

Now your canvas should have a hole in the shape you draw earlier using the Pen. So by moving the rectangular inside the canvas you will be able to notice the clipped area appearing when the rectangular or text is on the same position and disappearing when we move the rectangular or text to outside the clipped area.

Posted by Gavin Wignall on 30. December 2009 11:33 under: Intermediate
 with 2 Comments
Get Microsoft Silverlight  Silverlight pagination

Pagination (DataPager) is a built-in control in Silverlight 3.0. You simply bind your data to the DataContext through a PagedCollectionView variable.

PagedCollectionView is a class that could store collection of your data with IEnumerable interface. Through this class you are then able to use cool features such as sorting, filtering and paging functionalities.

To test pagination in this post I created a class of type “Contact” to store name, surname and tel number for each contact.

public class Contact
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Telephone { get; set; }
}

To get a better visual and have different fields display for each of my contacts I created a ContactTemplate.xaml. This simply contains the template for each of my contacts:


<Grid x:Name="LayoutRoot" Height="50">
    <TextBlock Text="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="19" />
    <TextBlock Text="{Binding Surname}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="100,2,0,19" />
    <TextBlock Text="Tel:" Margin="0,17,0,6" HorizontalAlignment="Left" />
    <TextBlock Text="{Binding Telephone}" Margin="25,17,0,7" />
</Grid>

In my Mainpage.xaml I use an ItemsControl to list all contacts that have created using Contact class, and since I want each contact to be displayed within my ContactTemplate I display a reference to the ContactTemplate.xaml page and bind each contact to that:


<ItemsControl x:Name="Contacts" ItemsSource="{Binding}" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Local:ContactTemplate />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

To create a reference to the ContactTemplate.xaml you first need to create a namespace in your MainPage.xaml that refers to the project which ContactTemplate.xaml exists (the same project in our case). So don’t forget to add this to the top of the MainPage.xaml in order for your above code to work:


xmlns:Local="clr-namespace:SilverlightPagination"

Last thing we need to do in the MainPage.xaml is to add a reference to the pagination control (DataPager):

First add the reference:


xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

Now add the control:


<data:DataPager DisplayMode="PreviousNext" Margin="0,0,0,4" HorizontalAlignment="Center" Source="{Binding}" NumericButtonCount="{Binding Value, ElementName=numericButtonCount}" AutoEllipsis="{Binding IsChecked, ElementName=autoEllipsis}" IsTotalItemCountFixed="{Binding IsChecked, ElementName=totalItemCountFixed}" />

And to get it working your MainPage.xaml.cs should look something like this:

private List<Contact> allContacts;

public MainPage()
{
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    allContacts = new List<Contact>();
    AddData();

    PagedCollectionView pcv = new PagedCollectionView(allContacts);
    pcv.PageSize = 6;
    DataContext = pcv;
}

private void AddData()
{
    for (int i = 0; i <25; i ++)
    {
        Contact contact = new Contact();
        contact.Name = "DummyName " + i;
        contact.Surname = "DummySurname " + i;
        contact.Telephone = 020711111 + i;

        allContacts.Add(contact);
    }
}

In summary, AddData() creates some contacts so that we can test this project, and the rest happens in the MainPage_Loaded. As I explained at the beginning of this post, if you add your list of data to a variable of type PagedCollectionView then you can use the pagination feature of this class. Set the page size, and set the DataContext of the page to your PagedCollectionView variable. The DataContext simply binds your data where ever it is asked to down your code (even in your ContactTemplate.xaml page that you had already added in the ItemsControl.

Posted by Allan Muller on 14. December 2009 19:33 under: Intermediate
 with 1 Comments

If you want to play music or a short sound clip in Silverlight here is what you need to do:

1. Your sound file
First, make sure you sound file is MP3 or WMA format as other formats are not supported.

Save your file to ClientBin folder (where your xap file gets coppied when buiding the project)

If you dont want to store your file to the ClientBin folder do this: from Visual Studio right click on the sound file and select Properties. Now in Properties window change Build Action to Resource. This ensures the file gets copied to the ClientBin folder during execution.

2. Add a MediaElement in your Xaml file


<MediaElement x:Name="SoundClip" Source="boing.mp3" Volume="1" AutoPlay="False"></MediaElement>

set the Source to be the name of your file and AutoPlay to False so it can be played at click of a button.

Also add a button to play the sound when clicked:


<Button x:Name="PlaySound" Content="Play Sound" />

3. play the sound
in your code behind add this to the Click event of your button:

SoundClip.Play();

If you have any questions please visit Silverlight Forums here: http://silverlightforums.com/showthread.php?p=2080#post2080

Posted by Allan Muller on 10. December 2009 13:16 under: Basic
 with 1 Comments
Get Microsoft Silverlight  Silverlight Deep Linking.

This post is an update to the previous post I have done about Silverlight Deep Linking. So for details and to see previous code visit Basic Silverlight Deep Linking.

Download:
As usual, you can download the complete project from CodePlex site here.

Questions and answers:
For updates and any issues visit the specific thread regarding this post at Silverlight Forums: http://silverlightforums.com/showthread.php?t=1425

Basically, we need to use a built-in class called “NavigationFailed” from our Frame control to fire the event when user tries navigation to a none-existent page.

Here I demonstrate two ways of handling the error exception and displaying a friendly error message.

  • Using an error template page
  • Using a child window to display a popup message for the error

Here are 3 steps to get this working with error template page:

1. Create Error404.xaml and add it to UriMapper
add a new page to your Silverlight project and call it Error404 as it will only be used for the Error 404  or “Page not found” error.

Now, in your App.xaml add the error page to your Navigation UriMapper so the application can navigate to it when needed:


<Nav:UriMapping Uri="Error" MappedUri="/Error404.xaml" />

2. Add “MainFrame_NavigationFailed” method in MainPage.xaml.cs
in your MainPage.xaml.cs and in your constructor or Loaded method, add NavigationFailed event handler to your Frame control (MainFrame):

MainFrame.NavigationFailed += new System.Windows.Navigation.NavigationFailedEventHandler(MainFrame_NavigationFailed);

If you use the Visual Studio’s snippet/shortcut it will automatically create the method for NavigationFailed event for you. Otherwise, add this method:

private void MainFrame_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
{
    MainFrame.Navigate(new Uri("Error", UriKind.Relative));
}

3. Handle the exception
although the above code looks find and seems to be working, If you run it you get the following exception error:

System.ArgumentException:
Navigation is only supported to relative URIs that are fragments, or begin with '/', or which contain ';component/'.

To fix this, you need to tell the Frame control (MainFrame) that this exception is being handled. So add this to your MainFrame_NavigationFailed method:

e.Handled = true;

Now if you try to change the URL to a page that doesnt exist you should get to see the Error404.xml page.

Using Child Window

To do this using Child Window all we need to do is to show the Child Window which we had created before (for more information about creating and showing a Child Window see my post: Passing value from Child Window to parent window).

1. Create a new Child Window (ErrorPopup.xaml)
add this file to your Silverlight project. Since we could use this for other errors too I tried to called it something more generic.

2. Add error property and placeholder to ErrorPopup
Since we want to be able to pass different error message to our popup control in the future, we add a TextBlock in the ErrorPopup.xaml, and we also add a property to our control (in ErrorPopup.xaml.cs) to receive the error message and display it in the TextBlock.

In ErrorPopup.xaml:


<TextBlock x:Name="Error" />

In ErrorPopup.xaml.cs add a private member and control its value through the property:

private string _errorMessage;
public string ErrorMessage
{
    get { return _errorMessage; }
    set
    {
        _errorMessage = value;
    }
}

Now add the following code to ensure every time the ErrorPopup is loaded it displays the error message that it received through its property (ErrorMessage):

private void ErrorPopup_Loaded(object sender, RoutedEventArgs e)
{
    Error.Text = _errorMessage;
}

3. Show ErrorPopup and pass an error message
in MainPage.xaml.cs create a private variable of type ErrorPopup:

private ErrorPopup errorPopup;

In Loaded or constructor method create a new instance of the errorPopup:

errorPopup = new ErrorPopup();

Now you are ready to use the ErrorPopup every time needed within your application. So in your MainFrame_NavigationFailed method add the following code:

errorPopup.ErrorMessage = "Page you were trying to access could not be found.";
errorPopup.Show();

don’t forget to keep e.Handled = true; in that method as otherwise you receive the exception error I explained above.

Please note in the download from CodePlex I included both methods and just commented the display through Error404 template out by commenting out the MainFrame.Navigate function in the MainFrame_NavigationFailed method. Feel free to put that line back in and comment the other method out if you needed to.

I personally prefer to you the ErrorPopup, but depending on your need you can user either of the two options I explained above.

Posted by Damon Serji on 4. December 2009 00:06 under: Intermediate
 with 2 Comments