Listbox drag-reorder : Index of the dropped item

2019-02-11 05:33发布

问题:

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 !

回答1:

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.



回答2:

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.