Share via


Exercise 2: Drag and Drop

Not all users will have webcams, and even those who do may already have a picture they’d like to use instead of taking a new one. In this part of the lab, you’ll make it possible for users to drag a PNG or JPEG file from their computer into the application.

Note:
Don’t forget that the Completed folder in each lab contains a completed solution for every part of the lab. If you did not do the previous part (e.g., because you don’t have a webcam) you can use the solution in the Part 1 folder as your starting point for this part.

Add Drop Support

  1. Open the SlEventManager solution. In the SlEventManager project, open the UserPicture.xaml file in the Views folder.
  2. Find the Grid element named LayoutRoot.
  3. Set its AllowDrop property to true. This enables it to act as a drop target.
  4. Add a Drop event handler to the LayoutRoot element.
    Note:
    The Grid is currently invisible. It performs layout but has no appearance of its own. This presents a problem for drag and drop because invisible elements cannot directly receive mouse input. They can receive mouse events as they bubble out of child elements, but as far as Silverlight is concerned, any empty space in the UI really is empty, even though it’s contained within the bounding box of the grid. (Mouse events will end up being delivered to the element behind the Grid.)

    To ensure that the whole area occupied by the Grid works as a drop target, you need to set its Background property. In fact you can set it to Transparent (although this is also invisible). Silverlight treats anything that has been painted with a brush as being visible to the mouse, even if it’s not visible to the eyes.
  5. Set the background of the LayoutRoot to White.
  6. Add the following using directive to the UserPicture.xaml.cs(C#) or UserPicture.xaml.vb(VB) code behind.

    C#

    using System.Windows.Media.Imaging;

    Visual Basic

    Imports System.Windows.Media.Imaging
  7. Add the following code to the Drop event handler:

    C#

    if (e.Data.GetDataPresent(DataFormats.FileDrop)) { FileInfo[] fi = (FileInfo[]) e.Data.GetData(DataFormats.FileDrop); BitmapImage image = new BitmapImage(); using (Stream fileStream = fi[0].OpenRead()) { image.SetSource(fileStream); } ImageBrush brush = new ImageBrush(); brush.ImageSource = image; brush.Stretch = Stretch.UniformToFill; userPictureBorder.Background = brush; }

    Visual Basic

    If e.Data.GetDataPresent(DataFormats.FileDrop) Then Dim fi() As FileInfo = CType(e.Data.GetData(DataFormats.FileDrop), FileInfo()) Dim image As New BitmapImage() Using fileStream As Stream = fi(0).OpenRead() image.SetSource(fileStream) End Using Dim brush As New ImageBrush() brush.ImageSource = image brush.Stretch = Stretch.UniformToFill userPictureBorder.Background = brush End If
  8. Run the application.
  9. Navigate to the UserPicture View.
  10. Drag a bitmap onto the UI. (There’s a JPEG file in the lab folder if you don’t have a suitable image to hand.) You should see the image appear.
    Note:
    The Save Picture button won’t be working yet, because it relies on saving a copy of the bytes of the image. We’re not yet retrieving those bytes.
  11. Inside the using statement you just added, after the call to image.SetSource, add this code:

    C#

    fileStream.Seek(0, SeekOrigin.Begin); MemoryStream targetStream = new MemoryStream(); fileStream.CopyTo(targetStream); imageBytes = targetStream.ToArray();

    Visual Basic

    fileStream.Seek(0, SeekOrigin.Begin) Dim targetStream As New MemoryStream() fileStream.CopyTo(targetStream) imageBytes = targetStream.ToArray()
  12. Run the application.
  13. Verify that you can drag an image and save it to the database.

Load the Image from the Database (Optional)

As an additional exercise, you might want to try writing code that loads the images saved in this lab to display them. One way to do this would be to add a method to the domain service that retrieves an Attendee entity for the currently logged in user. This has a UserPicture property containing the image bytes. Once you’ve got that on the client side, you can wrap it in a MemoryStream, and then pass that to a BitmapImage object’s SetSource method, just like you did with the file stream in the Drop handler. (Or if you want a more advanced approach, you could write an ASP.NET HTTP handler that makes the user pictures available via HTTP.)

Note:
The solution for this optional task can be found in the completed lab for Exercise 2.