Introduction
This article shows how to implement a WPF label control that can be dragged and resized at runtime. Even though the current implementation is done based on the WPF label control, with a small amount of modifications, the code and logic here should be able to be reused for making any WPF control draggable and resizable at runtime.
Description
Most of the code for the draggable label is self explanatory. The core concept used for achieving the dragging effect is explained below.
To implement the runtime drag functionality, basically we need two pieces of information - the previous location of the mouse and the current location of the mouse. Using that information, the distance the control was dragged can be calculated. Therefore at the beginning of each mouse move event, the current location of the mouse is captured and assigned to the previous location at the end of the mouse move event.
protected override void OnMouseMove(MouseEventArgs e)
{
Window wnd = Window.GetWindow(this);
Point currentLocation = e.MouseDevice.GetPosition(wnd);
...
...
...
_previousLocation = currentLocation;
}
In WPF, a position of a control can be changed by applying a TranslateTransform
to it. The delta TranslateTransform
can be calculated within the mouse move event using the previous mouse location and the current mouse location. But when applying the TranslateTransform
for the drag delta, we have to be careful not to destroy any existing transforms applied to the draggable label. Therefore a TransformGroup
with the previous transform and the drag delta will be created and applied.
var delta = new TranslateTransform
(currentLocation.X - _previousLocation.X, currentLocation.Y - _previousLocation.Y);
var group = new TransformGroup();
group.Children.Add(_previousTransform);
group.Children.Add(delta);
this.RenderTransform = group;
_ previousTransform = this.RenderTransform;
In addition to the events and properties inherited from the WPF label control, the draggable label control exposes two additional events.
Drag
Fired when the control is being dragged. DraggableLabelDragEventArgs
are passed in as event arguments. The DraggableLabelDragEventArgs
exposes the following properties:
X
– Current horizontal position of the draggable label
Y
– Current vertical position of the draggable label
Resize
Fired when the control is being resized. DraggableLabelResizeEventArgs
are passed in as event arguments. The DraggableLabelResizeEventArgs
exposes the following properties:
Width
– Current width of the draggable label
Height
– Current height of the draggable label
Usage
The draggable label can be added to any container similarly to any other WPF user control. In Visual Studio 2008, right click on the Toolbox and click “Choose Items...”. In the Choose Toolbox Items dialog box, go to the WPF Components tab. Browse for the RtwControls.DraggableLabel.dll assembly and click Open. The draggable label control will be added to the WPF Components list. Click OK to close the toolbox items dialog and add the draggable label control to the Toolbox. Now the draggable label can be dragged and dropped from the toolbox.
Alternatively, you can also manually add a reference to the RtwControls.DraggableLabel.dll assembly from your WPF project and use the namespace for the draggable label as indicated below.
<Window x:Class="DraggableLabelTest.LayoutWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rtw="clr-namespace:RtwControls;assembly=RtwControls.DraggableLabel"
Title="Layout" Height="403" Width="836">
<Grid>
<rtw:DraggableLabel BorderBrush="Black" BorderThickness="1"
HorizontalAlignment="Left" Margin="12,12,0,0" Name="Label1"
OverridesDefaultStyle="False" Drag="draggableLabel_Drag"
Resize="draggableLabel_Resize"
VerticalAlignment="Top">Label1</rtw:DraggableLabel>
</Grid>
</Window>
Demo Application
The demo application shows how to implement a customizable print layout using the draggable label control. The main window contains the fields whose data will be printed according to the custom layout.
From the layout window, the user can customize the print layout by dragging and resizing the draggable labels. Once saved, the custom locations will be saved in the "layout.xml" file.
While printing, the saved locations will be loaded from the "layout.xml" file and the data will be printed at the appropriate positions.
History
- April 13, 2010: First release