Introduction
Silverlight gives you easy access to make your User Controls come alive. For example you can make any control in Silverlight draggable. Here's how:
In your XAML Code add a TranslateTransform inside your layout grid of your user control. The TranslateTransform will allow you to move your grid along the x and y coordinates of your application
Listing 1 - Adding the TranslateTransform to your control
<Grid x:Name="LayoutRoot" >
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform x:Name="LocalTranslateTransform"/>
</TransformGroup>
</Grid.RenderTransform>
Now we want to pick a control inside the UserControl to grab onto. In our sample we will use a Border control. Inside the Border control, we'll add mouse events to handle the various states of dragging with the mouse.
Listing 2 - Hooking up the mouse events to the Border control
<Border x:Name="myToolbar"
MouseLeftButtonDown="OnToolbarClicked" MouseLeftButtonUp="OnToolbarReleased" MouseMove="OnToolbarMoving" />
The Code
The XAML part was pretty simple. Now let's look at the code behind. All of the dragging functionality is handled by our 3 event handlers: OnToolbarClicked, OnToolbarReleased, and OnToolbarMoving. When we first click down on the border control, we need to record the initial offset point for our transform. We also need to set the state to mouseDownInToolbar to true to indicate we are dragging. Finally we need to set the mouse mode to capturing inside the border control.
Listing 3 - Handling the mousedown event inside the border
private void
OnToolbarClicked(object sender, MouseButtonEventArgs e)
{
mouseDownInToolbar = true;
DragOffset = e.GetPosition(LayoutRoot);
toolbarBorder.CaptureMouse();
}
While the mouse is in the mouseDownInToolbar state, we need to translate the position of the toolbar in reference to the position of the mouse. Listing 4 illustrates how we go about this. We get the position of the mouse relative to the main grid of the control. Then we change the TranslateTransform of the grid based on the new position of the mouse. We also need to offset the current mouse position by the original location of the mouse when we first clicked down in the control. Everytime we move the mouse, the new TranslateTransform will be computed and our control will move to the translated location. The mouse cursor will remain at the point when we first clicked the toolbar.
Listing 4 - handling the dragging of the control while the mouse is moving
private void
OnToolbarMoving(object sender, MouseEventArgs e)
{
if (mouseDownInToolbar)
{
// we want to move
it based on the position of the mouse
moveUserControl(e);
}
}
private void
moveUserControl (MouseEventArgs e)
{
Point mousePos = e.GetPosition(LayoutRoot);
Double newX = LocalTranslateTransform.X + (mousePos.X - DragOffset.X);
Double newY = LocalTranslateTransform.Y + (mousePos.Y - DragOffset.Y);
LocalTranslateTransform.X = newX;
LocalTranslateTransform.Y = newY;
}
When the user unclicks the mouse, we need to stop the drag process. The MouseUp event handler will release the mouse capture and set the mouseDownInToolbar state to false. This will prevent the toolbar to continue to move as we drag the mouse around the screen.
Listing 5 - Handling Mouse Up when dragging the Toolbar
private void
OnToolbarReleased(object sender, MouseButtonEventArgs e)
{
mouseDownInToolbar = false;
toolbarBorder.ReleaseMouseCapture();
}
Conclusion
Manipulating size and position of controls is fairly easy in Silverlight with the power of transforms. Dragging a control is accomplished using the TranslateTransform in conjunction with mouse events and functions. You can probably take this a step further and build your own docking framework. Anyway, drag yourself away from conventional controls in Windows and enjoy the power and flexibility of WPF in the browser with Silverlight.