Hi,
You can find an example below. It opens a new window that covers the whole screen to enable drawing the node everywhere. The drag operation is started by holding down shift while pressing the mouse button. It doesn't actually use the Windows drag/drop events, since MouseMove is enough when we cover the whole screen. VisualTreeHelper.HitTest might not work with the dock control you are using if it creates system windows via the Win32 API. In such case you will have to use the dock control's API for hit testing.
Another option might be to create a small window - just as big as the node - and move the window around while the mouse moves. This might be necessary if you have to support drag between two instances of the application, since VisualTreeHelper won't work then, and you will have to use OLE drag/drop instead of MouseMove anyway.
The code below is from a modification of the MultiViews sample project, where you must also add these changes:
In MainWindow.xaml, add the following attribute to windowHost:
PreviewMouseDown="OnPreviewMouseDown"
In MainWindow.xaml.cs, replace the window.Content = view assignment with:
window.Content = new Diagram();
I hope that helps,
Stoyan
private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
{
VisualTreeHelper.HitTest((Visual)sender, null, StartDrag,
new PointHitTestParameters(e.GetPosition((IInputElement)sender)));
e.Handled = true;
}
}
private HitTestResultBehavior StartDrag(HitTestResult result)
{
var node = result.VisualHit as DiagramNode;
if (node != null)
{
overlay = new Window();
overlay.AllowsTransparency = true;
overlay.WindowStyle = WindowStyle.None;
overlay.Background = Brushes.Transparent;
overlay.ShowInTaskbar = false;
overlay.Left = 0;
overlay.Top = 0;
overlay.Width = 2000;
overlay.Height = 2000;
overlay.Show();
overlay.Topmost = true;
var diagram = new Diagram();
diagram.BackBrush = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0));
diagram.Bounds = new Rect(0, 0, 2000, 2000);
diagram.CaptureMouse();
diagram.Focus();
diagram.PreviewMouseMove += OnOverlayMouseMove;
diagram.PreviewMouseUp += OnOverlayMouseUp;
overlay.Content = diagram;
var clone = (DiagramNode)node.Clone(false);
diagram.Nodes.Add(clone);
overlay.UpdateLayout();
var pos = Mouse.GetPosition(diagram.DocumentPlane);
clone.Move(
pos.X - clone.Bounds.Width / 2,
pos.Y - clone.Bounds.Height / 2);
return HitTestResultBehavior.Stop;
}
return HitTestResultBehavior.Continue;
}
private void OnOverlayMouseMove(object sender, MouseEventArgs e)
{
var diagram = (Diagram)sender;
var pos = e.GetPosition(diagram.DocumentPlane);
var clone = diagram.Nodes[0];
clone.Move(
pos.X - clone.Bounds.Width / 2,
pos.Y - clone.Bounds.Height / 2);
}
private void OnOverlayMouseUp(object sender, MouseButtonEventArgs e)
{
overlay.Close();
windowHost.CaptureMouse();
var mousePos = Mouse.GetPosition(windowHost);
windowHost.ReleaseMouseCapture();
VisualTreeHelper.HitTest(
windowHost, null, EndDrag,
new PointHitTestParameters(mousePos));
}
private HitTestResultBehavior EndDrag(HitTestResult result)
{
// result.VisualHit is diagram.DocumentPlane
var diagram = VisualTreeHelper.GetParent(result.VisualHit) as Diagram;
if (diagram != null)
{
var overlayDiagram = (Diagram)overlay.Content;
var clone = (DiagramNode)overlayDiagram.Nodes[0].Clone(false);
diagram.Nodes.Add(clone);
var pos = Mouse.GetPosition(diagram.DocumentPlane);
clone.Move(
pos.X - clone.Bounds.Width / 2,
pos.Y - clone.Bounds.Height / 2);
return HitTestResultBehavior.Stop;
}
return HitTestResultBehavior.Continue;
}
Window overlay;