Introduction
Having taken lots of ideas from this site over the past months, I have decided to give something back. I have had a steep learning curve trying to learn Silverlight and as with every new technology, although you know how to program, you still have to try and find out how to do some of the more trickier things. Pressing F1 in Visual Studio never really helps, so it's off to surfing the web.
Then the fun begins. I find a lot of examples overcomplicated and also with Silverlight most examples are in C#.
This app will show how to load photos via an XML file and also how to save them on the client's PC. Both are achieved using a Webclient.
Background
Most examples found suggested what I wanted to achieve could not be done purely within Silverlight. But as this app shows, it can. Although this example deals with JPGs, the methodology could be applied to any type of file.
Using the Code
This app is a very simple photo album with the main issues I wish to share being loading and storing XML data and allowing a user to save a photo on his/her PC using Webclients.
Firstly, create a simple class to store URLs to the photos.
Both the URLs to the thumbnails and photos will be stored here.
Namespace Pictures
Public Class Picture
Private strPicture As String
Private strThumbNail As String
Public Sub New(ByVal strPic As String, ByVal strThumb As String)
strPicture = strPic
strThumbNail = strThumb
End Sub
Public ReadOnly Property Picture() As String
Get
Return strPicture
End Get
End Property
Public ReadOnly Property Thumbnail() As String
Get
Return strThumbNail
End Get
End Property
End Class
End Namespace
Then in the XAML code behind, add the following (N.B. - also import system.linq
& system.xml.linq
).
Firstly by calling the DownloadStringAsync
method, the Webclient will load the XML file. Once completed, the DownloadStringCompleted
event will be fired. Then a list (xmlList
) is created by looping through the XML and storing each item in a class in the list.
Private xmlList As New List(Of Pictures.Picture)
Public Sub New()
InitializeComponent()
Dim url As New Uri("images.xml", UriKind.RelativeOrAbsolute)
Dim xmlWebClient As New WebClient
AddHandler xmlWebClient.DownloadStringCompleted,
AddressOf XMLWebClient_DownloadStringCompleted
xmlWebClient.DownloadStringAsync(url)
End Sub
Private Sub XMLWebClient_DownloadStringCompleted(ByVal sender As Object,
ByVal e As DownloadStringCompletedEventArgs)
Dim xmlPictures As XDocument
Dim xmlElement As XElement
xmlPictures = XDocument.Parse(e.Result)
For Each xmlElement In xmlPictures.Descendants("all")
xmlList.Add(New Pictures.Picture(xmlElement.Element("pict_path"),
xmlElement.Element("thumb_path")))
Next
LoadInitialThumbs()
End Sub
That's it. The Webclient loads the XML file and then the URLs are added to the list collection. Please download the source code to see how the data is processed and linked to the XAML.
Next I want to touch on using Silverlight's SaveFileDialog
. This has to be initiated by the user. So a click event is required. Calling it directly or from any other mouse event causes an error.
Firstly, you need to add a button to the XAML page, give it a name and then create a click event. Within this event, a SaveFileDialog
is created and a filter applied. The dialog is displayed to the user using the ShowDialog
method. Next the user enters a filename. If everything is ok, the filename is stored in the stream fs
.
Next to actually retrieve the file from the server to the PC.
Again, this is achieved using a webclient with handler, but this time, the OpenReadAsync
method is used together with the OpenReadCompleted
event.
On firing this event, the file is written to the fs
stream.
Private Sub btnSavePic_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs)
Dim sfd As New SaveFileDialog
sfd.Filter = "JPEG Files (*.jpg)|*.jpg"
Dim result As System.Nullable(Of Boolean) = sfd.ShowDialog()
If result = True Then
fs = sfd.OpenFile
SaveFile(mainImage.Tag.ToString)
End If
End Sub
Private fs As Stream
Private Sub SaveFile(ByVal strURL As String)
Dim photoWebClient As New WebClient
Dim url As New Uri(strURL, UriKind.RelativeOrAbsolute)
AddHandler photoWebClient.OpenReadCompleted, AddressOf photoWebClient_OpenReadCompleted
photoWebClient.OpenReadAsync(url)
End Sub
Private Sub photoWebClient_OpenReadCompleted(ByVal sender As Object,
ByVal e As OpenReadCompletedEventArgs)
Dim length As Integer = Convert.ToInt32(e.Result.Length)
Dim byteResult As Byte() = New Byte(length - 1) {}
e.Result.Read(byteResult, 0, byteResult.Length)
fs.Write(byteResult, 0, byteResult.Length)
fs.Close()
End Sub
The only problem is that you cannot put the filename in the save dialog box.
The above has taken quite a while to suss out so I hope other developers will find using the Webclient in this way useful. It also allows files to be saved directly rather than using extra client to server traffic - just 100% pure Silverlight.
History
- 5th May, 2010: Initial post