Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Custom Groupbox UIElement and Dropping of Nodes (Read 5473 times)
integragreg
YaBB Newbies
*
Offline



Posts: 40
Location: Tennessee
Joined: Jan 26th, 2009
Custom Groupbox UIElement and Dropping of Nodes
Feb 22nd, 2011 at 5:29pm
Print Post  
We have created a custom WPF Groupbox control that behaves in a similar manner to the Windows Forms group box.

We are able to place it on a diagram and drag items from a toolbar and drop them into our groupbox. We have also implemented functionality that allows us to drag an item out of the groupbox and drop it onto a diagram.

The thing that we cannot seem to accomplish is selecting a node that has been dropped onto a diagram, then dragging and dropping it into our groupbox. We've tried initiating DragDrop.DoDragDrop() from the Diagram.NodeModifying event handler, as well as from the Diagram.NodeModified handler. But every time that we do so, the diagram's OnDrop() method is called and we can never invoke the drop handling that is built into our control.

Can you provide us with some guidance on how to "bypass" the diagram's OnDrop handling when a node is dragged and dropped over a container control? We can provide a sample project, if necessary.


Thanks,

Greg
  
Back to top
WWW  
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Custom Groupbox UIElement and Dropping of Node
Reply #1 - Feb 22nd, 2011 at 7:19pm
Print Post  
Hi,

If that Groupbox is a child of the diagram, the Drop event should bubble through it before reaching the diagram or other parent controls up the visual tree. If you set a breakpoint at the Groupbox' handler, doesn't the debugger ever stop there? Alternatively you could try handling PreviewDrop (the tunneling phase of the event) and your handler should always get called before any Drop handlers run.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
integragreg
YaBB Newbies
*
Offline



Posts: 40
Location: Tennessee
Joined: Jan 26th, 2009
Re: Custom Groupbox UIElement and Dropping of Node
Reply #2 - Feb 22nd, 2011 at 9:14pm
Print Post  
Yes, the Groupbox's OnDrop() method is called, and if we set e.Handled = true, then the Diagram's OnDrop() does not get called.

So it seems that I need to modify my original post a bit and say that we don't know exactly where to call the DragDrop.DoDragDrop method.

We have created a new custom node class that inherits from DiagramNode, and in its OnDragOver(DiagramItem) override, we initiate the DragDrop.DoDragDrop, and this seems to work. But we'd like to not have to use a custom node, if possible.

The other issue we see is that we'd like to remove the node that was originally dragged from the diagram, since it is now going to be dropped onto the groupbox. When we do so, however, we are getting a NullReferenceException with the following call stack (truncated):

Code
Select All
   at MindFusion.Diagramming.Wpf.DiagramNode.x19a8a761a691d529(Rect xa6236fc5cd405c4e, Point x2f7096dac971d6ec, InteractionState xab29833053004740)
   at MindFusion.Diagramming.Wpf.DiagramNode.x690a7db222c5c9f0(Rect xfcad4c0a9c5890c6, Rect x3bd62873fafa6252, Point x2f7096dac971d6ec, AdjustmentHandles xe72ccf98bea3cb87, InteractionState xab29833053004740)
   at MindFusion.Diagramming.Wpf.DiagramNode.AllowModify(Point current, InteractionState ist)
   at MindFusion.Diagramming.Wpf.InteractionState.ValidateAndSetCursor(Point point, Diagram diagram)
   at MindFusion.Diagramming.Wpf.Behaviors.BehaviorBase.OnMouseMove(Point mousePosition)
   at MindFusion.Diagramming.Wpf.Diagram.OnPreviewMouseMove(MouseEventArgs e)
   at System.Windows.UIElement.OnPreviewMouseMoveThunk(Object sender, MouseEventArgs e)
   at System.Windows.Input.MouseEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.MouseDevice.Synchronize()
   at System.Windows.Input.MouseDevice.ChangeMouseCapture(IInputElement mouseCapture, IMouseInputProvider providerCapture, CaptureMode captureMode, Int32 timestamp)
   at System.Windows.Input.MouseDevice.PreNotifyInput(Object sender, NotifyInputEventArgs e)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.SafeNativeMethods.SafeNativeMethodsPrivate.IntReleaseCapture()
   at MS.Win32.SafeNativeMethods.ReleaseCapture()
   at System.Windows.Interop.HwndMouseInputProvider.System.Windows.Input.IMouseInputProvider.ReleaseMouseCapture()
   at System.Windows.Input.MouseDevice.Capture(IInputElement element, CaptureMode captureMode)
   at System.Windows.UIElement.ReleaseMouseCapture()
   at MindFusion.Diagramming.Wpf.Diagram.x355258a28dc3da25(MouseButtonEventArgs xfbf34718e704c6bc, Point xb30c565aa19aece6)
   at MindFusion.Diagramming.Wpf.Diagram.OnPreviewMouseUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnPreviewMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)

 

  
