Drag Drop using Listboxes – Part 2
In this post I will demo on how one can create a more advanced Drag Drop for ListBoxes than the one I posted earlier here.
Basically what we will do in this post is to create an Adorner for the ListBoxItem being dragged.We will have to create our own Adorner in order to show the ListBoxItem being dragged and then add that Adorner instance to the Parent control that is holding both the “source”ListBox and the “destination” ListBox. I got most of the code for this from here.
So let us start by creating the Adorner class. What we want is to display the ListBoxItem in the Adorner layer of the parent control yet we cannot just use the ListBoxItem from the original listbox because a UI Element can only belong to a single Visual Tree. So what we will do is Clone the ListBoxItem. This is very easy since a ListBoxItem is nothing more than a Content Control, so we can copy the Content and also use it’s ContentTemplate to create a Clone.
As you can see this helper method is doing nothing more that create a new ContentControl and setting the Content property and the ContentTemplate property from the Element that is passed and that is our Clone of the Item Selected.
Usually when using Adorner you would go ahead and do your own drawing yet in our case we are going to create a Content control and display it so we must make sure that the Layout system knows about this control. In order to do this we have to override 2 methods the MeasureOverride and the ArrangeOverride like this
Where elementToShow is just a reference to the ContentControl that we have created by using the CreateClone method.
Now we need to override another 2 methods so that WPF can get the elementToShow and render it.
Ok so by now we already have something showing up on screen. Yet right now the elementToShow is being displayed at a relative position to the AdornedElement. We would want the elementToShow to move around while dragging just like in Windows Explorer when you drag a file. So lets create a method that we can call from outside and pass the new coordinates to the Adorner.
Ok, so the UpdatePosition is just a method that one can call from outside the Adorner to update the position for the element. There is another method in the above code, GetDesiredTransform. We need to override this method in order to ask WPF to render our elementToShow at the point that is specified to us by the UpdatePosition method . All we need to do is create a TranslateTransform and specify the new coordinates. Without the TranslateTransform the elementToShow would be rendered relative to the Adornered element.
Ok and that is all for our Adorner, now lets have a look on how we can use it…
As explained in Part 1 of this post we need to handle the PreviewMouseLeftButtonDown of the “source” ListBox in order to grab the item to be dragged over to the “destination”ListBox. This time we will also create an instance of the adorner class we just built and add it to the AdornerLayer of the control that is parent to both the “source” ListBox and the “destination” Listbox.
Now that we have added the Adorner to the AdornerLayer, we only need to ask out beloved Adorner to update the position so that the elementToShow in the Adorner would move around accordingly. We will do this by handling the DragOver event of both the “source” and the “destination” ListBoxes
All other code is just like the Part 1 code that I have explained. The only differnce is that now we also have to remove the Adorner from the Adorner Layer once the item is Dropped on the “destination” ListBox(or even if it is dropped on the “source” ListBox since that would be like a cancel for us).