I'm using a Listbox
wrapped inside a ListBoxDragDropTarget
(from the Silverlight toolkit).
This ListBox
ca be manually reordered by the user. However the last item must always be located at the bottom of the ListBox
, and can't be moved at all. I found a way to cancel this last item moves, but if I drag and drop another item below this last item, it gets moved.
I can find the index of the dragged item using this code in the Drop
event of the ListBox:
object data = e.Data.GetData(e.Data.GetFormats()[0]);
ItemDragEventArgs dragEventArgs = data as ItemDragEventArgs;
SelectionCollection selectionCollection = dragEventArgs.Data as SelectionCollection;
if (selectionCollection != null)
{
MyClass cw = selectionCollection[0].Item as MyClass;
int idx = selectionCollection[0].Index.Value;
}
However this only gives me the index before the drag operation.
My question is the following: Is there a way to know the new index of the dropped item ? This way, if the index = last position of the list, I can move it to the forelast position.
Thanks in advance !
Ok I found a way to do this. I bound the ItemDragCompleted
event of the ListBoxDragDropTarget
, and did the following:
private void dropTarget1_ItemDragCompleted(object sender, ItemDragEventArgs e)
{
var tmp = (e.DragSource as ListBox).ItemsSource.Cast<MyClass>().ToList();
SelectionCollection selectionCollection = e.Data as SelectionCollection;
if (selectionCollection != null)
{
MyClass cw = selectionCollection[0].Item as MyClass;
int idx = tmp.IndexOf(cw);
if (idx == tmp.Count - 1)
{
tmp.Remove(cw);
tmp.Insert(tmp.Count - 1, cw);
MyListBox.ItemsSource = new ObservableCollection<MyClass>(tmp);
}
}
}
As the DragSource represents the Listbox, with the new "arrangement" of items, I can therefore check if the item is now located at the end, and move it in this case.
The only problem left is that it causes a flicker on the screen, due to the item being dropped and then moved.
I'm still open to any other (best) suggestion.
I have this exact same problem. I think it may be possible to loop through the rectangles of the items in the ListBox and see if var point = args.GetPosition(myListBox); is within them. But I am hoping for an easier way...
Edit: The problem with this though, is you don't get the gravity effect that is already built in to silverlight where only half of the above and half of the below rectangle are used to drop it into the list.