C# 通过拖放对列表进行排序,可以从列表中删除项目

C# 通过拖放对列表进行排序,可以从列表中删除项目,c#,wpf,xaml,drag-and-drop,C#,Wpf,Xaml,Drag And Drop,我试图让我的解决方案拖放到一个单一的列表排序。当我拖放一个项目时,它会从列表中删除该项目,我可以看到它从界面中消失。似乎DragOver方法没有首先移动对象,因此当Drop方法触发时,它只是删除该项 当我删除属性dd:DragDrop.DropHandler=“{Binding}”时,界面上的拖放工作正常。但是,我必须有一个事件火灾,以便我知道列表何时被重新排序 XAML: <Window x:Class="Reorder_item_WPF.MainWindow" xmln

我试图让我的解决方案拖放到一个单一的列表排序。当我拖放一个项目时,它会从列表中删除该项目,我可以看到它从界面中消失。似乎
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>
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);
    }
}

C#:

<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>
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);
    }
}
公共类MSP{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
类MainViewModel:IDropTarget
{
公共ObservableCollection MSPCollection{get;set;}
公共主视图模型(){
MSPCollection=新的ObservableCollection();
添加(新的MSP(){
Id=1,
Name=“Anis Derbel”
});
添加(新的MSP()
{
Id=2,
Name=“Firas Mdimagh”
});
添加(新的MSP()
{
Id=3,
Name=“Khaled Jemni”
});
添加(新的MSP()
{
Id=4,
Name=“Sahbouch”
});        
}
公共无效DragOver(IDropInfo dropInfo){
如果(dropInfo.Data是MSP){
dropInfo.DropTargetAdorner=DropTargetAdorner.Highlight;
dropInfo.Effects=DragDropEffects.Move;
}
}
公共作废删除(IDropInfo dropInfo){
MSP MSP=(MSP)dropInfo.Data;
((IList)dropInfo.DragInfo.SourceCollection).Remove(msp);
}
}

DragOver
不会删除任何项目。您正在删除
Drop
方法中的项。您不应该在
DragOver
方法中进行任何删除或添加操作,这就是
Drop
方法的作用
DragOver
只能用于设置目标装饰器和效果。我使用ILSpy查看了他们的代码(见下文),这有助于了解这里发生了什么。它们有一个名为
DefaultDropHandler:IDropTarget
的类,顾名思义,如果没有使用附加属性
dd:DragDrop.DropHandler
指定一个类,则该类是默认的DropHandler。因此,当您删除行
dd:DragDrop.DropHandler=“{Binding}”
时,这就是用于drop操作的内容。看看他们的代码,一切都是为你自己处理的,也就是说,项目被添加和删除,整个过程中有大量的错误检查和索引控制

当您确实将drop处理程序设置为您的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
)而不是实现
IDROPTTarget
接口。然后,只需重写
Drop
方法,并调用base方法。大概是这样的:

public override void Drop(IDropInfo dropInfo)
{
    base.Drop(dropInfo);
    //do other stuff
}
如果需要,也可以用同样的方法覆盖
DragOver
方法,但如果不这样做,它将只使用默认行为

额外信息 如果您感到好奇,这里是Gong在未分配处理程序时使用的默认处理程序:

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();
            }
        }
    }
}
公共虚拟作废删除(IDropInfo dropInfo)
{
if(dropInfo!=null&&dropInfo.DragInfo!=null)
{
int insertIndex=(dropInfo.insertIndex!=dropInfo.UnfilteredInsertIndex)?dropInfo.UnfilteredInsertIndex:dropInfo.insertIndex;
ItemsControl ItemsControl=dropInfo.VisualTarget作为ItemsControl;
if(itemsControl!=null)
{
IEditableCollectionView editableItems=itemsControl.Items;
if(可编辑项!=null)
{
NewItemPlaceholder位置NewItemPlaceholder位置=editableItems.NewItemPlaceholder位置;
if(newItemPlaceholderPosition==newItemPlaceholderPosition.atStart&&insertIndex==0)
{
insertIndex++;
}
else if(newItemPlaceholderPosition==newItemPlaceholderPosition.AtEnd&&insertIndex==itemsControl.Items.Count)
{
插入索引--;
}
}
}
IList destinationList=dropInfo.TargetCollection.TryGetList();
List data=ExtractData(dropInfo.data).OfType().ToList();
列表.枚举器枚举器;
如果(!ShouldCopyData(dropInfo))
{
IList sourceList=dropInfo.DragInfo.SourceCollection.TryGetList();
if(sourceList!=null)
{
枚举数