Back to top
WWW  
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Custom Groupbox UIElement and Dropping of Node
Reply #3 - Feb 22nd, 2011 at 9:36pm
Print Post  
Perhaps it is best to start the d-n-d operation from the NodeStartModifying handler, and set args.Cancel to prevent starting the diagram's move operation. That should also avoid the exception.
  
Back to top
 
IP Logged
 
integragreg
YaBB Newbies
*
Offline



Posts: 40
Location: Tennessee
Joined: Jan 26th, 2009
Re: Custom Groupbox UIElement and Dropping of Node
Reply #4 - Feb 23rd, 2011 at 1:32pm
Print Post  
After some additional work, we have been able to avoid the exception. We begin our drag/drop operation in our custom node's OnDragOver(DiagramItem) override, and the following code was used to avoid the exception:

Code
Select All
item.Parent.Behavior = Behavior.DoNothing;

                    if (item.Parent.Interaction != null)
                    {
                        item.Parent.Interaction.SetItemDeleted();
                    }
                    item.Parent.Items.Remove(item);
                    item.Parent.Behavior = Behavior.Modify;
 



Our preference would be to not use a custom node, though. We will try initiating the drag/drop in the NodeStartModifying handler. But by doing so, it seems like we would end up commencing a drag/drop operation every time we modify a node, rather than doing so only when a node is dragged over our groupbox. It also sounds like this approach would prevent us from moving a node, which we need to be able to do. Am I correct on that statement? If so, then I'm not sure that we'd achieve the desired result.
  
Back to top
WWW  
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Custom Groupbox UIElement and Dropping of Node
Reply #5 - Feb 23rd, 2011 at 2:02pm
Print Post  
Yes, calling it from the StartModifying handler will prevent mixing both kinds of drag operations. If you need to support the diagram's move operation together with drag-and-drop, try calling DoDragDrop from NodeModifying and call args.CancelNow if you need to delete the node. I'm not sure it's a good idea to do that immediately anyway; the user might choose not to drop the node into the groupbox and then it will just disappear? So perhaps you should delete the node from the groupbox' OnDrop handler.
  
Back to top
 
IP Logged
 
integragreg
YaBB Newbies
*
Offline



Posts: 40
Location: Tennessee
Joined: Jan 26th, 2009
Re: Custom Groupbox UIElement and Dropping of Node
Reply #6 - Feb 28th, 2011 at 3:28pm
Print Post  
Yes, that's what we are doing: we delete the node from the diagram in the groupbox's OnDrop handler. So it sounds like we are moving in the right direction.

Thank you for the valuable feedback.
  
Back to top
WWW  
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Custom Groupbox UIElement and Dropping of Node
Reply #7 - Mar 2nd, 2011 at 10:00am
Print Post  
I thought OnDrop will run after NodeModifying, but it runs in the context of DoDragDrop and you can't delete the item before NodeModifying exits. Try this instead:

Code
Select All
void diagram_PreviewMouseMove(object sender, MouseEventArgs e)
{
	if (diagram.Interaction != null &&
		diagram.Interaction.CurrentItem is DiagramNode &&
		diagram.Interaction.Action == Action.Modify)
	{
		Point mp = e.GetPosition(diagram.DocumentPlane);
		if (mp.X > 300)// eg. if over the groupbox
		{
			diagram.CancelDrag();
			DragDrop.DoDragDrop(this, "data", DragDropEffects.All);
		}
	}
}

protected override void OnDrop(DragEventArgs e)
{
	e.Effects = DragDropEffects.Move;
	e.Handled = true;
	diagram.Items.Remove(diagram.ActiveItem);
} 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint