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

Drag & Drop example

7 Answers 575 Views
ListView
This is a migrated thread and some comments may be shown as answers.
tom
Top achievements
Rank 1
tom asked on 16 Aug 2011, 10:41 AM
Hi,

I can't find an example for the RadListView and Drag & Drop items for reordering.
I am also missing some visual aids during the drop event like in the GridViews Row Drag&Drop example.

Regards,
Tom

7 Answers, 1 is accepted

Sort by
0
Ivan Todorov
Telerik team
answered on 17 Aug 2011, 03:01 PM
Hello Tom,

Thank you for writing.

Currently, RadListView does not support drag & drop row reorder out of the box. You can implement it by using the standard Windows Forms drag and drop mechanism as it is demonstrated below:
public partial class Form2 : Form
{
    Point? lastMouseDownLocation;
 
    public Form2()
    {
        InitializeComponent();
 
        radListView1.AllowDrop = true;
        radListView1.MouseDown += new MouseEventHandler(radListView1_MouseDown);
        radListView1.MouseMove += new MouseEventHandler(radListView1_MouseMove);
        radListView1.DragDrop += new DragEventHandler(radListView1_DragDrop);
        radListView1.DragEnter += new DragEventHandler(radListView1_DragEnter);
        radListView1.MultiSelect = true;
    }
 
    void radListView1_DragEnter(object sender, DragEventArgs e)
    {
        e.Effect = DragDropEffects.Move;
    }
 
    void radListView1_DragDrop(object sender, DragEventArgs e)
    {
        IDataObject dataObject = e.Data;
        if (dataObject != null)
        {
            List<ListViewDataItem> selectedItems = dataObject.GetData(typeof(List<ListViewDataItem>)) as List<ListViewDataItem>;
            if (selectedItems != null)
            {
                for (int i = 0; i < selectedItems.Count; i++)
                {
                    ListViewDataItem item = selectedItems[i];
                       
                    radListView1.Items.Remove(item);
 
                    BaseListViewVisualItem it = radListView1.ElementTree.GetElementAtPoint(radListView1.ListViewElement.PointFromScreen(new Point(e.X, e.Y))) as BaseListViewVisualItem;
                    if (it != null)
                    {
                        int indexToMoveTo = radListView1.Items.IndexOf(it.Data);
                        Insert(radListView1, indexToMoveTo, item);
 
                    }
                    else
                    {
                        radListView1.Items.Add(item);
                    }
                }
            }
            dataObject = null;
        }
    }
 
    private void Insert(RadListView listViewDrop, int indexToMoveTo, ListViewDataItem item)
    {
        Stack<ListViewDataItem> movedItems = new Stack<ListViewDataItem>();
 
        while (listViewDrop.Items.Count > indexToMoveTo)
        {
            movedItems.Push(listViewDrop.Items[listViewDrop.Items.Count - 1]);
            listViewDrop.Items.Remove(listViewDrop.Items[listViewDrop.Items.Count - 1]);
        }
 
        listViewDrop.Items.Add(item);
 
        while (movedItems.Count > 0)
        {
            listViewDrop.Items.Add(movedItems.Pop());
        }
    }
 
    void radListView1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left &&
        this.lastMouseDownLocation != null &&
        radListView1.SelectedItems.Count > 0)
        {
            Point cursorPos = new Point(e.X, e.Y);
            Point dragPoint = (Point)this.lastMouseDownLocation;
 
            Rectangle dragRect = new Rectangle(dragPoint,
            SystemInformation.DragSize);
            dragRect.X -= (int)(SystemInformation.DragSize.Width / 2);
            dragRect.Y -= (int)(SystemInformation.DragSize.Height / 2);
 
            if (dragRect.Contains(cursorPos) == false)
            {
                radListView1.Capture = false;
                List<ListViewDataItem> selectedItems = radListView1.SelectedItems.ToList<ListViewDataItem>();
 
                radListView1.DoDragDrop(selectedItems, DragDropEffects.Move);
            }
        }
    }
 
    void radListView1_MouseDown(object sender, MouseEventArgs e)
    {
        BaseListViewVisualItem itemAtPoint = radListView1.ElementTree.GetElementAtPoint(e.Location) as BaseListViewVisualItem;
        if (itemAtPoint != null)
            this.lastMouseDownLocation = new Point(e.X, e.Y);
        else
            this.lastMouseDownLocation = null;
    }
}

For your convenience, I have logged this as a feature request in PITS so you can subscribe and vote for it. As it gets more votes, we will consider implementing it with higher priority in the future releases.

Your Telerik points have been updated for requesting this feature.

Greetings,
Ivan Todorov
the Telerik team

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

0
tom
Top achievements
Rank 1
answered on 18 Aug 2011, 06:37 AM
Hello Ivan,

thank you this example was very helpfull.

But one question is not answered: the RadGridView has the possibility to show a drag image or hint during dragging. Do you know also a simple workaround for this?

Best regards,
Tom
0
Ivan Todorov
Telerik team
answered on 19 Aug 2011, 04:48 PM
Hello Tom,

You can add the following code to the class in my previous post in order to get a custom drag cursor:

Cursor textcursor;
 
