WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

Building Photo Uploaders with XAML

by Jack Herrington
08/29/2006

Introduction

If you are a user experience junky like I am, then XAML is like interface crack. If you haven't seen XAML demos on Windows Vista, or used the freely available WinFX SDK, then you haven't lived. XAML is a tag-based language that you use to create stunning interfaces quickly and easily.

In this article I'll show you not only how to develop one of these applications, but also how to do something useful with it. For this example I'll be writing a photo Uploader to get image files up to a simple PHP web application.

Building the PHP Web Application

The first stop on the journey is to create the PHP web application that will accept the photos, and show what has been uploaded. Because the PHP application isn't the primary focus of the article, I'll keep it pretty simple and just use a file-based solution to storing and retrieving the files. Obviously, to use this system in practice you will want to have a more robust image storage and retrieval system.

To start I'll create the page that will receive the uploaded files and move them into a sub-directory named "media." This PHP script is shown in Listing 1.

Listing 1. upload.php

<?php
move_uploaded_file( $_FILES['file']['tmp_name'],
  "media/".$_FILES['file']['name'] );
?>

Wow, it doesn't get a lot easier than that. Here I used PHP's move_uploaded_file function to take the uploaded file and move it into the media directory. Clearly the ideal application would check for colliding file names, but since this is just a test application I'll keep it simple.

To see what's been uploaded, I need another script that will show the contents of the media directory as an HTML page. That PHP script is shown in Listing 2.

Listing 2. index.php

<html>
<body>
<table>
<?php
$dir = opendir( "media" );
while ( ( $name = readdir( $dir ) ) ) {
if ( preg_match( "/[.]jpg$/", $name ) ) { 
?>
<tr>
<td><?php echo( $name ); ?></td>
<td><img src="media/<?php echo( $name ); ?>" /></td>
</tr>
<?php echo( $row[1] ); ?>
<?php } } ?>
</table>
</body>
</html>

This is a pretty simple script. It starts by building out the tags for a page and then a table. Then it opens up the directory and creates a row in the table for each file and two cells within each row, one of which holds the name of the file and the other an image tag which will display the image.

Once I have the XAML Uploader application written and some test images uploaded, I'll show the output of this page.

Starting with XAML

The next step is to create the XAML Uploader application. And that starts by installing the WinFX SDK and Visual Studio 2005. Both of these can be installed either on Windows XP or a Windows Vista beta if you are brave enough to run that. The SDK is free and evaluation versions of 2005 are also available. Plan to spend a long time on a fat pipe downloading this stuff because the SDK is several gigabytes.

With the development toolkit installed I can start working on the interface.

The Interface Basics

In my mind's eye I've sketched out a simple layout for the Uploader. Along the top is a line of image thumbnails, and then in the center is a preview of the selected thumbnail. When a thumbnail is selected, an Upload button will appear; when pressed it will send the file to the server.

The first thing to do is create a new XAML application project and title it UploaderProject. Then within that project I create a new XAML page called Uploader. This will create two files: Uploader.xaml and Uploader.xaml.cs. The XAML file defines the objects and the layout and the CS file is the code for the page. It's a C# class that's called when the page is loaded, buttons are clicked, etc. Using Visual Studio I could put together the layout visually. But I like to work in code and the first version of the page is shown in Listing 3.

Listing 3. Uploader.xaml

<Grid 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:d="http://schemas.microsoft.com/expression/interactivedesigner/2006"
  mc:Ignorable="d"
  Background="black" 
  x:Name="DocumentRoot"
  x:Class="UploaderProject.Uploader" 
  Width="640" Height="480">

  <Grid.ColumnDefinitions>
    <ColumnDefinition/>
  </Grid.ColumnDefinitions>
  
  <Grid.RowDefinitions>
    <RowDefinition Height="27*"/>
    <RowDefinition Height="69*"/>
    <RowDefinition Height="4*"/>
  </Grid.RowDefinitions>
  
  <ScrollViewer Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch"
      VerticalAlignment="Top" Width="Auto" Height="Auto"
      HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
    <StackPanel RenderTransformOrigin="0.5,0.5" Orientation="Horizontal" 
      x:Name="ImageList" />
  </ScrollViewer>

  <Image Width="Auto" Height="Auto" Grid.Row="1" Grid.Column="0"
    x:Name="DisplayImage" HorizontalAlignment="Center"
    VerticalAlignment="Center" />

  <Button Click="Upload_Click" Visibility="Hidden" Grid.Row="1" Grid.Column="0"
    HorizontalAlignment="Right" VerticalAlignment="Bottom" x:Name="Upload"
    Content="Upload" FontSize="16" FontWeight="Bold" Margin="0,0,12,14"
    Width="92" BorderBrush="sc#1, 0.175407261, 0.290725321, 0.621118367" >
  </Button>

  <TextBox Grid.Row="2" Background="Black" BorderBrush="{x:Null}"
     Foreground="White" Grid.Column="0" x:Name="PercentDone"
     FontFamily="Tahoma" FontSize="9pt" />
  
