none
Drag and Drop from a ListControl to Canvas

    Question

  •  How can i add a drag and drop from a list control to stage ( canvas)? I have one ListControl listing names of 10 user controls, i want that the user can select and drag the name of a control from list and drop it on Canvas.I would be better if i can use proxy image as well for drag and drop operation just like Flex.

     

    Wednesday, July 09, 2008 1:24 AM

Answers

  • Hello, by ListControl, do you mean ListBox? The problem is: You can't handle ListBoxItem.MouseLeftButtonDown event because it's already handled by ListBox and marked as handled. But if after the ListBoxItem is dropped on the Canvas, you don't need to drag it anymore, you can handle the ListBox's SelectionChanged event. Suppose you have something like this:

     <Canvas x:Name="LayoutRoot" Background="White">
    <ListBox x:Name="lb" Width="100" Height="200" SelectionChanged="lb_SelectionChanged">
    <ListBoxItem Width="100" Content="a"/>
    <ListBoxItem Width="100" Content="b"/>
    <ListBoxItem Width="100" Content="c"/>
    </ListBox>
    </Canvas>

     

    In the UserControl.Loaded event handler, you create a TranslateTransfrom and the necessary event handlers for each item:

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
    foreach (ListBoxItem item in lb.Items)
    {
    item.RenderTransform = new TranslateTransform();
    item.MouseLeftButtonUp += new MouseButtonEventHandler(item_MouseLeftButtonUp);
    item.MouseMove += new MouseEventHandler(item_MouseMove);
    }
    }

     

    You need two support variables:

    private Point? previousPosition;
    private bool isDragging;

     

    In SelectionChanged event handler, you capture the mouse on the selected item, use TransformToVisual method to get the offset of this item to the root Canvas, which is a MatrixTransform, and set the matrix's OffsetX/Y to previousPosition. You also need to remove the ListBoxItem from the ListBox and add it directly as a child of the Canvas, so it can be dragged outside the ListBox.

    private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    ListBoxItem item = (ListBoxItem)lb.SelectedItem;
    item.CaptureMouse();
    MatrixTransform mt = (MatrixTransform)item.TransformToVisual(LayoutRoot);
    previousPosition = new Point(mt.Matrix.OffsetX, mt.Matrix.OffsetY);
    isDragging = true;
    lb.Items.Remove(item);
    LayoutRoot.Children.Add(item);
    }

     

    In MouseMove, you check the current position, minus the previous position, update the TranslateTransform with the delta, and update the previous position.

    void item_MouseMove(object sender, MouseEventArgs e)
    {
    if (isDragging)
    {
    ListBoxItem item = (ListBoxItem)sender;
    TranslateTransform transform = (TranslateTransform)item.RenderTransform;
    Point currentPosition = e.GetPosition(LayoutRoot);
    transform.X += currentPosition.X - previousPosition.Value.X;
    transform.Y += currentPosition.Y - previousPosition.Value.Y;
    previousPosition = currentPosition;
    }
    }

     

    Finally, in MouseLeftButtonUp, you release the mouse capture, and stop dragging.

    void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
    ListBoxItem item = (ListBoxItem)sender;
    item.ReleaseMouseCapture();
    isDragging = false;
    }

     

    One thing to note is: It's better to use TranslateTransform rather than Canvas.Left/Top in drag and drop scenarios, because TranslateTransform supports any layout panels.

    Friday, July 11, 2008 1:27 AM

