title: WPF Drag and Drop with Adorner using mouse and touch
body: <p>I want this to be good question, so I'll write in details what I would like to achieve, what I've found on the internet and I show what I've done so far and what I've tried.</p>
  
  <p>I need to add drag and drop functionality to my application. I have Images (basically controls) that I want to drag to items of listbox.</p>
  
  <p>Here is sample UI:</p>
  
  <p><a href="https://i.stack.imgur.com/UAI96.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UAI96.png" alt="enter image description here"></a></p>
  
  <p>And here is usage I have now:</p>
  
  <p><a href="https://i.stack.imgur.com/XX1bA.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XX1bA.gif" alt="enter image description here"></a></p>
  
  <p>As You can see I'm able to drag one of four images and drop it over listbox item.
  If I move image over correct target (listbox image) image near cursor disappears and everything works fine, but when I don't drop image on list item (I release mouse) that image stays on screen.</p>
  
  <p>I've based my solution on answers to <a href="https://stackoverflow.com/questions/3129443/wpf-4-drag-and-drop-with-visual-element-as-cursor">this</a> question, and I'm unable to remove that unwanted window (image near cursor)</p>
  
  <p>My XAML looks like this:</p>
  
  <pre><code>&lt;Window x:Class="DragDrop.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="Drag'n'Drop" Height="350" Width="525"
          DataContext="{Binding RelativeSource={RelativeSource Self}}"&gt;
      &lt;Grid&gt;
          &lt;ListBox HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Height="300" Margin="0,10,10,0" VerticalAlignment="Top" Width="234" ItemsSource="{Binding People}"&gt;
              &lt;ListBox.ItemTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;StackPanel Orientation="Vertical" AllowDrop="True" PreviewDrop="UIElement_OnPreviewDrop"&gt;
                          &lt;TextBlock Text="{Binding Name}" FontWeight="Bold" /&gt;
                          &lt;ProgressBar Height="20" Value="{Binding Points}" Margin="0,0,0,0"/&gt;
                      &lt;/StackPanel&gt;
                  &lt;/DataTemplate&gt;
              &lt;/ListBox.ItemTemplate&gt;
          &lt;/ListBox&gt;
  
          &lt;Image HorizontalAlignment="Left" Height="72" Margin="10,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-60000-icon.png" RenderTransformOrigin="0.5,0.5"
                 PreviewMouseLeftButtonDown="OnMouseTouchDown"
                 PreviewTouchDown="OnMouseTouchDown"
                 PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="10"/&gt;
          &lt;Image HorizontalAlignment="Left" Height="72" Margin="87,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700000-icon.png" RenderTransformOrigin="0.5,0.5"
                 PreviewMouseLeftButtonDown="OnMouseTouchDown"
                 PreviewTouchDown="OnMouseTouchDown"
                 PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="20"/&gt;
          &lt;Image HorizontalAlignment="Left" Height="72" Margin="10,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-7000-icon.png" RenderTransformOrigin="0.5,0.5"
                 PreviewMouseLeftButtonDown="OnMouseTouchDown"
                 PreviewTouchDown="OnMouseTouchDown"
                 PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="30"/&gt;
          &lt;Image HorizontalAlignment="Left" Height="72" Margin="87,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700-icon.png" RenderTransformOrigin="0.5,0.5"
                 PreviewMouseLeftButtonDown="OnMouseTouchDown"
                 PreviewTouchDown="OnMouseTouchDown"
                 PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="40"/&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>And code behind:</p>
  
  <pre><code>public partial class MainWindow
  {
      private readonly ObservableCollection&lt;Person&gt; _people = new ObservableCollection&lt;Person&gt;();
  
      public ObservableCollection&lt;Person&gt; People
      {
          get { return _people; }
      }
  
      public MainWindow()
      {
          InitializeComponent();
  
          _people.Add(new Person() {Name = "Person1", Points = 10});
          _people.Add(new Person() {Name = "Person2", Points = 0});
          _people.Add(new Person() {Name = "Person3", Points = 40});
      }
  
      private void OnMouseTouchDown(object sender, InputEventArgs e)
      {
          var item = sender as Image;
          if (item == null) return;
  
          var draggedItem = item;
          var points = Convert.ToInt32(draggedItem.Tag);
          CreateDragDropWindow(draggedItem);
          System.Windows.DragDrop.DoDragDrop(draggedItem, points, DragDropEffects.Move);
      }
  
      private Window _dragdropWindow;
  
      private void CreateDragDropWindow(Visual dragElement)
      {
          _dragdropWindow = new Window
          {
              WindowStyle = WindowStyle.None,
              AllowsTransparency = true,
              AllowDrop = false,
              Background = null,
              IsHitTestVisible = false,
              SizeToContent = SizeToContent.WidthAndHeight,
              Topmost = true,
              ShowInTaskbar = false
          };
  
          Rectangle r = new Rectangle
          {
              Width = ((FrameworkElement) dragElement).ActualWidth/2,
              Height = ((FrameworkElement) dragElement).ActualHeight/2,
              Fill = new VisualBrush(dragElement)
          };
          _dragdropWindow.Content = r;
  
  
          Win32Point w32Mouse = new Win32Point();
          GetCursorPos(ref w32Mouse);
  
  
          _dragdropWindow.Left = w32Mouse.X;
          _dragdropWindow.Top = w32Mouse.Y;
          _dragdropWindow.Show();
      }
  
  
      [DllImport("user32.dll")]
      [return: MarshalAs(UnmanagedType.Bool)]
      internal static extern bool GetCursorPos(ref Win32Point pt);
  
      [StructLayout(LayoutKind.Sequential)]
      internal struct Win32Point
      {
          public Int32 X;
          public Int32 Y;
      };
  
      private void UIElement_OnPreviewGiveFeedback(object sender, GiveFeedbackEventArgs e)
      {
          Win32Point w32Mouse = new Win32Point();
          GetCursorPos(ref w32Mouse);
  
          _dragdropWindow.Left = w32Mouse.X;
          _dragdropWindow.Top = w32Mouse.Y;
      }
  
      private void UIElement_OnPreviewDrop(object sender, DragEventArgs e)
      {
          //var droppedData = e.Data.GetData(typeof(Image)) as Image;
          var droppedData = (Int32) e.Data.GetData(typeof (Int32));
          var stackPanel = sender as StackPanel;
          if (stackPanel != null)
          {
              var student = stackPanel.DataContext as Person;
  
              //int targetIndex = _people.IndexOf(student);
  
  
              if (student != null) student.Points += droppedData;
          }
          if (_dragdropWindow != null)
          {
              _dragdropWindow.Close();
              _dragdropWindow = null;
          }
      }
  }
  
  public class Person : INotifyPropertyChanged
  {
      private string _name;
      private int _points;
  
      public string Name
      {
          get { return _name; }
          set
          {
              if (value == _name) return;
              _name = value;
              OnPropertyChanged();
          }
      }
  
      public int Points
      {
          get { return _points; }
          set
          {
              if (value == _points) return;
              _points = value;
              if (_points &gt;= 100)
              {
                  _points -= 100;
                  Debug.WriteLine("100!");
              }
              OnPropertyChanged();
          }
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
          var handler = PropertyChanged;
          if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
      }
  }
  </code></pre>
  
  <p>I found over the internet that I can use class that extends Adorner and I found some examples:</p>
  
  <ul>
  <li><a href="http://nonocast.cn/adorner-in-wpf-part-5-drag-and-drop/" rel="nofollow noreferrer">http://nonocast.cn/adorner-in-wpf-part-5-drag-and-drop/</a> - (WaybackMachine archive <a href="https://web.archive.org/web/20131015000055/http://nonocast.cn/adorner-in-wpf-part-5-drag-and-drop/" rel="nofollow noreferrer" title="Wayback link">link</a>)</li>
  <li><a href="http://www.zagstudio.com/blog/488#.VfiMSBHtmko" rel="nofollow noreferrer">http://www.zagstudio.com/blog/488#.VfiMSBHtmko</a></li>
  <li><a href="http://www.infragistics.com/community/blogs/alex_fidanov/archive/2009/07/28/drag-amp-drop-with-datapresenter-family-controls.aspx" rel="nofollow noreferrer">http://www.infragistics.com/community/blogs/alex_fidanov/archive/2009/07/28/drag-amp-drop-with-datapresenter-family-controls.aspx</a></li>
  <li><a href="https://github.com/punker76/gong-wpf-dragdrop" rel="nofollow noreferrer">https://github.com/punker76/gong-wpf-dragdrop</a></li>
  </ul>
  
  <p>but all of them show how to drag items from collections (ItemsControls). Third link was promising, but I wasn't able to adopt it to my needs.</p>
  
  <p>So my questions are:</p>
  
  <ol>
  <li>How can I hide that small image window in my example when I cancel drag (MouseUp or incorrect drag target)</li>
  <li>Show I use Adorner and how can I use it in my code? I need to show it when I start drag and hide when I drop Image correctly or I cancel drag or drop target is incorrect</li>
  </ol>
  
  <p>I'm starting with WPF so please try to understand my frustration - I've spend last two evenings and night trying to get this working.</p>