In this example, I am going to show you how to drag and drop objects in a Silverlight Application. To make it a little more fun, we are going to be dragging ducks around a Duck Hunt for NES canvas. Bring back the memories? The following code snippet is our XAML document that gives us 2 ducks on our page.
<UserControl x:Class="Drag_N_Drop.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Drag_N_Drop"
Width="500" Height="438">
<Canvas x:Name="LayoutRoot">
<Canvas.Background>
<ImageBrush ImageSource="Images/canvas.png" />
</Canvas.Background>
<local:Duck Canvas.Left="140" Canvas.Top="20" />
<local:Duck Canvas.Left="240" Canvas.Top="20" />
</Canvas>
</UserControl>
So we have 2 ducks on a canvas. The next step is to wire each duck up so that when the user drags a duck across the screen, the duck moves with the cursor until they let go. First we define our variables. We need a variable to hold the X and Y coordinates of the mouse when we begin dragging and another variable to track if the user has their left mouse button down or not.
Private isMouseDown As Boolean = False
Private mousePosition As Point = Nothing
We want to handle 3 mouse events for each duck: MouseLeftButtonDown, MouseMove, and MouseLeftButtonUp. When the page is loaded, I loop through through each duck on the canvas and add these 3 event handlers for them.
Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Me.InitializeComponent()
For Each element As UIElement In LayoutRoot.Children
If TypeOf (element) Is Duck Then
Dim item As Duck = DirectCast(element, Duck)
AddHandler item.MouseLeftButtonDown, AddressOf duck_MouseLeftButtonDown
AddHandler item.MouseLeftButtonUp, AddressOf duck_MouseLeftButtonUp
AddHandler item.MouseMove, AddressOf duck_MouseMove
End If
Next
End Sub
When the user presses the left mouse button on a duck, we need to capture what the current X and Y coordinates are, set that the mouse left button is down, and capture the mouse events for the duck.
Sub duck_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim item As Duck = DirectCast(sender, Duck)
mousePosition = e.GetPosition(Nothing)
Me.isMouseDown = True
item.CaptureMouse()
End Sub
Take note of line 5. The item.CaptureMouse() method basically tells Silverlight to only handle mouse events for the duck we are dragging. As the user moves the mouse, the MouseMove event is fired. This event will fire regardless if the user is dragging the duck or not. Therefore we check to see if the left mouse button is down first. If it is, it's being dragged so we want to refresh the duck's new position. We use the current position of the mouse and calculate what the new position the duck should be set to relative to the canvas.
Sub duck_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim item As Duck = DirectCast(sender, Duck)
If (Me.isMouseDown) Then
Dim deltaV As Double = e.GetPosition(Nothing).Y - mousePosition.Y
Dim deltaH As Double = e.GetPosition(Nothing).X - mousePosition.X
Dim newTop As Double = deltaV + DirectCast(item.GetValue(Canvas.TopProperty), Double)
Dim newLeft As Double = deltaH + DirectCast(item.GetValue(Canvas.LeftProperty), Double)
item.SetValue(Canvas.TopProperty, newTop)
item.SetValue(Canvas.LeftProperty, newLeft)
mousePosition = e.GetPosition(Nothing)
End If
End Sub
When the user releases the left mouse button, we release the mouse capture and set our isMouseDown variable back to false.
Sub duck_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseEventArgs)
Dim item As Duck = DirectCast(sender, Duck)
isMouseDown = False
mousePosition = New Point(0, 0)
item.ReleaseMouseCapture()
End Sub
The final application looks like below. You can drag the ducks around the canvas.
Drag-N-Drop_Soln.zip (2.11 mb)