我正在尝试将我的Gong Solutions拖放到一个列表中。当我拖放一个项目时,它将从列表中删除该项目,并且我可以看到它从界面中消失了。看来DragOver
方法不是先移动对象,所以当Drop
方法启动时,它只是删除了该项目。
当我删除属性dd:DragDrop.DropHandler="{Binding}"
时,在界面上的拖放工作正常。但是,我必须触发事件,这样我才能知道列表何时重新排序。
XAML:
<Window x:Class="Reorder_item_WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop">
<Grid>
<ListBox Grid.Column="1" SelectionMode="Extended" ItemsSource="{Binding MSPCollection}"
dd:DragDrop.IsDragSource="True" Width="300" Margin="0,0,5,0"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="#2ba3d5" Height="50" Width="280">
<TextBlock Drop="TextBlock_Drop" Text="{Binding Name}"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="40"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
C#:
public class MSP {
public int Id { get; set; }
public string Name { get; set; }
}
class MainViewModel : IDropTarget
{
public ObservableCollection<MSP> MSPCollection { get; set; }
public MainViewModel() {
MSPCollection = new ObservableCollection<MSP>();
MSPCollection.Add(new MSP() {
Id = 1,
Name = "Anis Derbel"
});
MSPCollection.Add(new MSP()
{
Id = 2,
Name = "Firas Mdimagh"
});
MSPCollection.Add(new MSP()
{
Id = 3,
Name = "Khaled Jemni"
});
MSPCollection.Add(new MSP()
{
Id = 4,
Name = "Sahbouch"
});
}
public void DragOver(IDropInfo dropInfo) {
if (dropInfo.Data is MSP) {
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
dropInfo.Effects = DragDropEffects.Move;
}
}
public void Drop(IDropInfo dropInfo) {
MSP msp = (MSP)dropInfo.Data;
((IList)dropInfo.DragInfo.SourceCollection).Remove(msp);
}
}
答案 0 :(得分:1)
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
方法,并调用base方法。像这样:
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();
}
}
}
}