oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Building Photo Uploaders with XAML
Pages: 1, 2, 3

Wiring Up the Back End

Now with the interface all put together I can start working on the Uploader.xaml.cs class that sits behind the user interface. The first thing I do is create class that will hold information about each image; I call it ImageInfo and it's shown in Listing 6.

Listing 6. The ImageInfo private class

using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Media.Imaging;
using System.Collections;
using System.Configuration;

namespace UploaderProject
  public class ImageInfo
    private BitmapImage m_Image = null;
    public BitmapImage Image { get { return m_Image; } }

    private string m_sPath = null;
    public string Path { get { return m_sPath; } }

    private ImageInfo() {
      m_Image = null;
      m_sPath = "";

    public ImageInfo( string sPath, BitmapImage image ) {
      m_sPath = sPath;
      m_Image = image;

The class isn't really important enough to get its own file, so I'm just going to stick it in the same definition file for the Uploader interface code.

To finish off the backend, I write the code for the interface itself as the Uploader class as shown in Listing 7.

Listing 7. The Uploader class behind the interface

  public partial class Uploader
    private Hashtable m_ImageLookup = new Hashtable();
    private WebClient m_Client = new WebClient();
    private ArrayList m_PendingFiles = new ArrayList();
    private ImageInfo m_CurrentlySelected = null;
    private string m_sCurrentDownload = "";

    public Uploader() {
      m_Client.DownloadFileCompleted += new AsyncCompletedEventHandler(
          WebClient_DownloadFileCompleted );
      m_Client.DownloadProgressChanged += new
          WebClient_DownloadProgressChanged );

    void WebClient_DownloadProgressChanged(object sender,
        DownloadProgressChangedEventArgs e) {
      PercentDone.Text = String.Format("{0} - {1}% done",
        m_sCurrentDownload, e.ProgressPercentage);

    void WebClient_DownloadFileCompleted(object sender,AsyncCompletedEventArgs e) {
      PercentDone.Text = "";

    void StartUpload() {
      string sPath = (string)m_PendingFiles[0];
      m_sCurrentDownload = Path.GetFileName(sPath);

      string sUploadPage = ConfigurationSettings.AppSettings.Get("UploadPage");

      if ( m_Client.IsBusy == false )
        m_Client.UploadFileAsync(new Uri(sUploadPage), "POST", sPath, null);

    protected override void OnInitialized(EventArgs e) {
      string[] sFiles = Directory.GetFiles( Directory.GetCurrentDirectory() );
      foreach( string sFile in sFiles ) AddImageButton( sFile );

    void Upload_Click(object sender, RoutedEventArgs e) {
      if (m_CurrentlySelected != null)
        Upload.Visibility = Visibility.Hidden;
        m_CurrentlySelected = null;

    protected void AddImageButton(string sPath) {
      if (Path.GetExtension(sPath).ToLower() != ".jpg") return;

      BitmapImage image = null;
      try {
        image = new BitmapImage();
        image.UriSource = new Uri("file://" + sPath);
      } catch { }

      if (image != null)
        int nFixedHeight = 100;

        double dScaleRatio = (double)image.Height / (double)(nFixedHeight - 10);

        Canvas b = new Canvas();
        b.Width = (int)(image.Width / dScaleRatio) + 5;
        b.Height = nFixedHeight;

        Image bi = new Image();
        bi.Source = image;
        bi.Width = (int)(image.Width / dScaleRatio);
        bi.Height = nFixedHeight - 10;
        bi.Style = (Style)DocumentRoot.FindResource("TopImage");
        bi.SetValue(Canvas.LeftProperty, 5.0);
        bi.SetValue(Canvas.TopProperty, 5.0);
        bi.MouseUp += new MouseButtonEventHandler(TopImage_MouseUp);

        m_ImageLookup[bi] = new ImageInfo(sPath, image);


    void TopImage_MouseUp(object sender, MouseButtonEventArgs e) {
      if (m_ImageLookup[sender] != null)
        m_CurrentlySelected = (ImageInfo)m_ImageLookup[sender];
        DisplayImage.Source = m_CurrentlySelected.Image;
        Upload.Visibility = Visibility.Visible;

The bulk of the code sits in the AddImageButton method, which adds an image thumbnail to the display. Its job is to dynamically create a new Canvas object, then within that place an Image object, and add that into the ImageList element in the interface. As with Dynamic HTML, adding new interface items to the display is as easy as adding new nodes into a visual tree.

The other interesting portion of the example is in the Upload_Click method which is called when the Upload button is clicked. It starts the file transfer to the web server using a WebClient object. This WebClient object is the equivalent of a scriptable web browser, you can use it to get the contents of pages, post forms, and it even stores cookies and sessions. So if you have some authentication requirements you can still use the WebClient to first log in, then upload the files.

The value of using the WebClient is that there is no special back door for the Uploader. This mechanism uses exactly the same method for uploading files as a web browser, so the PHP web application doesn't need to change at all to support this mechanism.

One thing the application does need is the URL of the page that will handle the upload of the image. This is set in the XML configuration file for the application as shown in Listing 8.

Listing 8. The configuration file

?xml version="1.0" encoding="utf-8" ?>
    <add key="UploadPage"
      value="" />

In my case, I have the PHP application on a Mac OS X laptop sitting next to my Windows box on the same router, thus the hardcoded address. In production, you would likely use a host name resolved via DNS to an IP address, such as

Pages: 1, 2, 3

Next Pagearrow