Gong Solutions拖放以对列表进行排序,从列表中删除项目

时间:2018-12-20 22:53:04

标签: c# wpf xaml drag-and-drop

我正在尝试将我的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);
    }
}

1 个答案:

答案 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();
            }
        }
    }
}