Home > Silverlight > Drag and Drop in Silverlight

Drag and Drop in Silverlight

Let’s do some drag & drop of Items between listboxes. The same thing could be used for rearranging items in a control(say listbox).
we can even show what item is getting dragged around
you can see a demo here 

(Note: updated code if you drag and drop between listboxes it should be fine. Error checking is not there, it will blowup if you click in the empty space in the listbox and mouseup and down on a item without dragging, need to fix those issues)

In the sample, I am using 3 listboxes each having different Itemtemplates

for the HitTest to work the listboxes have to be given some Background otherwise HitTest wont work

we are going to use the same events MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove events
the example here is using all listboxes, so the code is going to refer to listboxes

In XAML we drop a PopUp control with a ContentControl as child and set the opacity to .5, just to give it some effect

We start the DragDrop when the mouseleftbuttondown event is raised, we do a hittest and see if it is a listbox, If so start DragDrop

we are assuming that all the listboxes will have ItemTemplates defined

void StartDragDrop(ListBox sender,MouseEventArgs e)
{
DataTemplate dt = sender.ItemTemplate as DataTemplate;
dragSource = sender;
popupContent.Content = sender.SelectedItem;
popupContent.ContentTemplate = dt;
popup1.CaptureMouse();
captured = true;
mouseVerticalPosition = e.GetPosition(null).Y;
mouseHorizontalPosition = e.GetPosition(null).X;
popup1.HorizontalOffset = mouseHorizontalPosition;
popup1.VerticalOffset = mouseVerticalPosition;
}

We are getting the Datatemplate of the listbox and SelectedItem of the listbox we are interested in and setting the content of the ContentControl in the PopUp to the selectedItem of the ListBox.
Set the ContentTemplate property of the ContentControl to this DataTemplate.
Make sure we capture the mouse
For positioning the popup we set the HorizontalOffset and VerticalOffset properties of the Popup Control we added in the XAML

when the mouse moves we are going to adjust the same properties(HorizontalOffset and VerticalOffset) of the Popup Control to reflect mouse movement

when the MouseLeftButtonUp is raised we do a hitTest again to see the Destination(listBox)

void Page_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
List elements = (List)this.HitTest(e.GetPosition(null));
for(int i=0;i<elements.Count;i++){
ListBox lb = elements[i] as ListBox;
if (lb != null){
(lb.ItemsSource as ObservableCollection).Add(popupContent.Content as Customer);
(dragSource.ItemsSource as ObservableCollection).Remove(popupContent.Content as Customer);
break;
}
}
captured = false;
popupContent.Content = null;
popupContent.ContentTemplate = null;
popup1.ReleaseMouseCapture();
mouseVerticalPosition = -1;
mouseHorizontalPosition = -1;}  

 


Add and remove Items as necessary and we have to make sure we set the Content and ContentTemplate properties of the ContentControl in the Popup to null, release the mousecapture

download the updated source here

