This is a migrated thread and some comments may be shown as answers.

Drag/Drop within a ListBox

33 Answers 1041 Views
DragAndDrop
This is a migrated thread and some comments may be shown as answers.
GEB
Top achievements
Rank 1
GEB asked on 10 Feb 2009, 03:02 PM
Is there a simple example or a recommendation on how to drag/drop items within a ListBox, giving the user feedback as to where the dragged item will be dropped? This would allow the user to re-order items within the ListBox.

33 Answers, 1 is accepted

Sort by
0
Miroslav
Telerik team
answered on 16 Feb 2009, 11:53 AM
Hi Gary,

First, I assume you have calculated where the item should go (before/after the drop destination).

There are three ways in which the feedback can be given to the user:

1. (Easy) The DragCue can be changed to reflect the DropLocation, e.g. place a text saying "Drop after XXXX Item".

2. Modify the ControlTemplate of the ListBoxItem and add two drop feedback lines (that look like separators) to each item. Then add 2 additional states that show them and go to these states when in the DropQuery handlers.

3. Modify the ListBox template and add a separator there. Again it will be hidden and will be shown only when an item is being dropped. To move it around, just place it in a canvas. You can get access to a named element in the ControlTemplate by using FindName on the first visual child of the control.

Hopefully I will have time to create a simple example for this.

Sincerely yours,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
GEB
Top achievements
Rank 1
answered on 17 Feb 2009, 02:26 PM
Thanks.  I believe that for most of us, Option #3 is the most desireable.  I would hope that your sample will be something that many of your users would find helpful.
0
Aaron
Top achievements
Rank 1
answered on 01 Mar 2009, 01:35 AM
"First, I assume you have calculated where the item should go (before/after the drop destination)."

Could you give an example of how the calculation could be made, in particular how to translate e.Options.CurrentDragPoint into an item index in the destination list?

Thank you,
Aaron
0
Miroslav
Telerik team
answered on 02 Mar 2009, 12:45 PM
Hello Aaron & Gary,

It is always fun to push the boundaries of a control :).

Implementing drag-reorder is not quite so trivial, so I decided to actually create the example than try to go into explanations first. Here it is:



(the sample project is attached)

There are few interesting points:

  • The ListBoxItem's Parent is always null when bound, this is not very helpful :). Generally, all Telerik ItemsControls have the ItemContainerGenerator and a few Static methods that allow you to get the ItemsCotnrol of a container (or the container of an item for example). Since the ListBox does not have that I created an extension method that will always find the ItemsControl of a container.
  • The drag and drop is best to be a process of communication between a destination and a source. It should not matter what they are, the only thing they have in common is the DragDrop payload. This way it does not matter whether you drag items from/to listboxes or a grid or TreeView. Therefore the drag-arrange works when dragging items between ListBoxes as well.
  • Unlike other DragDrop implementations you do not have to inherit and extend the ListBox items and ListBox. It is a matter of applying a style and handling a 4 events. (which can be handled at a root or class level as well, quite handy)

The code can be improved a bit, but I should finally get to blogging things like this so I will clean it up there.

Your comments are welcome!

All the best,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
GEB
Top achievements
Rank 1
answered on 02 Mar 2009, 07:40 PM
Miroslav , thank you very much for this example.  I have not studied the code yet, but I have run your sample, at it looks like exactly what I needed.  And, I believe that several others will find this example very helpful.
0
Aaron
Top achievements
Rank 1
answered on 02 Mar 2009, 10:25 PM
Hi Miroslav,

This was exactly what we were looking for and very helpful! Interestingly, the listboxes don't seem to fire drag/drop events if they're empty. If I empty the second list and drag an item to it, it does not show up that dragging is allowed. Other that, it works beautifully.

Thank you :)
Aaron
0
GEB
Top achievements
Rank 1
answered on 03 Mar 2009, 07:55 AM
Miroslav, I have been working with the example that you provided.  Thanks again for putting it together.  I have a follow up question.  For one of my tests, I constructed a listbox that has a checkbox, followed by text.  It was exactly like your example, except each item has a checkbox and text.  The DataTemplate is a StackPanel, and the data is loaded in the listbox via binding (just as with your example).  However, when I attempt to check the checkbox of an item in the ListBox, it thinks I want to drag the listitem.  Using your example, how can I tell if the user is attempting to check the checkbox versus dragging the object?  When I look at the drag events received, I could not find a way to determine if the object was the checkbox or the item's text.
0
Miroslav
Telerik team
answered on 03 Mar 2009, 12:39 PM
Hello Aaron & Gary,

