Получить индекс падения в перетаскивании Silverlight - PullRequest
4 голосов
/ 25 сентября 2010

В этой статье показано, как реализовать операцию копирования в событии удаления. Я хотел бы сделать то же самое, но я хочу, чтобы мой упавший элемент отображался в коллекции в соответствии с тем, где он был размещен в пользовательском интерфейсе. Поэтому мне нужно, чтобы StartIndex был похож на NotifyCollectionChangedEventArgs при изменении ObservableCollection. В статье вы увидите, что в конечном итоге вы получите объект SelectionCollection, элементы которого имеют свойство Index. Но, к сожалению, это индекс исходной коллекции (где она была выбрана), а не целевой коллекции (где она была удалена).

1 Ответ

1 голос
/ 31 октября 2011

Ладно, это довольно уродливо, но я не нашел другого пути, ни сам по себе, ни в поисках ответов в сети. Должно быть, это был еще один крайний срок в Microsoft, который не позволил включить довольно очевидную функциональность ...

В основном, метод, описанный ниже, делает все вручную, получая местоположение отбрасывания и проверяя его на наличие элементов списка для использования в качестве ссылок на индексы.

private void ListBoxDragDropTarget_Drop(object sender, Microsoft.Windows.DragEventArgs e)
{
    // only valid for copying
    if (e.Effects.HasFlag(DragDropEffects.Copy))
    {
        SelectionCollection selections = ((ItemDragEventArgs)e.Data.GetData("System.Windows.Controls.ItemDragEventArgs")).Data as SelectionCollection;
        int? index = null;

        if (selections != null)
        {
            Point p1 = e.GetPosition(this.LayoutRoot); // get drop position relative to layout root
            var elements = VisualTreeHelper.FindElementsInHostCoordinates(p1, this.LayoutRoot); // get ui elements at drop location

            foreach (var dataItem in this.lbxConfiguration.Items) // iteration over data items
            {
                // get listbox item from data item
                ListBoxItem lbxItem = this.lbxConfiguration.ItemContainerGenerator.ContainerFromItem(dataItem) as ListBoxItem;

                // find listbox item that contains drop location
                if (elements.Contains(lbxItem))
                {
                    Point p2 = e.GetPosition(lbxItem); // get drop position relative to listbox item
                    index = this.lbxConfiguration.Items.IndexOf(dataItem); // new item will be inserted immediately before listbox item
                    if (p2.Y > lbxItem.ActualHeight / 2)
                        index += 1; // new item will be inserted after listbox item (drop location was in bottom half of listbox item)

                    break;
                }
            }

            if (index != null)
            {
                foreach (var selection in selections)
                {
                    // adding a new item to the listbox - adjust this to your model
                    (lbxConfiguration.ItemsSource as IList<ViewItem>).Insert((int)index, (selection.Item as ViewItem).Clone());
                }
            }
        }
    }
}
...