Categories: Silverlight Tags: ,
  1. Ben Hayat
    April 12, 2008 at 2:14 am | #1

    In the demo, when I click on a list box in the white space area, I get a big error!

  2. lee
    April 12, 2008 at 2:51 am | #2

    Thanks, I noticed it after I posted the demo. As this demo doesn’t have any validations at all, it fails on the condition you mentioned as well as clicking (2 or 3 times) on the same listbox(it will remove the item and add it back again) will also throw an error.

  3. April 14, 2008 at 3:28 am | #3

    Thanks.

    I noticed it after I posted the demo. As this demo doesn’t have any validations at all, it fails on the condition you mentioned as well as clicking (2 or 3 times) on the same listbox(it will remove the item and add it back again) will also throw an error.

    Thanks for this post. Any plan to fix this error?

  4. lee
    April 14, 2008 at 9:12 am | #4

    yes, will update the post with the fix

  5. lee
    April 14, 2008 at 9:40 am | #5

    Updated the code, you should not see any errors that I found earlier.

  6. desopedr
    May 9, 2008 at 10:09 am | #6

    Hi,

    Thanks to share this useful code :)

    When I do a MouseLeftDown click on a listbox item and start to move it the popup is still empty, I never see the popup, but when I drop it in the second listbox it works fine.

    Do you have an idea why I can’t see my popup ?
    (IsOpened property is True)

    I have another problem with this solution. When I remove the XAML page (doc.xaml) where I have these listboxes and the popup from the MainPage.xaml (ContentZone.Children.Clear) and I click on my menu to add on more time the XAML page (doc.xaml) in my MainPage.xaml I get an exception :

    A first chance exception of type ‘System.Windows.Markup.XamlParseException’ occurred in System.Windows.dll
    Additional information: The name already exists in the tree: popupContent. [Line: 0 Position: 0]

    Your project throws the same error if you try the same context of a MainPage where you load Page or Page2, when you load the Page.xaml for the second time you get the error of popupConent.

    Thanks in advance if you can help.

    desopedr

  7. desopedr
    May 9, 2008 at 11:09 am | #7

    Hi,

    I’ve resolved my problem :

    Set the popup IsOpened property to false by default, set it to true before CaptureMouse

    dragDropPopup.IsOpen = true; // desopedr
    dragDropPopup.CaptureMouse();

    and set it to false after ReleaseMouseCapture

    dragDropPopup.ReleaseMouseCapture();
    dragDropPopup.IsOpen = false; // desopedr

    I think the problem was that the popup with the IsOpened property set to true is considered in use and is never removed from my application.

  8. lee
    May 9, 2008 at 12:11 pm | #8

    Glad, you figured it out

  9. Sush
    May 17, 2008 at 7:07 am | #9

    Hi, I am totally new to silverlight. Is it possible to run this application in .aspx page. I mean in asp.net web applications.

  10. lee
    May 17, 2008 at 10:10 pm | #10

    yes, you can do that

  11. Prashant
    June 24, 2008 at 4:17 am | #11

    Hi,

    Thanks for your valuable code that I have just downloaded but I am getting problem into it.

    While running I could see three listboxes but I cant drag-drop any of item from first listbox to second or third.

    I have also added breakpoint to ‘MouseButtonDown’ event but it seems that its not firing.

    Please let me know if I am doing anything wrong.

    Thanks & Regards

  12. lee
    June 24, 2008 at 7:49 am | #12

    I did not convert this to Beta2. this was a breaking change in beta2.

    the workaround is to put a canvas on top of listbox, as in the other sample I did convert
    http://leeontech.wordpress.com/2008/06/13/drag-drop-datagridrows/

  13. June 29, 2008 at 4:11 am | #13

    Why .hta?

  14. lee
    June 29, 2008 at 7:45 am | #14

    Michael,
    As I dont have my own website, I used to uplod the app to microsoft’s silverlight streaming. this is one of the options there. I thought this is the option which will let users see the app in fewer clicks

  15. October 17, 2008 at 4:33 pm | #15

    Hi Lee and others,

    The .hittest method has changed in the final release of Silverlight 2. Tried to fix it but no luck. Any help?

  16. Apurva
    October 28, 2008 at 8:43 am | #16
  17. littlesteps
    November 5, 2008 at 2:39 pm | #17

    Thanks for this code.

    I have just upgraded that code for compatibility issue with Silverlight 2:

    replace:
    List elements = (List)this.HitTest(e.GetPosition(null));
    for (int i = 0; i < elements.Count; i++)
    {
    ListBox lb = elements[i] as ListBox;

    with:
    IEnumerable elements = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), this);

    foreach (UIElement elem in elements)
    {
    ListBox lb = elem as ListBox;

    The “canvas on top of listbox” is really tricky… Aaargh, I would like to have “WPF Preview” events in Silverlight… it is a big hole.

    Any other idea to workaround this?

  18. lee
    November 5, 2008 at 3:26 pm | #18

    I am not sure if there are other/better ways. did not investigate further on this after the post

  19. Andreas
    February 19, 2009 at 12:09 pm | #19

    Very nice example! Would it also be possible to drop the ListBoxItem into a specific position in the TargetListbox – and moreover – indicate the drop position for the user during the drag (i.e. with a red line between the ListBoxItems in the TargetListbox?).
    Cheers,
    Andreas

    • lee
      February 19, 2009 at 3:38 pm | #20

      Hi Andreas,
      I will try to modify the sample and post an update

  20. Arif shareef
    June 24, 2009 at 8:18 am | #21

    when i run the App on my local machine ,
    it is throwing error ,by saying that page does not conatin definition for HitTest

    • lee
      June 24, 2009 at 8:52 am | #22

      Arif,
      HitTest was removed and we have to used this function
      VisualTreeHelper.FindElementsInHostCoordinates instead of HitTest

  21. July 30, 2009 at 7:25 am | #23

    Hi,
    I run this application and i have seen Three list box. Left top list box Filled by some city names. Then i draged in the Label and droped into to other (Right)List box. nothing happend.

    • lee
      July 30, 2009 at 8:30 am | #24

      This sample is quite old and might not be easy to get that up and running

  1. April 23, 2008 at 9:05 am | #1