context: using System;
  using System.Windows;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Diagnostics;
  
  //Original code
  //From Pavan Podila & Kevin Hoffman 
  //WPF Control Development
  
  namespace MusicCollectionWPF.Infra
  {
      public static class DragDropManager
      {
          private static readonly string DragOffsetFormat = "DnD.DragOffset";
  
          public static readonly DependencyProperty DragSourceAdvisorProperty =
              DependencyProperty.RegisterAttached("DragSourceAdvisor", typeof(IDragSourceAdvisor),
                                                  typeof(DragDropManager),
                                                  new FrameworkPropertyMetadata(
                                                      new PropertyChangedCallback(OnDragSourceAdvisorChanged)));
  
          public static readonly DependencyProperty DropTargetAdvisorProperty =
              DependencyProperty.RegisterAttached("DropTargetAdvisor", typeof(IDropTargetAdvisor),
                                                  typeof(DragDropManager),
                                                  new FrameworkPropertyMetadata(
                                                      new PropertyChangedCallback(OnDropTargetAdvisorChanged)));
  
          private static Point _adornerPosition;
  
          private static UIElement _draggedElt;
          private static Point _dragStartPoint;
          private static bool _isMouseDown;
          private static Point _offsetPoint;
          private static DropPreviewAdorner _overlayElt;
          private static bool _IsDropCompletedOK = false;
  
          //private static IDragSourceAdvisor s_currentDragSourceAdvisor;
          private static IDropTargetAdvisor s_currentDropTargetAdvisor;
          //private static IDragSourceAdvisor CurrentDragSourceAdvisor
          //{
          //    get { return s_currentDragSourceAdvisor; }
          //    set { s_currentDragSourceAdvisor = value; }
          //}
  
          private static IDropTargetAdvisor CurrentDropTargetAdvisor
          {
              get { return s_currentDropTargetAdvisor; }
              set 
              {
                  if (s_currentDropTargetAdvisor != value)
                      s_currentDropTargetAdvisor = value; 
              }
          }
  
  
          private static WeakReference _CurrentDragSourceAdvisor = new WeakReference(null);
          private static IDragSourceAdvisor CurrentDragSourceAdvisor
          {
              get { return _CurrentDragSourceAdvisor.Target as IDragSourceAdvisor; }
              set { _CurrentDragSourceAdvisor.Target = value; }
          }
  
          //private static WeakReference _CurrentDropTargetAdvisor = new WeakReference(null);
          //private static IDropTargetAdvisor CurrentDropTargetAdvisor
          //{
          //    get { return _CurrentDropTargetAdvisor.Target as IDropTargetAdvisor; }
          //    set { _CurrentDropTargetAdvisor.Target = value; }
          //}
  
          #region Dependency Properties Getter/Setters
  
          public static void SetDragSourceAdvisor(DependencyObject depObj, IDragSourceAdvisor advisor)
          {
              depObj.SetValue(DragSourceAdvisorProperty, advisor);
          }
  
          public static void SetDropTargetAdvisor(DependencyObject depObj, IDropTargetAdvisor advisor)
          {
              depObj.SetValue(DropTargetAdvisorProperty, advisor);
          }
  
          public static IDragSourceAdvisor GetDragSourceAdvisor(DependencyObject depObj)
          {
              return depObj.GetValue(DragSourceAdvisorProperty) as IDragSourceAdvisor;
          }
  
          public static IDropTargetAdvisor GetDropTargetAdvisor(DependencyObject depObj)
          {
              return depObj.GetValue(DropTargetAdvisorProperty) as IDropTargetAdvisor;
          }
  
          #endregion
  
          #region Property Change handlers
  
          private static void OnDragSourceAdvisorChanged(DependencyObject depObj,
                                                         DependencyPropertyChangedEventArgs args)
          {
              UIElement sourceElt = depObj as UIElement;
              if (args.NewValue != null && args.OldValue == null)
              {
                  sourceElt.PreviewMouseLeftButtonDown += DragSource_PreviewMouseLeftButtonDown;
                  sourceElt.PreviewMouseMove += DragSource_PreviewMouseMove;
                  sourceElt.PreviewMouseUp += DragSource_PreviewMouseUp;
  
                  // 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.PreviewMouseUp -= DragSource_PreviewMouseUp;
              }
          }
  
          private static void OnDropTargetAdvisorChanged(DependencyObject depObj,
                                                         DependencyPropertyChangedEventArgs args)
          {
              UIElement targetElt = depObj as UIElement;
              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 = true;
  
                  //targetElt.DragEnter += DropTarget_DragEnter;
  
                  // Set the Drag source UI
                  IDropTargetAdvisor advisor = args.NewValue as IDropTargetAdvisor;
                  advisor.TargetUI = targetElt;
              }
              else if (args.NewValue == null && args.OldValue != null)
              {
                  //targetElt.DragEnter -= DropTarget_DragEnter;
  
                  targetElt.PreviewDragEnter -= DropTarget_PreviewDragEnter;
                  targetElt.PreviewDragOver -= DropTarget_PreviewDragOver;
                  targetElt.PreviewDragLeave -= DropTarget_PreviewDragLeave;
                  targetElt.PreviewDrop -= DropTarget_PreviewDrop;
                  targetElt.AllowDrop = false;
              }
          }
  
          #endregion
  
          /* ____________________________________________________________________
  		 *		Drop Target events 
  		 * ____________________________________________________________________
  		 */
  
          private static void DropTarget_PreviewDrop(object sender, DragEventArgs e)
          {
              UpdateEffects(e);
  
  
  
              Point dropPoint = e.GetPosition(sender as UIElement);
  
              // Calculate displacement for (Left, Top)
              Point offset = e.GetPosition(_overlayElt);
              dropPoint.X = dropPoint.X - offset.X;
              dropPoint.Y = dropPoint.Y - offset.Y;
  
              RemovePreviewAdorner();
              _offsetPoint = new Point(0, 0);
  
              if (CurrentDropTargetAdvisor.IsValidDataObject(e.Data))
              {
                  _IsDropCompletedOK = CurrentDropTargetAdvisor.OnDropCompleted(e.Data, dropPoint, e.OriginalSource);
              }
              e.Handled = true;
              CurrentDropTargetAdvisor = null;
          }
  
          private static void DropTarget_PreviewDragLeave(object sender, DragEventArgs e)
          {
              UpdateEffects(e);
  
              RemovePreviewAdorner();
              e.Handled = true;
              CurrentDropTargetAdvisor = null;
          }
  
          private static void DropTarget_PreviewDragOver(object sender, DragEventArgs e)
          {
              UpdateEffects(e);
  
              // Update position of the preview Adorner
              _adornerPosition = e.GetPosition(sender as UIElement);
              PositionAdorner();
  
              e.Handled = true;
          }
  
          private static void DropTarget_PreviewDragEnter(object sender, DragEventArgs e)
          {
                 // Get the current drop target advisor
              IDropTargetAdvisor dsa = GetDropTargetAdvisor(sender as DependencyObject);
              CurrentDropTargetAdvisor = dsa;
     
              UpdateEffects(e);
  
              // Setup the preview Adorner
  
gt:             _offsetPoint = new Point();