Chris
Chris

Reputation: 7611

Drag drop sorting in C# - Best algorithm

I have a Telerik RadGrid which allows the user to drag rows to reorder them. What will happen on the server side is an int column for each row will be modified based on where they've dragged, then we sort on this figure on the screens.

What I can't figure out is the easiest way to handle the reordering in the code behind. What's the easiest/best way of updating incrementing/decrementing any rows 'inbetween' the dragged rows?

EDIT: What I have so far

     //We should only allow one section to be dragged at a time
            GridDataItem draggedItem = e.DraggedItems.Single();
            TakeoffSection draggedSection = dc.TakeoffSections.Where(a => a.ID == (long)draggedItem.GetDataKeyValue("ID")).Single(); 
            int origDragSectNo = draggedSection.SectionNo;

            GridDataItem destItem = e.DestDataItem;
            TakeoffSection destSection = dc.TakeoffSections.Where(a => a.ID == (long)destItem.GetDataKeyValue("ID")).Single(); 
            int origDestSectNo = destSection.SectionNo;

            if (e.DropPosition == GridItemDropPosition.Above)
            {
                if (draggedSection.SectionNo < destSection.SectionNo)
                {
                    //They are dragging *down*!
                    draggedSection.SectionNo = destSection.SectionNo;
                    destSection.SectionNo++;

                    foreach (var item in dc.TakeoffSections.Where(a => a.RevisionID == ActiveRevisionID && a.SectionNo < origDestSectNo && a.SectionNo > origDestSectNo))
                        item.SectionNo--;
                    dc.SubmitChanges();
                }
                else
                {
                    //They are dragging *up*

                }
            }

Upvotes: 2

Views: 2570

Answers (1)

Win
Win

Reputation: 62260

Basically, you need to update all items' SectionNo. In other words, you are not swapping two items instead you are pushing down SectionNo of items below.

Here is the algorithm I use.

protected void RadGrid1_RowDrop(object sender, GridDragDropEventArgs e)
{
   var ids = (from GridDataItem item in this.RadGrid1.Items
            select Convert.ToInt32(item.GetDataKeyValue("ID"))).ToList();

   // Rearranges item in requested order
   if (ids.Count > 0 && e.DestDataItem != null)
   {
     // Get the index of destination row
     int destItem = ids.FirstOrDefault(item => 
       item == Convert.ToInt32(e.DestDataItem.GetDataKeyValue("ID")));

     int destinationIndex = destItem == 0 ? -1 : ids.IndexOf(destItem);

     foreach (GridDataItem draggedItem in e.DraggedItems)
     {
       int draggedId = ids.FirstOrDefault(item => 
         item == Convert.ToInt32(draggedItem.GetDataKeyValue("ID")));

       if (draggedId != 0 && destinationIndex > -1)
       {
         // Remove and re-insert at specified index
         ids.Remove(draggedId);
         ids.Insert(destinationIndex, draggedId);
       }
     }
   }

   // Update each entity's display orders based on the given order
   MyUpdateDisplayOrder(ids);

   RadGrid1.Rebind();
}

Upvotes: 3

Related Questions