DragOver
не удаляет никаких предметов.Вы удаляете предметы методом Drop
.Вы не должны выполнять удаление или добавление в методе DragOver
, для этого и нужен метод Drop
.DragOver
следует использовать только для установки целевого украшения и эффектов.Я использовал ILSpy для просмотра их кода (см. Ниже), и это помогло пролить некоторый свет на то, что здесь происходит.У них есть класс с именем DefaultDropHandler : IDropTarget
, который, как следует из названия, является обработчиком удаления по умолчанию, если он не назначен с использованием присоединенного свойства dd:DragDrop.DropHandler
.Поэтому, когда вы удаляете строку dd:DragDrop.DropHandler="{Binding}"
, это то, что используется для операции удаления.Глядя на их код, все обрабатывается для вас, то есть элемент добавляется и удаляется, с целым рядом ошибок и проверок индекса на этом пути.
Когда вы действительно установите обработчик отбрасывания какваша ViewModel, ни один из кодов в обработчике по умолчанию не выполняется, так как вы заменили этот обработчик с вашей ViewModel.Таким образом, вы должны полностью справиться с падением.Другими словами, вы должны выполнить всю проверку ошибок и типов, удалить элементы и добавить элементы (если у вас более одного списка) и сохранить правильный порядок.Вы также можете проверить, что исходная коллекция не совпадает с целевой коллекцией, прежде чем выполнять какие-либо операции удаления и добавления, но это все равно не добавит их в правильные позиции.
Поскольку у вас есть толькоодин список, не удаляйте элемент в методе Drop
.Но ничего не произойдет по причинам, которые я изложил выше.Если у вас есть более одного списка, вот как вы бы перемещали элементы из одного списка в другой:
public void Drop(IDropInfo dropInfo)
{
MSP msp = (MSP)dropInfo.Data;
if(dropInfo.DragInfo.SourceCollection != dropInfo.TargetCollection)
{
((IList)dropInfo.DragInfo.SourceCollection).Remove(msp);
((IList)dropInfo.TargetCollection).Add(msp);
}
}
Вы должны будете выполнить работу по поддержанию элементов в правильном порядке, если этоэто то, что вам нужно.В качестве альтернативы выполнению всей этой работы вы можете использовать и расширить их обработчик по умолчанию.Они создали Drop
метод virtual
, так что вы можете сделать так, чтобы ваша модель представления наследовала от DefaultDropHandler
(т.е. class MainViewModel : DefaultDropHandler
) вместо реализации интерфейса IDropTarget
.Затем просто переопределите метод Drop
и вызовите базовый метод.Примерно так:
public override void Drop(IDropInfo dropInfo)
{
base.Drop(dropInfo);
//do other stuff
}
Вы также можете переопределить метод DragOver
таким же образом, если вам нужно, но если вы этого не сделаете, он просто будет использовать поведение по умолчанию.
Дополнительная информация
Если вам интересно, вот обработчик по умолчанию, который использует Гун, когда вы его не назначаете:
public virtual void Drop(IDropInfo dropInfo)
{
if (dropInfo != null && dropInfo.DragInfo != null)
{
int insertIndex = (dropInfo.InsertIndex != dropInfo.UnfilteredInsertIndex) ? dropInfo.UnfilteredInsertIndex : dropInfo.InsertIndex;
ItemsControl itemsControl = dropInfo.VisualTarget as ItemsControl;
if (itemsControl != null)
{
IEditableCollectionView editableItems = itemsControl.Items;
if (editableItems != null)
{
NewItemPlaceholderPosition newItemPlaceholderPosition = editableItems.NewItemPlaceholderPosition;
if (newItemPlaceholderPosition == NewItemPlaceholderPosition.AtBeginning && insertIndex == 0)
{
insertIndex++;
}
else if (newItemPlaceholderPosition == NewItemPlaceholderPosition.AtEnd && insertIndex == itemsControl.Items.Count)
{
insertIndex--;
}
}
}
IList destinationList = dropInfo.TargetCollection.TryGetList();
List<object> data = ExtractData(dropInfo.Data).OfType<object>().ToList();
List<object>.Enumerator enumerator;
if (!ShouldCopyData(dropInfo))
{
IList sourceList = dropInfo.DragInfo.SourceCollection.TryGetList();
if (sourceList != null)
{
enumerator = data.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
object o2 = enumerator.Current;
int index = sourceList.IndexOf(o2);
if (index != -1)
{
sourceList.RemoveAt(index);
if (destinationList != null && object.Equals(sourceList, destinationList) && index < insertIndex)
{
insertIndex--;
}
}
}
}
finally
{
((IDisposable)enumerator).Dispose();
}
}
}
if (destinationList != null)
{
TabControl tabControl = dropInfo.VisualTarget as TabControl;
bool cloneData = dropInfo.Effects.HasFlag(DragDropEffects.Copy) || dropInfo.Effects.HasFlag(DragDropEffects.Link);
enumerator = data.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
object o = enumerator.Current;
object obj2Insert = o;
if (cloneData)
{
ICloneable cloneable = o as ICloneable;
if (cloneable != null)
{
obj2Insert = cloneable.Clone();
}
}
destinationList.Insert(insertIndex++, obj2Insert);
if (tabControl != null)
{
TabItem obj = tabControl.ItemContainerGenerator.ContainerFromItem(obj2Insert) as TabItem;
if (obj != null)
{
obj.ApplyTemplate();
}
tabControl.SetSelectedItem(obj2Insert);
}
}
}
finally
{
((IDisposable)enumerator).Dispose();
}
}
}
}