Thanks for the feedback!

Yes, I missed the case of the empty ListBox, but that is just a matter of making it a drop target and checking for it in the DropQuery event, I added that to the ListBox Style and changed the handler so that it will check for this case.

The tricky bit here is where to place the black visual cue because there is no easy way to get the last item container of the ListBox. (Again, this is not a problem with Telerik ItemsControls :)).

Then the issue with the CheckBox is because of mouse capturing. When a control captures the mouse, all mouse events will go through it an no other controls will receive mouse events. All button controls capture the mouse on mouse down, so after the mouse is pressed, the drag&drop will not receive mouse up events and therefore mouse movement will be considered a drag.

We used to capture the mouse during drag/drop just to guard against that case but then this was removed because controls (like ListBoxItem) needed mouse events to properly update their visual states.

There isn't really a way to check for mouse capturing unless you try to capture the mouse and do not succeed:

var sourceControl = e.Options.Source;  
if (!sourceControl.CaptureMouse())  
{  
    e.QueryResult = false;  
    e.Handled = true;  
    return;  
}  
else  
{  
    sourceControl.ReleaseMouseCapture();  

With the above code CheckBoxes function as expected.

The above check will be included in the next release of the controls, surely you do not need to deal with MouseCapturing issues :).

Note that I used two different item templates for a similar visual result but different behavior:

<ListBox.ItemTemplate> 
    <DataTemplate> 
        <Grid> 
            <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Name}"/>  
        </Grid> 
    </DataTemplate> 
</ListBox.ItemTemplate> 

and:

<ListBox.ItemTemplate> 
    <DataTemplate> 
        <StackPanel Orientation="Horizontal">  
            <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" /> 
            <TextBlock Text="{Binding Name}" /> 
        </StackPanel> 
    </DataTemplate> 
</ListBox.ItemTemplate> 

I will update the example with the Q1 release as well, once it is out.

Sincerely yours,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
GEB
Top achievements
Rank 1
answered on 03 Mar 2009, 07:40 PM
The check for mouse capture seems to work great.  Thanks for the quick response!
0
Aaron
Top achievements
Rank 1
answered on 03 Mar 2009, 10:18 PM
Works great! Thank you, Miroslav for your quick and thorough responses.
0
anwar
Top achievements
Rank 1
answered on 06 Jul 2009, 07:17 PM
Hi Miroslav,

Thanks for the sample.

My listbox data template contains three textblocks, i would like to add column headers for each textblock,  Can you please help me how to add the column headers templates in the Drag/Drop listbox control.

Thanks,
Anwar
0
Miroslav
Telerik team
answered on 09 Jul 2009, 12:57 PM
Hi Anwar,

It seems that you need something like a ListView or GridView. Unfortunately I cannot think of an easy way to add column headers to the ListBox.

I would suggest using a GridView for this purpose.

On a side note if you are just after the visual effect, you can always add some elements that will look like column headers above the ListBox.

Greetings,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Randall Nelson
Top achievements
Rank 1
answered on 09 Jul 2009, 06:53 PM
Hello.  After updating to the Q2 release (from July 1st) this drag drop example no longer works if it is embedded in a RadWindow - it used to.  Help! My application used this sample code almost verbatim as a way to organize two lists of items - but the DropQuery does not seem to be firing (when in a RadWindow).

To reproduce this issue make the following changes to the sample project:
- In the XAML, place these lines before the line that begins with <Grid x:Name="LayoutRoot" and after the </UserControl.Resources> line:
   
    <Canvas x:Name="cvMain" Background="AntiqueWhite">  
        <telerikNavigation:RadWindow x:Name="rwTest" Width="500" Height="550" Header="Organize Columns" 
                                     ResizeMode="NoResize">  
 


-  And place these lines after the </Grid> line:
   

        </telerikNavigation:RadWindow> 
        <Button x:Name="btnShow" Canvas.Top="10" Canvas.Left="10" Content="Show" Click="btnShow_Click" /> 
    </Canvas> 
 