All replies

  • Wednesday, July 09, 2008 1:36 AM
  •  Thanks Hitesh

     But i could not figure our how the example you refered can help me, Do anyone have seen the drag and drop support of Flex? you can drag an item from a list control to a data Grid or List control?

    My question is, can SL do the same thing ? if yes how can i do that. 

    Wednesday, July 09, 2008 4:51 AM
  • Hello, by ListControl, do you mean ListBox? The problem is: You can't handle ListBoxItem.MouseLeftButtonDown event because it's already handled by ListBox and marked as handled. But if after the ListBoxItem is dropped on the Canvas, you don't need to drag it anymore, you can handle the ListBox's SelectionChanged event. Suppose you have something like this:

     <Canvas x:Name="LayoutRoot" Background="White">
    <ListBox x:Name="lb" Width="100" Height="200" SelectionChanged="lb_SelectionChanged">
    <ListBoxItem Width="100" Content="a"/>
    <ListBoxItem Width="100" Content="b"/>
    <ListBoxItem Width="100" Content="c"/>
    </ListBox>
    </Canvas>

     

    In the UserControl.Loaded event handler, you create a TranslateTransfrom and the necessary event handlers for each item:

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
    foreach (ListBoxItem item in lb.Items)
    {
    item.RenderTransform = new TranslateTransform();
    item.MouseLeftButtonUp += new MouseButtonEventHandler(item_MouseLeftButtonUp);
    item.MouseMove += new MouseEventHandler(item_MouseMove);
    }
    }

     

    You need two support variables:

    private Point? previousPosition;
    private bool isDragging;

     

    In SelectionChanged event handler, you capture the mouse on the selected item, use TransformToVisual method to get the offset of this item to the root Canvas, which is a MatrixTransform, and set the matrix's OffsetX/Y to previousPosition. You also need to remove the ListBoxItem from the ListBox and add it directly as a child of the Canvas, so it can be dragged outside the ListBox.

    private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    ListBoxItem item = (ListBoxItem)lb.SelectedItem;
    item.CaptureMouse();
    MatrixTransform mt = (MatrixTransform)item.TransformToVisual(LayoutRoot);
    previousPosition = new Point(mt.Matrix.OffsetX, mt.Matrix.OffsetY);
    isDragging = true;
    lb.Items.Remove(item);
    LayoutRoot.Children.Add(item);
    }

     

    In MouseMove, you check the current position, minus the previous position, update the TranslateTransform with the delta, and update the previous position.

    void item_MouseMove(object sender, MouseEventArgs e)
    {
    if (isDragging)
    {
    ListBoxItem item = (ListBoxItem)sender;
    TranslateTransform transform = (TranslateTransform)item.RenderTransform;
    Point currentPosition = e.GetPosition(LayoutRoot);
    transform.X += currentPosition.X - previousPosition.Value.X;
    transform.Y += currentPosition.Y - previousPosition.Value.Y;
    previousPosition = currentPosition;
    }
    }

     

    Finally, in MouseLeftButtonUp, you release the mouse capture, and stop dragging.

    void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
    ListBoxItem item = (ListBoxItem)sender;
    item.ReleaseMouseCapture();
    isDragging = false;
    }

     

    One thing to note is: It's better to use TranslateTransform rather than Canvas.Left/Top in drag and drop scenarios, because TranslateTransform supports any layout panels.

    Friday, July 11, 2008 1:27 AM
  • Thank you very much for your detailed response

     I will try this code today, i have a feeling that it will work :)

     

    Friday, July 11, 2008 1:47 AM
  •  I tried the code you sent, Its working

    You are great, You are a super star :) 

     Thanks Alot

     

    Monday, July 14, 2008 2:20 AM
  • Hi

    I am trying to do the same in SL 2 and when i drag the item and drop it in layoutroot which is the canvas in which the listbox is placed, i am not able to see the content of the item in the canvas.

    My intention here is to drag an item from one list box and drop it in to another listbox. Both the listboxes should be in the same canvas. After dropping the item to the second listbox, the item should still persist in the first listbox.

    Please let me know if we could implement this.

    Thanks


     

    Wednesday, October 29, 2008 4:42 PM
  • Hi, Thank you for this code part, Can you please tell me how can i do drag and drop from One list box to another,and viceversa Thank you
    Wednesday, December 03, 2008 5:25 AM
  •  Hello Everybody, 

    I am doing the Dragging and Dropping of items in the 3 different ListBoxes. I have made some code but having problem in finding the Children of Listbox(ListBoxItems) on the UserControl_Loaded Event and also ListBoxItem class is not raising the MouseLeftButtonDown event.

    Could you please tell me about me the detailed solution for dragging and dropping between the ListBoxes control ?

     Thanks in advance

     

     

    Sunday, May 17, 2009 2:35 PM
  • is it possible to drag something from the outside of SL application.

    For Ex: Like Microsoft outlook if we drag attachments onto it , it will attach them automatically.

    Like this functionality, can we achieve in SL.

    Thanks in Advance...

    Tuesday, June 09, 2009 7:25 AM
  • is it possible to drag something from the outside of SL application.

    No, for Silverlight 1, 2, and 3, because it lives in a Sandbox which is like a sealed well, or a box of sand that you cannot take out or add any sand.

    Monday, July 27, 2009 1:49 PM
  •  Ok, Thanks, But what is Sandbox

    Thursday, July 30, 2009 10:48 AM
  • hi mmanzoor,

     is it possible that you can share the code that you received, it is a bit interesting? I am working on a project that supposed to copy image files in listbox to canvas via drag and drop. So far, I can't find any good example.

    Thanks,


    Rudy

    Monday, November 30, 2009 1:30 AM
  • is it possible to drag something from the outside of SL application.

    Anil, you can do this very easily in Silverlight 4. Silverlight 4 Beta 1 has this functionality & using that you can load any external files dropped into your application.

    Have a look into my latest blog post which also has a sample demo application: http://kunal2383.blogspot.com/2009/11/silverlight-4-how-to-drag-and-drop.html

    Wednesday, December 02, 2009 12:00 PM
  • Ridvan, have a look into my updated post in my blog. Hope this will now give you better visibility...
    Wednesday, December 02, 2009 12:09 PM
  • Hi Kunal,Your update was awesome, now, I can be able to clone images, rather than moving them onto the Canvas. I hope I can be able to integrate into my project. Since all my images created in XAML, I am not sure how successful I can be. I'll post.Regards,
    Ridvan

     

    Wednesday, December 02, 2009 4:04 PM
  • Look into the comment. That's also easy enough. You have to set the AllowDrag="True".
    Wednesday, December 02, 2009 10:43 PM
  • Hi Kunal,Thanks for posting wonderful help on your blog.I followed your idea of placing icons in the ListBox during the run time and I clean up the XAML partition of my project. SnipedPopulateHPServerListBox();RadDragAndDropManager.AddDragInfoHandler(HPServer, OnDragInfo);RadDragAndDropManager.AddDragQueryHandler(HPServer, OnDragQuery);RadDragAndDropManager.AddDropInfoHandler(DropArea, OnDropInfo);RadDragAndDropManager.AddDropQueryHandler(DropArea, OnDropQuery);RadDragAndDropManager.SetAllowDrop(DropArea, true); // HP Server ListBox will populate on Run Timeprivate void PopulateHPServerListBox(){      Image dragableHPServerLH3000R = new Image()      {Source = new BitmapImage(new Uri("Images/hp_server/NetServerLH3000R.png ", UriKind.RelativeOrAbsolute))       }; RadDragAndDropManager.SetAllowDrag(dragableHPServerLH3000R, true);HPServer.Items.Add(dragableHPServerLH3000R);HPServer.Items.Add("HP NetServer LH3000R"); }Full project located at http://cid-89e24e31b10a0ed6.skydrive.live.com/self.aspx/.Public/VisualLanSL4Beta12-3-09.rarFor next step, I would like to know if there is a way to clean the Canvas if I would like to start Drag Drop new images from beginning. Like DOS’ CLR command. For second, I start looking into your other project “SL4RightClickContextMenuDemo” program. I would like to know if I can be able to attach that functionality to above code so I can be able to right click on each icon that I placed on the Canvas. By enabling right click on each icon, I can be able to select the option to enter a command (in this case “Enter an IP Address”).

    Regards,

     

    Ridvan Aktas

    Thursday, December 03, 2009 12:25 AM
  • The first query: Yes, you can clear the canvas using myCanvas.Children.Clear();

    The second query:  Yes, you can also enable the right click behavior in your images to ask the user to enter IP address. Here follow the article & the next implementation logic is yours...

    Thursday, December 03, 2009 7:51 AM
  • Hello Yi,

    Your code works fine for drag and drop from Listbox to canvas but i have some further requirements.

    After dropping images on canvas from listbox i want to make those images movable within canvas. i mean images can be drag and drop within canvas also. how can i achieve this functionality?

    I have tried to register that image all mouse events after dropping on canvas but i could not achieve what i want.

    Thanks

    Ashish

    Friday, December 03, 2010 12:08 AM
  • I have just copy your code to the VS2010 and tried to run it.But when I dragged the item in the left listbox and moved it to the right listbox .The item I dragged simply disappeared and was not added to the right listbox.What's the problem?Can you help me ? 

    Friday, July 27, 2012 9:36 PM