</Grid>

I'll base this page on a Grid class. The Grid class is one of many XAML layout managers. It's similar to a table in HTML. In this case I'll define three rows. The first is where the thumbnails will go. The second row, the largest, is where the image preview will go. And the third row will hold a small status text line. If you look at the Grid.RowDefinitions tag you can see these three rows, and their relative widths, laid out.

After that, I define the visual objects. At the top I create a StackPanel within a ScrollViewer to hold the thumbnails. A StackPanel is another organizing class, like a Grid, but in this case it just stacks the contained objects either horizontally or vertically. The ScrollViewer puts a set of scrollbars around the StackPanel.

The Image object is the preview for the selected thumbnail. Below that, the Upload button is in the same Grid cell as the preview but is aligned along the bottom right to give some visual distinction.

Located in the bottom cell is a TextBox that contains the status line.

It's interesting to note the different approach taken in this layout model than what would be done in HTML. In an HTML <table> there would three rows, with one cell each and the content of each cell would be defined with the <td> tag of the cell. With XAML, I define a container and then use special attributes, in this case Grid.Row and Grid.Column to specify where I want the element within the container.

To spice this up, I'm going to add a definition at the top of the file that will provide a glow around an image thumbnail when the mouse rolls over it. This definition is shown in Listing 4.

Listing 4. The mouseover glow definition

  <Grid.Resources>
    <Style TargetType="{x:Type Image}" x:Key="TopImage">
      <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
          <Setter Property="BitmapEffect">
            <Setter.Value>
              <OuterGlowBitmapEffect GlowSize="6"/>
            </Setter.Value>
          </Setter>
        </Trigger>
      </Style.Triggers>
    </Style>
  </Grid.Resources>

This is the XAML version of an inline CSS stylesheet. In this case, I'm defining a style that applies to Image types and that triggers when the IsMouseOver property is set to true. A BitmapEffect property is altered to add an outer glow effect. Outer glow adds an anti-aliased glowing visual effect to the image. You can set the color of the glow, the size of the glow, and more.

XAML provides a grab bag of bitmap effects that you can apply not only to images but to almost any object. If you are familiar with Adobe Photoshop and its effects package, then you will see some similarities to what's provided in the XAML toolkit. To demonstrate that, I'll give the upload button a little visual pop by changing its background to have a linear gradient fill, as shown in Listing 5.

Listing 5. Altering the appearance of the Upload button

  <Button Click="Upload_Click" Visibility="Hidden"
    Grid.Row="1" Grid.Column="0"
    HorizontalAlignment="Right" VerticalAlignment="Bottom" x:Name="Upload"
    Content="Upload" FontSize="16" FontWeight="Bold" Margin="0,0,12,14"
    Width="92" BorderBrush="sc#1, 0.175407261, 0.290725321, 0.621118367" >
    <Button.Background>
      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
        <LinearGradientBrush.GradientStops>
          <GradientStopCollection>
            <GradientStop Offset="0"
              Color="sc#1, 0.2154015, 0.2336096, 0.868529737"/>
            <GradientStop Offset="0.9" Color="#FFF0F0EA"/>
          </GradientStopCollection>
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Button.Background>
  </Button>

Notice that I've changed the background property of the button. All of the UI elements in XAML are composed of XAML elements that you can alter in this way, either at the individual object level, or by specifying a class of elements. For example, all buttons--or all buttons of a specific class--can be given a new background, a new font for the name of the button, a new template for positioning the content of the button, and so on. All while retaining the interactivity of the button. So, for example, creating icon buttons is a snap in XAML.

Pages: 1, 2, 3

Next Pagearrow