public static Bitmap SetOpacity(Bitmap original, float opacity)
{
    Bitmap temp = new Bitmap(original.Width, original.Height);
    Graphics g = Graphics.FromImage(temp);
    ColorMatrix cm = new ColorMatrix();
    cm.Matrix33 = opacity;
 
    ImageAttributes ia = new ImageAttributes();
    ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
    g.DrawImage(original, new Rectangle(0, 0, temp.Width, temp.Height), 0, 0, original.Width, original.Height, GraphicsUnit.Pixel, ia);
    g.Dispose();
 
    return temp;
}
 
public void Drawcursor(DragEventArgs e)
{
    IDataObject dataObject = e.Data;
    if (dataObject == null)
    {
        return;
    }
 
    List<ListViewDataItem> selectedItems = dataObject.GetData(typeof(List<ListViewDataItem>)) as List<ListViewDataItem>;
    if (selectedItems == null || selectedItems.Count == 0)
    {
        return;
    }
 
    RadElement element = this.radListView1.ListViewElement.ViewElement.GetElement(selectedItems[0]);
 
    Bitmap bmp = SetOpacity(element.GetAsBitmapEx(Color.Transparent, 0, new SizeF(1, 1)), 0.5f);
     
    textcursor = new Cursor(bmp.GetHicon());
 
    bmp.Dispose();
}
 
void radListView1_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
    e.UseDefaultCursors = false;
    Cursor.Current = textcursor;
}
 
void radListView1_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Move;
    Drawcursor(e);
}

I hope this is useful. Feel free to ask if you have any further questions.

Best wishes,
Ivan Todorov
the Telerik team

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

0
tom
Top achievements
Rank 1
answered on 22 Aug 2011, 03:53 PM
Hi Ivan,

many thanks for your fantastic code snippets. They are very helpfull and instructive.

So I feel a little bit bad, if I ask you for some further help.
The dragging image is one solved request, but it would be very nice, if the user could see the insertion point of the dropped items dynamically. I think something like a insertion cue. Maybe only one bold line at the top,left,right or bottom of an item, showing the possibility of insertion.

Many thanks in advance.

Best regards,
Tom
0
Ivan Todorov
Telerik team
answered on 25 Aug 2011, 08:56 AM
Hi Tom,

I am glad that you find my answer helpful. Please do not hesitate to contact us, ask questions or leave feedback whenever you need to. Our team is always ready to help.

As to your question, you can display some kind of visual clue of the insertion point by handling the following events:

void radListView1_DragOver(object sender, DragEventArgs e)
{
    Point location = this.radListView1.PointToClient(new Point(e.X, e.Y));
 
    this.radListView1.ListViewElement.SynchronizeVisualItems();
 
    BaseListViewVisualItem visual = this.radListView1.ElementTree.GetElementAtPoint(location) as BaseListViewVisualItem;
 
    if (visual != null)
    {
        visual.BackColor = Color.Red;
        visual.NumberOfColors = 1;
    }
 
    this.radListView1.ListViewElement.Update(RadListViewElement.UpdateModes.InvalidateItems);
}
 
void radListView1_VisualItemFormatting(object sender, ListViewVisualItemEventArgs e)
{
    e.VisualItem.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local);
    e.VisualItem.ResetValue(LightVisualElement.NumberOfColorsProperty, ValueResetFlags.Local);
}

Using the same approach you can set every property of the visual item you need. Please have in mind that you have to reset its local setting in the VisualItemFormatting event.

Indeed, such functionality will come very handy out of the box, so we might expect it to be introduced in the near future.

Kind regards,
Ivan Todorov
the Telerik team

Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

0
Paul
Top achievements
Rank 2
answered on 22 Jun 2012, 11:12 AM
Could someone help me convert this to vb.net? I'm having the worst time trying to get it working.

Thanks :)
0
Stefan
Telerik team
answered on 27 Jun 2012, 07:31 AM
Here you are Paul:
     Private Sub radListView1_DragOver(sender As Object, e As DragEventArgs)
    Dim location As Point = Me.radListView1.PointToClient(New Point(e.X, e.Y))
 
    Me.radListView1.ListViewElement.SynchronizeVisualItems()
 
    Dim visual As BaseListViewVisualItem = TryCast(Me.radListView1.ElementTree.GetElementAtPoint(location), BaseListViewVisualItem)
 
    If visual IsNot Nothing Then
        visual.BackColor = Color.Red
        visual.NumberOfColors = 1
    End If
 
    Me.radListView1.ListViewElement.Update(RadListViewElement.UpdateModes.InvalidateItems)
End Sub
 
Private Sub radListView1_VisualItemFormatting(sender As Object, e As ListViewVisualItemEventArgs)
    e.VisualItem.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local)
    e.VisualItem.ResetValue(LightVisualElement.NumberOfColorsProperty, ValueResetFlags.Local)
End Sub

You can always use our free online converter for converting code between C# and VB.NET: http://converter.telerik.com/.

I hope this helps.
 
Regards,
Stefan
the Telerik team
RadControls for WinForms Q2'12 release is now live! Check out what's new or download a free trial >>
Tags
ListView
Asked by
tom
Top achievements
Rank 1
Answers by
Ivan Todorov
Telerik team
tom
Top achievements
Rank 1
Paul
Top achievements
Rank 2
Stefan
Telerik team
Share this question
or