Silverlight Media Viewer Web Part for SharePoint
One of my blog readers asked me for help with a variant of the Silverlight Media Viewer, which is one of the Silverlight BluePrint samples, and he wondered why he couldn’t make it run on his machine.
First of all, at this time of writing, not all of the BluePrint samples seem to be converted yet to the released version of Silverlight 2, and the Media Viewer is not among the converted ones. So I made the necessary changes to make it compatible for Silverlight 2. These changes include setting the MinimumVersion property of the SilverlightControl to 2.0.31005.0.
The Media Viewer is a web part that hosts a Silverlight application that is uploaded in a document library. When you want to add the web part to a page in your SharePoint site you can find it in the Silverlight Web Parts category of the Web Part Gallery.
If you work with a standard Picture library, the Media Viewer will show up as the classic Media Viewer from the BluePrint samples with all pictures listed in the list box at the left of the web part.

But you can also arrange your pictures in categories. In that case you have a custom list containing the different categories and a lookup field in the picture library referencing the category list. The Media Viewer shows up with an extra list box at the bottom of the web part. Clicking on one of the categories causes the left list box to display the pictures of the selected category.

The web part contains a custom editor part in which you can configure following options:
- the document library where you uploaded the Silverlight application
- the picture library that contains the pictures
- the type of media: picture or movie
- the list containing the categories
- a field that will be used as the caption of the button
- a field that contains an URL to a picture that can be used as the background of the button

