In my previous post on this topic, I gave a quick overview of how Drag and Drop can be accomplished using attached properties. To review, here are the key elements of the implementation:
The property changed handlers for the attached properties hooks up events for the source and target controls. Below is the handler for the DragSourceAdvisor property. Note that here I am hooking up to the Mouse events for initiating DragDrop. These events are primarily used to detect the drag gesture. For more information read Marcelo’s blog.
private static void OnDragSourceAdvisorChanged(DependencyObject depObj,
DependencyPropertyChangedEventArgs args)
{
UIElement sourceElt = depObj as UIElement;
if (args.NewValue != null && args.OldValue == null)
{
sourceElt.PreviewMouseLeftButtonDown +=
new MouseButtonEventHandler(DragSource_PreviewMouseLeftButtonDown);
sourceElt.PreviewMouseMove +=
new MouseEventHandler(DragSource_PreviewMouseMove);
sourceElt.PreviewMouseLeftButtonUp +=
new MouseButtonEventHandler(DragSource_PreviewMouseLeftButtonUp);
sourceElt.PreviewGiveFeedback +=
new GiveFeedbackEventHandler(DragSource_PreviewGiveFeedback);
// Set the Drag source UI
IDragSourceAdvisor advisor = args.NewValue as IDragSourceAdvisor;
advisor.SourceUI = sourceElt;
}
else if (args.NewValue == null && args.OldValue != null)
{
sourceElt.PreviewMouseLeftButtonDown -= DragSource_PreviewMouseLeftButtonDown;
sourceElt.PreviewMouseMove -= DragSource_PreviewMouseMove;
sourceElt.PreviewMouseLeftButtonUp -= DragSource_PreviewMouseLeftButtonUp;
sourceElt.PreviewGiveFeedback -= DragSource_PreviewGiveFeedback;
}
}
and the DropTargetAdvisor property handler:
private static void OnDropTargetAdvisorChanged(DependencyObject depObj,
DependencyPropertyChangedEventArgs args)
{
UIElement targetElt = depObj as UIElement;
if (args.NewValue != null && args.OldValue == null)
{
targetElt.PreviewDragEnter += new DragEventHandler(DropTarget_PreviewDragEnter);
targetElt.PreviewDragOver += new DragEventHandler(DropTarget_PreviewDragOver);
targetElt.PreviewDragLeave += new DragEventHandler(DropTarget_PreviewDragLeave);
targetElt.PreviewDrop += new DragEventHandler(DropTarget_PreviewDrop);
targetElt.AllowDrop = true;
// Set the Drag source UI
IDropTargetAdvisor advisor = args.NewValue as IDropTargetAdvisor;
advisor.TargetUI = targetElt;
}
else if (args.NewValue == null && args.OldValue != null)
{
targetElt.PreviewDragEnter -= DropTarget_PreviewDragEnter;
targetElt.PreviewDragOver -= DropTarget_PreviewDragOver;
targetElt.PreviewDragLeave -= DropTarget_PreviewDragLeave;
targetElt.PreviewDrop -= DropTarget_PreviewDrop;
targetElt.AllowDrop = false;
}
}
Since all the event handlers are part of the DragDropManager, all the dirty work ;) will be done here and the appropriate interface methods will be called. The calls to these interface methods are spread across the different event handlers.
Examples
In the attached zip, I have included two examples:
The source for both the examples should be pretty self-explanatory so I am not going over it. Since both the examples are part of the same project, you will have to change the StartupUri in App.xaml to switch between examples. Use the following StartupUris:
CanvasExample: StartupUri="CanvasExample/DragCanvasExample.xaml"
PanelExample: StartupUri="PanelExample/Window1.xaml"
Anyways, feel free to use the code in your own apps. If you do come up with a scenario where the interface methods are not sufficient, say, drop me a line and I would be glad to fix it. Any feedback…good, bad, ugly is welcome ;)