My other "solution" implements a usercontrol which can be dragged around the same canvas it's originally placed on.
If you meant you need to drag the user controls from another element on TO a Canvas, then here's an example using WPF drag and drop...
First, implement a custom Canvas class which is a drop target and a drag/drop data class to pass info from the drag/drop source to the drop target:
public class DropableCanvas : Canvas
{
public DropableCanvas()
: base()
{
this.AllowDrop = true;
this.Drop += new DragEventHandler(DropableCanvas_Drop);
}
void DropableCanvas_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DropableCanvasDragDropData)))
{
DropableCanvasDragDropData dragdropdata = e.Data.GetData(typeof(DropableCanvasDragDropData)) as DropableCanvasDragDropData;
dragdropdata.SourcePanel.Children.Remove(dragdropdata.UserControl);
Point dropPoint = e.GetPosition(this);
Canvas.SetLeft(dragdropdata.UserControl, dropPoint.X - dragdropdata.OffsetPoint.X);
Canvas.SetTop(dragdropdata.UserControl, dropPoint.Y - dragdropdata.OffsetPoint.Y);
this.Children.Add(dragdropdata.UserControl);
}
e.Handled = true;
}
}
public class DropableCanvasDragDropData
{
public DropableCanvasDragDropData(Panel srcpanel, UserControl control, Point pt)
{
this.SourcePanel = srcpanel;
this.UserControl = control;
this.OffsetPoint = pt;
}
public Panel SourcePanel { get; protected set; }
public UserControl UserControl { get; protected set; }
public Point OffsetPoint { get; protected set; }
}
Next,implement a dragable user control by making it a drag source:
public partial class DragableUserControl : UserControl
{
public DragableUserControl()
{
InitializeComponent();
}
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
DragableUserControl dragableusercontrol = sender as DragableUserControl;
if (dragableusercontrol != null && e.LeftButton == MouseButtonState.Pressed)
{
DragDrop.DoDragDrop(dragableusercontrol,
new DropableCanvasDragDropData(dragableusercontrol.Parent as Panel, dragableusercontrol, e.GetPosition(dragableusercontrol)),
DragDropEffects.All);
}
}
}
<UserControl x:Class="WPFTester.DragableUserControl"
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/blend/2008"
mc:Ignorable="d"
MouseMove="UserControl_MouseMove"
>
<Grid Width="100" Height="100" >
<Border Background="SteelBlue" />
</Grid>
</UserControl>
And finally, test it all:
<UserControl x:Class="WPFTester.DragControlTestPage"
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/blend/2008"
xmlns:local="clr-namespace:WPFTester"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="450"
>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:DropableCanvas Grid.Column="0" Background="LightSteelBlue" Height="200" Width="200" Margin="10" >
<local:DragableUserControl Canvas.Left="10" Canvas.Top="10" />
</local:DropableCanvas>
<local:DropableCanvas Grid.Column="1" Background="LightSteelBlue" Height="200" Width="200" Margin="10" >
<local:DragableUserControl Canvas.Left="10" Canvas.Top="10" />
</local:DropableCanvas>
</Grid>
</UserControl>
You should be able to drag and drop the two dragable usercontrols between the two canvases.
*Edit* 7/5/2011 Removed a couple unused fields from the DragableUserControl class...oops.
*Edit* 7/6/2011 Here's an example of dropping a new usercontrol of the same type as the dragged usercontrol instead of moving the dragged control. Just change the DropableCanvas.DropableCanvas_Drop method to this:
void DropableCanvas_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(DropableCanvasDragDropData)))
{
DropableCanvasDragDropData dragdropdata = e.Data.GetData(typeof(DropableCanvasDragDropData)) as DropableCanvasDragDropData;
UserControl newcontrol;
try
{
newcontrol = Activator.CreateInstance(dragdropdata.UserControl.GetType()) as UserControl;
}
catch (Exception)
{
newcontrol = null;
}
if (newcontrol != null)
{
Point dropPoint = e.GetPosition(this);
Canvas.SetLeft(newcontrol, dropPoint.X - dragdropdata.OffsetPoint.X);
Canvas.SetTop(newcontrol, dropPoint.Y - dragdropdata.OffsetPoint.Y);
this.Children.Add(newcontrol);
}
}
e.Handled = true;
}