WPF drag and drop to a specific position in a list
I have a list view and have defined handlers for it which will allow me to select an entry on the list and move it to another position.
So I can grab say the 5th item in the list and drag it up to the 2nd position.
In my view model I have code which tells me the 5th item was selected and shows me the contents of the selected data object, but I don't know how to pick up the position I want to move it to.
It is easy if I just want to add to the bottom of the list (say dragging thing sover from 1 list to the other) but I want to resequence the items in my list.
Here is my XAML :
<ListView Grid.Row="1" x:Name="HierarchyMenuListView" Style="{StaticResource ListViewStyle}" Margin="5,5,5,5"
ItemsSource="{Binding Path=UserMenuList}" MouseMove="ListView_MouseMove" Drop="ListView_Drop" AllowDrop="True"
In my ListView_Drop method I can see exactly what I want to move, I just can't pick up where I want to move it to.
Can anyone help? It feels like I am very close, but just not close enough

I have been forwarded a few C# examples and will work through those.
I think my code is "nearly" correct and I just have to set something to allow the drag operation to be completed.
I was just hoping that someone, somewhere in the synergy world had resequenced an item in a list before

I have gone down so many wrong roads on this, and googled until I am cross eyed.
I can do everything but find the target position to drop the item into its new position in the grid.
It is easy to add something to the END of a list. I have found loads of people asking the same thing on forums, but the answers just don't seem to work
Surely someone, somewhere has done this in the past ???????????

If everything is valid, does the re-ordered item appear in its new place in the list and I then update the list in my code ?
Or does it not appear in its new position until I trap where it is moved to and then I update my list ?
If tits the latter, then I am back to not knowing how to tell what the target is. All I seem to be able to access is the sourcve position in the grid/list
Here are the steps I take:
- using the sender parameter as a ListBox, get the listbox.SelectedItems. These are the items being dragged.
- using listbox.datacontext, create a viewmodel object. this gives you access to your collection
- now you have to figure out what you "landed" on when you did the drop. In my case the item template contains TextBlocks, Border, Button, and so on, so you need a series of if's to catch what you landed on. See the attached code. Keep in mind you can drop at the bottom of the list, this will cause the "landed on" item to be null.
- once you catch which item you landed on you create an object of that type using e.OriginalSource (if you have it in the handler parameters). Now you can create an item (which is the type of the items in your collection) by using this object.DataContext. Now we know which item in your collection you have dropped on top of.
- remove the dragged items from the collection
- find the index of the item we dropped onto, item could be null here.
- if the "landed on" item is null, just add the dragged item/items to the bottom of the list. else Insert the dragged item/items into the collection.
That should be all. I think it all depends on whether or not the e parameter of the handler contains e.OriginalSource.
Here is my OnDrop handler that contains all of the described code from above:
private void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs e) { int currentLoadNo = 0; int dropSpotIndex = 0; RccDelivery rccDelDropSpotItem = null; ObservableCollection<RccDelivery> BackupList = new ObservableCollection<RccDelivery>(); ListBox listbox = sender as ListBox; var selectedItems = listbox.SelectedItems as IList; // Items we are dragging ObservableCollection<RccDelivery> DraggedList = new ObservableCollection<RccDelivery>(); foreach (RccDelivery rccD in selectedItems) { DraggedList.Add(rccD); } tmvm = listbox.DataContext as TicketManagerVM; currentLoadNo = tmvm.OutstandingLoadDeliveriesList[0].LoadNo; // make a backup of the list BackupList = new ObservableCollection<RccDelivery>(tmvm.OutstandingLoadDeliveriesList); // Figure out which item we landed on if (e.OriginalSource is TextBlock) { TextBlock tb = e.OriginalSource as TextBlock; rccDelDropSpotItem = tb.DataContext as RccDelivery; if (rccDelDropSpotItem == null) { ListBoxItem _listboxitem = RccVisualTreeHelpers.FindParent<ListBoxItem>(tb); if (_listboxitem != null) { rccDelDropSpotItem = _listboxitem.DataContext as RccDelivery; } } } else if (e.OriginalSource is Border) { Border bd = e.OriginalSource as Border; rccDelDropSpotItem = bd.DataContext as RccDelivery; } else if (e.OriginalSource is Button) { Button bt = e.OriginalSource as Button; rccDelDropSpotItem = bt.DataContext as RccDelivery; } else if (e.OriginalSource is Rectangle) { Rectangle rt = e.OriginalSource as Rectangle; rccDelDropSpotItem = rt.DataContext as RccDelivery; } else if (e.OriginalSource is ScrollViewer) { // Drop a the end rccDelDropSpotItem = null; } else { e.Handled = true; return; } // is the rccDelDropSpotItem in the DraggedList if (rccDelDropSpotItem != null) { int x = DraggedList.IndexOf(rccDelDropSpotItem); if (x != -1) { if (dragToScrollListBoxItem != null) { if (indicationAdorner != null) { var adornerObject = AdornerLayer.GetAdornerLayer(dragToScrollListBoxItem); if (adornerObject != null) { AdornerLayer.GetAdornerLayer(dragToScrollListBoxItem).Remove(indicationAdorner); indicationAdorner = null; } } } e.Handled = true; return; } } // remove the Dragged items from the collection foreach (RccDelivery rccD in DraggedList) { tmvm.OutstandingLoadDeliveriesList.Remove(rccD); } // find the index of the Item being Dropped on to if (rccDelDropSpotItem != null) { dropSpotIndex = tmvm.OutstandingLoadDeliveriesList.IndexOf(rccDelDropSpotItem); } if (rccDelDropSpotItem == null) { //ADD them to the collection foreach (RccDelivery rccD in DraggedList) { tmvm.OutstandingLoadDeliveriesList.Add(rccD); } } else { //INSERT them to the collection foreach (RccDelivery rccD in DraggedList) { tmvm.OutstandingLoadDeliveriesList.Insert(dropSpotIndex, rccD); dropSpotIndex++; } } listbox.SelectedItems.AddRange(DraggedList); if (currentLoadNo != 0) { tmvm.UpdateDeliveriesLoadSeq(currentLoadNo); // Clear load and delivery trip info properties. tmvm.ClearTripInfoProperties(currentLoadNo); tmvm.CalculateEstimatedLoadGallons(currentLoadNo); tmvm.SetLoadToDirty(currentLoadNo); } }

I will convert to synergy.net and see how I get on with it.
I can see e.OriginalSource in my drop code, but I didn't know what to do with it.