- In the CS file add these lines:

        private void btnShow_Click(object sender, RoutedEventArgs e)  
        {  
            rwTest.ShowDialog();  
        }  
 

 

 

 

You'll need to add a reference to Telerik.Windows.Control.Navigation and you'll need to add the following to the top of the XAML:
   

        xmlns:telerikNavigation="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" 
 

 

 

 

 

0
Miroslav
Telerik team
answered on 10 Jul 2009, 12:22 PM
Hello Randall Nelson,

Thank you for identifying this issue. The RadWindow is not registering itself as a visual root for the DragDrop. This should happen automatically and currently it is a bug.

I have updated your Telerik Points for the feedback.

The workaround is to add all open windows as visual roots during the OnDragQuery. You can do this at the root of the application like so:

public Page()  
{  
    InitializeComponent();  
 
    this.AddHandler(RadDragAndDropManager.DragQueryEvent,   
        new EventHandler<DragDropQueryEventArgs>(OnDragQuery), true);  
}  
 
private void OnDragQuery(object sender, DragDropQueryEventArgs e)  
{  
    //Addd all open windows, here I just add one:  
    e.Options.ParticipatingVisualRoots.Add(myWindow);  

I am sorry that we have introduced this issue, it will be fixed for the next Internal build of the controls. Then you will be able to remove the workaround.

Best wishes,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Randall Nelson
Top achievements
Rank 1
answered on 10 Jul 2009, 06:44 PM
Thanks for the workaround - this seems to do the trick.  The drag/drop is a little bit more choppy, but it works.  Thanks again.
0
matt pannella
Top achievements
Rank 1
answered on 13 Oct 2009, 06:36 PM
Miroslav, could you post the example of how you changed your sample code to allow drops into the empty list box?
0
Miroslav
Telerik team
answered on 19 Oct 2009, 09:50 AM
Hello matt,

Yes, surely.

I am Attaching the altered example.

Regards,
Miroslav
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Drammy
Top achievements
Rank 1
answered on 23 Apr 2010, 01:33 PM
In SIlverlight 4 there is no FindItemsConrolParent on System.Windows.FrameworkElement.

How should this example work in Silverlight 4?



EDIT: please ignore my post.  I didn't spot the ControlExtension and assumed this was replaced with the new VisualTreeHelper kind of stuff...
0
Droidilate
Top achievements
Rank 1
answered on 09 Nov 2010, 12:46 AM
I read through the second code example and wowsers, it sure seems awfully tedious.  I played with the Silverlight 4 toolkit from Codeplex and it handles this automatically (though I wouldn't say it's flawless).

Is this still the best method for doing "same list" drag and drop reordering?

Thanks
0
neo e
Top achievements
Rank 1
answered on 09 Nov 2010, 03:51 AM
does it show the drop cue well where? I mean between the items.

thx

kevin
0
Droidilate
Top achievements
Rank 1
answered on 10 Nov 2010, 12:09 AM
Yes it does
0
Alan
Top achievements
Rank 2
answered on 25 Feb 2011, 09:49 PM
Miroslav,

Would you mind plesae showing how you can drag & drop multiple items at the same time? Perhaps using CTRL or SHIFT to select multiple items and then dragging and dropping them all at once?

Thanks!
0
Tsvyatko
Telerik team
answered on 01 Mar 2011, 10:50 AM
Hello Alan,

You might want to check this thread and the project attached there. Let me know if you have any further questions.

All the best,
Tsvyatko
the Telerik team
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
Alex Olenev
Top achievements
Rank 1
answered on 28 Mar 2011, 12:20 PM
This example not works in ChildWindow. Please help.
Thanks. Already find answer on this question.
0
Andy
Top achievements
Rank 1
answered on 05 Nov 2011, 04:51 PM
We just bought the Telerik controls and I have downloaded the latest version. (Oct 25, 2011)
My question is about dragging and dropping between listboxes and reordering them. The latest demo doesn't have any codes related to dragging and inserting at desired location.

Then I downloaded the
  • listboxdragreorder.zip  dated April 2009 mentioned above in this thread. That is what I exactly need. But the demo doesn't work when I try to compile with latest version of telerik silverlight assembly ( too many compliation errors).
  • Can someone point me to right direction with some running codes.
    Again, my problem is - How can I reorder in same List box + drop to different ListBox at desired location (not at the end).

    I apologize if I am not using the right thread...

    Thanks & regards,
    Andy Singh

     
    0
    Vlad
    Telerik team
    answered on 07 Nov 2011, 08:19 AM
    Hello Andy,

     I suggest you to check our official demo for more info:
    http://demos.telerik.com/silverlight/#DragAndDrop/TreeToGrid

    Regards,
    Vlad
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

    0
    Andy
    Top achievements
    Rank 1
    answered on 07 Nov 2011, 02:02 PM

    Hello Telerik team,
    Thanks for the reply. I have already looked at this example but it doesn't reorder the listBox item. It has a treeview, Grid, and a list box.

    • When we try to Drag and drop  listBoxitems in between List Box, it just remove from the dragged location and adds at the end.
    • When we drag from Treeview or Grid into ListBox, again it addes at the end not at dropped location. Following is the line of code that I got from the source code of the link you sent me.
      •  

         

        foreach (object draggedItem in draggedItems)

         

        {

        items.Add(draggedItem);  -- It insert at the end

        }

      • The old zip file works great (2009). It insert at the dropped location having following codes.

      •    

         

         

        var operation = e.Options.Payload as DragDropOperation;

         

         

        var insertIndex = operation.DropPosition == DropPosition.Before ? destinationIndex : destinationIndex + 1;

         

        itemsSource.Insert(insertIndex, operation.Payload);

      • I am not able to convert this  codes with new assembly. Please help asap as I have demo in a day or two.

    Thanks & regards,
    Andy Singh

    0
    Andy
    Top achievements
    Rank 1
    answered on 14 Nov 2011, 08:00 PM
    Hello Sir,
    I am just curious to know if you get a chance to work on List box drag & drop reordering. Do you think I need to open support ticket for this. I will really appreciate if you guide me to solve this reordering problem.

    Thanks & regards,
    Andy Singh
    0
    Tsvyatko
    Telerik team
    answered on 16 Nov 2011, 10:21 AM
    Hi Andy,

     I have prepared sample project (SilverlightApplication8) that demonstrate how you can achieve this out of the box using our build in behavior. (Please, note that you need to use one of our recent LIBs to work). More information about drag behaviors can be found here

    However, if you need more custom solution, I have modified the initial project to fit the latest version (SL4 and Q2 SP1 telerik binaries). Please, find the attached project - SilverlightApplication9.

    Let us know if you have any further questions or issues.

    Kind regards,
    Tsvyatko
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

    0
    Andy
    Top achievements
    Rank 1
    answered on 17 Nov 2011, 10:25 PM
    Hello,
    Thanks for the zip file. They works fine with Q2 assemblies. The only thing is that they still use Style Resource "DraggableListBoxStyle" that I don' want to use.

    I have put together a small applicatioin with Q2 dll and Drag/Drop events codes from one of your latest Example.cs files. I will appreciate if you fix my problem on this Application. Please search for the word "Problem"  in the project and here I am not able to get the Index of dropped location. You may just have to change 2 or 3 lines of code.

    I will really appreciate if you please make necessary changes so that I can
    •  Drop from one list box into other at desired location.
    • Reorder the individual List box.

    How can I send this project to you. I am not able to upload it. Only image files are enabled..
    BTW here is the .DropInfo Event where I want the fix.

     

     

     

    private void DropInfo(object sender, DragDropEventArgs e)

     

    {

    System.Windows.Controls.

     

    ItemsControl wishlist = e.Options.Destination as System.Windows.Controls.ItemsControl;

     

     

     

    ICollection draggedItems = e.Options.Payload as ICollection;

     

     

     

    // Get the drag cu that the TreeView or we have created

     

     

     

     

     

     

    TreeViewDragCue cue = e.Options.DragCue

     

    as TreeViewDragCue;

     

     

     

    if (e.Options.Status == DragStatus.DropPossible)

     

    {

     

     

    // Set a suitable text:

     

     

     

     

     

     

    cue.DragActionContent =

     

    String.Format("Add {0} item{1} to Wishlist", draggedItems.Count, draggedItems.Count > 1 ? "s" : String.Empty);

     

    cue.IsDropPossible =

     

    true;

     

     

     

     

    // wishlist.Background = this.Resources["BasicBrush"] as Brush;

     

     

     

     

     

     

    }

     

     

    else if (e.Options.Status == DragStatus.DropImpossible)

     

    {

    cue.DragActionContent =

     

    null;

     

    cue.IsDropPossible =

     

    false;

     

    }

     

     

    else if (e.Options.Status == DragStatus.DropComplete && e.Options.Destination is ListBox)

     

    {

     

    System.Windows.Controls.

     

    ListBox listBoxSender = sender as System.Windows.Controls.ListBox;

     

     

     

     

    IList items = wishlist.ItemsSource as IList;

     

     

     

    IList<MachineScheduleViewModel> itemsSource = wishlist.ItemsSource as IList<MachineScheduleViewModel>;

     

     

     

    foreach (object draggedItem in draggedItems)

     

    {

     

     

     

    //Problem

     

     

     

     

     

     

     

     

    var destinationIndex = 2;// itemsSource.IndexOf((MachineScheduleViewModel)wishlist.DataContext);

     

     

     

     

     

     

     

     

    var operation = draggedItem as DragDropOperation;

     

     

     

    // var operation = e.Options.Payload as DragDropOperation;

     

     

     

     

     

     

     

     

     

    //Problem here ****************************************************************************

     

     

     

     

     

     

     

     

     

    // How can I get the actual insert Index... I have hard coded index = 2 and the dragged items are

     

     

     

     

     

     

     

     

    // getting inserted there at idex 2.

     

     

     

     

     

     

     

     

    var insertIndex =0;

     

     

     

    if(itemsSource.Count > 2)

     

    insertIndex = 2;

     

    // operation.DropPosition == DropPosition.Before ? destinationIndex : destinationIndex + 1;

     

     

     

     

     

     

     

    else

     

     

     

     

     

    insertIndex = itemsSource.Count;

     

     

     

    // Please fix this so that I can get the actual index ****************

     

     

     

     

     

     

     

     

    itemsSource.Insert(insertIndex, (

     

    MachineScheduleViewModel)draggedItem);

     

     

     

    ListBox listBox = (ListBox)wishlist;

     

    listBox.Dispatcher.BeginInvoke(() =>

    {

    listBox.SelectedIndex = insertIndex;

    });

     

     

     

    // items.Add(draggedItem); //original

     

     

     

     

     

     

    }

    }

     

     

    if (e.Options.Status != DragStatus.DropPossible)

     

    {

    wishlist.Background =

     

    new SolidColorBrush(Colors.White);

     

    }

    }


    0
    Tsvyatko
    Telerik team
    answered on 18 Nov 2011, 11:06 AM
    Hi Andy,

     You can attach project by opening support ticket. I encourage you to do so. that way we will be able to update it and provide solution in the specific case. Also, keep in mind that support tickets response time is shorter, so you will be able to receive response faster.

    All the best,
    Tsvyatko
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

    0
    Trang
    Top achievements
    Rank 1
    answered on 12 Jul 2012, 05:24 PM
    I have this latest version but the autoscrolling does not work.  Please advise.

    Trang
    0
    NRT
    Top achievements
    Rank 1
    answered on 31 Jan 2013, 01:43 PM
    Hello , 
    Can I get an example where I can reorder/drag drop items WITHIN the SAME listbox which has vertically alligned items.
    I want a seperator also to indicate that we can drop the item in that position. 
     Please find the attachment. 
    Tags
    DragAndDrop
    Asked by
    GEB
    Top achievements
    Rank 1
    Answers by
    Miroslav
    Telerik team
    GEB
    Top achievements
    Rank 1
    Aaron
    Top achievements
    Rank 1
    anwar
    Top achievements
    Rank 1
    Randall Nelson
    Top achievements
    Rank 1
    matt pannella
    Top achievements
    Rank 1
    Drammy
    Top achievements
    Rank 1
    Droidilate
    Top achievements
    Rank 1
    neo e
    Top achievements
    Rank 1
    Alan
    Top achievements
    Rank 2
    Tsvyatko
    Telerik team
    Alex Olenev
    Top achievements
    Rank 1
    Andy
    Top achievements
    Rank 1
    Vlad
    Telerik team
    Trang
    Top achievements
    Rank 1
    NRT
    Top achievements
    Rank 1
    Share this question
    or