If you don’t choose a document library from the first dropdown list, the Web Part will try to load the Silverlight application from the Shared Documents document library.
If you choose a Category list but no fields, the Title field will be used as button caption and the background of the button will be a simple glass button. With thanks to Michael for providing the code of his glass button.
The communication between SharePoint and Silverlight is established by passing the necessary data through the InitParameters property of the SilverlightControl.
// parameters passed are the name of the selected picture library, the media // type and the url of the SharePoint site string parameters = "lib=" + mediaLibName + ",type=" + mediaType.ToString() + ",url=" + SPContext.Current.Web.Url; if (!string.IsNullOrEmpty(categoryListName) && !categoryListName.StartsWith("Select")) { parameters += ",evlist=" + categoryListName; if (!string.IsNullOrEmpty(categoryFieldName) && !categoryFieldName.StartsWith("Select")) parameters += ",caption=" + categoryFieldName; if (!string.IsNullOrEmpty(categoryPictureUrl) && !categoryPictureUrl.StartsWith("Select")) parameters += ",pic=" + categoryPictureUrl; } silverlightControl.InitParameters = parameters;
Within the Silverlight application the SharePoint data from the picture library and category list are retrieved using the HttpWebRequest technique which on its turn can call the standard SharePoint web services. As this runs completely asynchronous and on different background threads now (this is different form the way it worked in Beta 2), I had to make some changes to the code to make this work again for Silverlight 2.
In Beta 2, when I initialized the HttpWebRequest object, I defined a callback method for both the BeginGetRequestStream method and the BeginGetResponseStream method. Now you have to define a callback for the BeginGetResponse method within the callback method passed in the BeginGetRequestStream.
This is the initialization code of the HttpWebRequest object:
internal void BuildPreviewBar(string title) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create( new Uri(siteUrl + "/_vti_bin/Lists.asmx", UriKind.Absolute)); request.Method = "POST"; request.ContentType = "application/soap+xml; charset=utf-8"; request.Headers["ClientType"] = "Silverlight"; // changed for additionally handling the event results request.Headers["ListType"] = "piclib"; if (title != null) request.Headers["Event"] = title; request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request); }
Within the callback method for the BeginGetRequestStream method, you can define a callback method for the BeginGetResponse method. But before you can define that callback, you have to make sure to call the EndGetRequestStream method and to close the stream.
body = request.EndGetRequestStream(asyncResult); System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); byte[] formBytes = encoding.GetBytes(envelope); body.Write(formBytes, 0, formBytes.Length); body.Close(); request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
Within the callback method for the BeginGetResponse method you first have to retrieve the request object of type HttpWebRequest and then call the EndGetResponse method on it to retrieve the response object of HttpWebResponse. Use the GetResponseStream method to retrieve the response. If the status is OK you can store the response in a class-level variable of type string and call the BeginInvoke method of the Dispatcher to return on the UI thread. Pass in the name of a method to indicate the Dispatcher where you want to continue.
private void ResponseCallback(IAsyncResult asyncResult) { HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult); Stream content = response.GetResponseStream(); if (response.StatusCode == HttpStatusCode.OK) { using (StreamReader reader = new StreamReader(content)) { responsestring = reader.ReadToEnd(); } try { // changed for additionally handling the event results if (request.Headers["ListType"] != null) { switch (request.Headers["ListType"]) { case "event": this.Dispatcher.BeginInvoke(ProcessResponseEvents); break; case "piclib": this.Dispatcher.BeginInvoke(ProcessResponsePictureLibrary); break; } } } catch { } } }
The Silverlight application of the original BluePrint sample (for Silverlight 2 Beta 2) contained one Page.xaml with all Silverlight controls and styles on it. To have a better insight in it, I encapsulated the different controls and styles in different user controls.
I wanted to keep the SharePoint communication outside the controls and in the Page.xaml.cs code behind. This has some implications for the events: I had to create and raise custom events. The event arguments in Silverlight are of type RoutedEventArgs and inheritance is not supported. So I had to work with the standard Silverlight event arguments and place the significant data into properties of the user controls before raising the custom event.
The ItemSource property of the list boxes is set to use data binding.
As you can see there is a difference between the vertical list box at the left of the Silverlight application and the horizontal list box at the bottom of the Silverlight application. The horizontal listbox is a normal listbox with only a custom style template for the item to be able to use the glass button.
<UserControl x:Class="SL.XAML.MediaViewer.HorizontalListBox" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml xmlns:my="clr-namespace:SL.XAML.MediaViewer" Width="690" Height="90" Background="Transparent"> <UserControl.Resources> <Style TargetType="ListBox" x:Key="EventListBoxStyle"> <Style.Setters> <Setter Property="Background" Value="Transparent" /> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style.Setters> </Style> <DataTemplate x:Key="EventButtonTemplate" > <Grid x:Name="EventElement"> <my:GlassButton ButtonClick="GlassButton_ButtonClick" /> </Grid> </DataTemplate> </UserControl.Resources>
<Grid x:Name=”LayoutRoot” Background=”Transparent” >
<ListBox x:Name=”EventListBox” Height=”90″ Width=”690″ Style=”{StaticResource EventListBoxStyle}”
ItemTemplate=”{StaticResource EventButtonTemplate}” />
</Grid>
</UserControl>
The vertical list box is a more customized control using styles for the ListBoxItem and the ScrollViewer:
<UserControl x:Class="SL.XAML.MediaViewer.VerticalListBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="86" Height="600" Background="Transparent"> <UserControl.Resources> <!-- Linear Brushes for the preview controls --> <LinearGradientBrush x:Key="BorderGradientBrush" StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Turquoise" Offset="0.0" /> <GradientStop Color="Black" Offset="0.75" /> </LinearGradientBrush> <LinearGradientBrush x:Key="ActiveBorderGradientBrush" StartPoint="0.2,0.2" EndPoint="1,1"> <GradientStop Color="Turquoise" Offset="0.0" /> <GradientStop Color="DarkTurquoise" Offset="1" /> </LinearGradientBrush> <LinearGradientBrush x:Key="SelectedGradientBrush" StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="White" Offset="0.0" /> <GradientStop Color="DarkTurquoise" Offset="0.85" /> </LinearGradientBrush> <!-- Style for the List Item --> <Style x:Key="PreviewPictureItemStyle" TargetType="ListBoxItem"> <Setter Property="Foreground" Value="#FF000000" /> <Setter Property="Width" Value="80" /> <Setter Property="Height" Value="80" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <Grid x:Name="PreviewElement" MouseEnter="PreviewElement_MouseEnter" MouseLeave="PreviewElement_MouseLeave" MouseLeftButtonDown="PreviewElement_MouseLeftButtonDown"> <Border BorderBrush="{StaticResource BorderGradientBrush}" BorderThickness="5" CornerRadius="4" Margin="2" Background="Transparent" > <Image Width="70" Height="70" Stretch="Fill" Source="{Binding Url}" /> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="PreviewMovieItemStyle" TargetType="ListBoxItem"> <Setter Property="Foreground" Value="#FF000000" /> <Setter Property="Width" Value="80" /> <Setter Property="Height" Value="80" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBoxItem"> <Grid x:Name="PreviewElement" MouseEnter="PreviewElement_MouseEnter" MouseLeave="PreviewElement_MouseLeave" MouseLeftButtonDown="PreviewElement_MouseLeftButtonDown"> <Border BorderBrush="{StaticResource BorderGradientBrush}" BorderThickness="5" CornerRadius="4" Margin="2" Background="Transparent" > <MediaElement Width="70" Height="70" Stretch="Fill" AutoPlay="True" Source="{Binding PreviewUri}" /> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- Style for the ScrollViewer --> <Style x:Key="ScrollViewerStyle1" TargetType="ScrollViewer"> <Setter Property="IsEnabled" Value="true"/> <Setter Property="Foreground" Value="#FF000000"/> <Setter Property="BorderBrush" Value="#FFA4A4A4"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="Cursor" Value="Arrow"/> <Setter Property="FontSize" Value="11"/> <Setter Property="Background" Value="Transparent" /> <Setter Property="VerticalScrollBarVisibility" Value="Visible"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ScrollViewer"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5"> <Grid Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Rectangle Grid.Column="1" Grid.Row="1" Fill="Transparent" /> <ScrollBar Cursor="Arrow" x:Name="VerticalScrollBar" HorizontalAlignment="Stretch" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Row="0" Orientation="Vertical" Opacity="1" ViewportSize="{TemplateBinding ViewportHeight}" SmallChange="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}" /> <ScrollContentPresenter x:Name="ScrollContentPresenter" Cursor="{TemplateBinding Cursor}" Margin="0,18,0,18" Grid.Column="0" Grid.Row="0" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" /> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- Style for the ListBox --> <Style TargetType="ListBox" x:Key="PreviewListBoxStyle"> <Setter Property="ItemContainerStyle" Value="{StaticResource PreviewMovieItemStyle}" /> <!-- <Setter Property="Width" Value="86" /> --> <Setter Property="Background" Value="Transparent" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBox"> <Grid x:Name="LayoutRoot"> <Border Background="Transparent" CornerRadius="5" Width="86"> <ScrollViewer x:Name="PreviewScrollViewer" Width="86" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Style="{StaticResource ScrollViewerStyle1}" > <ItemsPresenter /> </ScrollViewer> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="Transparent"> <ListBox x:Name="PreviewListBox" Height="600" Width="86" Style="{StaticResource PreviewListBoxStyle}" > </ListBox> </Grid> </UserControl>
If you want to run the sample in your SharePoint environment and you didn’t yet configure it for Silverlight, read this blog post first but also make sure that your read the bottom of this post otherwise the SharePoint web services will not be working anymore.
You can download the source code here.

Wow, great post! Thanks for the comment as well — I gave you a shout-out in my post also, especially since your web part is a lot prettier than mine!
http://www.devexpertise.com/2009/02/07/retrieving-sharepoint-list-data-from-silverlight-without-a-custom-wcf-or-aspnet-web-service/
Thanks A lot karine for your help
It was a pleasure doing this!
Karine
Thanks for the post, it’s well.
But I have a problem because i have an error on the function ResponseCallback
private void ResponseCallback(IAsyncResult asyncResult)
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
The message est SecurityExcetion. Someone could explain if I need to authorize something on my sharepoint site to use WebService.
Thanks so much, if someone have an idea.
Hi Fabien,
It is possible you have specified a wrong url when instantiating the web request. The best way to check is to open a internet browser and to enter the URL to the Lists.asmx you use in your code.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
new Uri(siteUrl + “/_vti_bin/Lists.asmx”, UriKind.Absolute));
Also check the name of the list you use in your soap envelope.
Can you try this out?
Great post and code. Thanks for this.
Thanks for the post it is very well.
But I have a problem with the Application. I don’t have any Connection between the Category List and the Picture Libray. I don’t get any Errors when i debug it.
If i press the button in the horizontal Listbox, i don’t see any Pictures in the Viewer. I think the buttons don’t have any function.
Thanks so much if anybody have an idea…
Hi Christian,
Clicking the horizontal list box will populate the vertical list box. Clicking the vertical list box will populate the Viewer (large image).
If you don’t have a connection between the Category list and the Picture Library, then I don’t know how you want to populate the vertical list box.
Can you explain which functionality you need?
Karine
Hi Karine,
thanks for the fast post. I click on a category button in the horizontal list box but it won’t populate the vertical list box and i don’t know why??? There is no function…
If i have only Pictures without categories, it will be run correctly…
thanks
Christian
PS: My steps are:
- I made a picture library with the name pictures
- than a custom List with the name “categorie”
- I made a lookup field in the picture library referencing to the categorie List
- I set the categories to the pictures
Have I to make any Changes in the Code because of the “categorie” List?
Hi Christian,
If you selected the correct lists in the custom tool pane of the web part, everything should work. The lists selected in the toolpane are passed to the silverlight control and are used to execute the HttpWebRequest.
Karine
I think it should work, but it doesn’t
Thank you so much…
Christian
Hi Karine,
My scenario is like this:
I have created a silverlight grid(with many controls inside the grid) and i have put it on a custom aspx page in my SharePoint site.
Now what I need is “the name of the person who has logged into SharePoint site should automatically get filled in the TEXTBOX control of my Silverlight grid”..
usually i wud have used SPSite appSite = SPControl.GetContextSite(Context);SPWeb myWeb = SPControl.GetContextWeb(Context);txtBox1.Text = myWeb.CurrentUser.Name.ToString();
But I cant use object model since ShaarePoint dll’s cant be added into silverlight project…
Is there any solution for this??
Thanks in Advance,
Akhil
Hi Akhil,
Can you let me know how you place your Silverlight control on your page? Are adding it declaratively as follows:
Or do you add the Silvelright control in code?
If you can let me know the above, I will be able to help you out.
Karine
I am new to this but what is the process of getting this installed into sharepoint once I have downloaded the code from above. Do i have to make any changes to the code besides pointing it to the correct image libraries? Do I have to create a wsp and then deploy it like a typical wsp into sharepoint ? Just a bit confused so any help would be great.
Hi Anhal,
All necessary parts for a SharePoint solution are there:
- a Silverlight application
- a web part
- feature manifests
- solution manifests
You just have to generate a .wsp file out of this. For this purpose you can use WSP Builder or you generate the .ddf file manually.
Karine
Awesome…Thank you very much. i will give it a shot.
Karine,
One last question..you have been very helpful..Thank you ! Can you tell me what the name of the solution is that I need to open and then build the wsp from? I guess I’m still a little confused on what to do after I extract the files. I see a SharePoint and a xmal directory each with solutions in them. If I try to open those solutions up in VS 2008 I get a project is not supported by this installation. I have installed the pre-reqs as stated in the article above. Is there anything else that you can see that I would need? Any other guidance would be greatly appreciated
Anhal,
To be able to generate the wsp, you have to open the web part project with name SL.SharePoint.MediaViewer but it is possible it has been made using STSDEV or VSEWSS 2.1.
For the Silverlight project, this is a Silverlight 2 project, so you will have to have Silverlight 2 installed.
Karine
Karine,
I have silverlight 2 and 3 installed on the server. I can open the project and create the wsp using the wspbuilder but when I add the webpart to the page it say’s the file you imported is not valid.
I’m sorry for all the questions, I just feel that this is the best solution out there and am very interested in getting this insatlled on our site.
using vs 2008.
moss 2007
.net framework 3.5 is installed
silverlight 2 tools as well.
Thanks again for your patience as I learn
ok, it seems all required parts are installed. Can you please tell me the exact error message when adding the webpart to a SharePoint page?
Thanks Karine,
Basically what I’m doing is opening up the project as you stated before. Using wsp builder to build the wsp. Using stadm to add and deploy the wsp to my server and then when I select the wsp from the web part page to be added to a page I get:”Unable to add selected web part. Silverlight media viewer: The file you imported is not valid, Verify that the file is a web part description file and that it contains well-formated xml”
I hope that helps.
Thanks again.
A .wsp file is a solution that can be deployed using stsadm. A webpart file has a .webpart extension and is part of a feature within that solution. WebParts can be added on a web part pages through the Web Part gallery, which never contains .wsp files. So I don’t understand how you are able to add a .wsp to a web part page.
But coming to the error: it seems like the file doesn’t contain XML. Did you modify the .webpart file? Or another XML file?
If I just try to upload the mediaviewer webpart file I get a similiar error. I must be going about this the wrong way.
I extract all the files.
I open up the project and create a wsp.
I add and deploy the wsp via stadm.
I open up sharepoint – site settings – web parts
Select upload
browse and upload the webpart file that was part of the project.
go to a sharepoint page.
add the Sharepoint media View webpart
and then I get the error.
I must be way off base but am obviously new at this.
Thanks again for all your help you have been FANTASTIC !!