GongSolutions.WPF.DragDrop
是一个很强大的WPF拖拽库github地址,我们看到Github上的ListBox
拖拽例子是基于两个ListBox的ItemSorce
的数据类型是相同的,如果两个ListBox
上的ItemSource
数据类型不一样,我们该怎么进行,这时就要使用这个dd:DragDrop.DropHandler
这个属性进行后台的MVVM绑定。
1.正常设置这个几个属性
dd:DragDrop.IsDragSource="True" //是否开启拖拽源
dd:DragDrop.IsDropTarget="True" //是否是拖放目标
dd:DragDrop.DropTargetAdornerBrush="Red" //拖拽过程产生的效果
2.分别设置两个ListBox的
DataTemplate
数据展示模板,模板的数据是不同的类型ListDataLeft
和ListDataRight
<DataTemplate x:Key="LeftListBoxKey" DataType="{x:Type local:ListDataLeft}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" Foreground="Green"/>
<TextBlock Margin="20,0,0,0" Text="{Binding Id}" FontSize="16" Foreground="Black"/>
<TextBlock Margin="20,0,0,0" Text="{Binding Id}" Foreground="Gray"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="RightListBoxKey" DataType="{x:Type local:ListDataRight}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" Foreground="Green"/>
<TextBlock Margin="20,0,0,0" Text="{Binding Name}" FontSize="16" Foreground="Black"/>
<TextBlock Margin="20,0,0,0" Text="{Binding Description}" Foreground="Red"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="LeftListBox"
Background="#1c1c1c"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="False"
dd:DragDrop.DropTargetAdornerBrush="Red"
ItemTemplate="{StaticResource LeftListBoxKey}"
ItemsSource="{Binding ListDataLefts}"
>
</ListBox>
<!--其中dd:DragDrop.DropHandler="{Binding CopyDragHandler}" 是我们自定义拖放逻辑-->
<ListBox x:Name="RightListBox"
Background="Gray" Grid.Column="1"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropTargetAdornerBrush="Red"
dd:DragDrop.DropHandler="{Binding CopyDragHandler}"
ItemTemplate="{StaticResource RightListBoxKey}"
ItemsSource="{Binding listDataRights}"
>
</ListBox>
</Grid>
3.创建其对应的ViewModel
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace DropDemo
{
public class MainViewModel : INotifyPropertyChanged, IInsert
{
public ObservableCollection<ListDataLeft> ListDataLefts { get; set; }
public ObservableCollection<ListDataRight> listDataRights { get; set; }
public CopyDragHandler CopyDragHandler { get; set; }
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public MainViewModel()
{
CopyDragHandler = new CopyDragHandler(this);
ListDataLefts = new ObservableCollection<ListDataLeft>()
{
new ListDataLeft()
{
Id = 1,
Name="itemLeft1"
},
new ListDataLeft()
{
Id = 2,
Name="itemLeft2"
},
new ListDataLeft()
{
Id = 3,
Name="itemLeft3"
},
};
listDataRights = new ObservableCollection<ListDataRight>()
{
new ListDataRight() {
Id = 1,
Name="itemRight1",
Description="显示itemRight1"
},
new ListDataRight() {
Id = 2,
Name="itemRight2",
Description="显示itemRight2"
},
new ListDataRight() {
Id = 3,
Name="itemRight3",
Description="显示itemRight3"
}
};
}
/// <summary>
/// 插入元素
/// </summary>
/// <param name="index"></param>
/// <param name="value"></param>
public void Insert(int index, ListDataRight value, bool IsSameType = false)
{
int count=listDataRights.Count;
if (!IsSameType)
{
if (count >= index)
{
listDataRights.Insert(index, value);
}
}
else
{
if (count > index)
{
int oldIndex=listDataRights.IndexOf(value);
listDataRights.Move(oldIndex,index);
}
else if(count == index)
{
listDataRights.Remove(value);
listDataRights.Add(value);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class ListDataLeft
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ListDataRight
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
4.实现CopyDragHandler,需要实现
IDropTarget
接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GongSolutions.Wpf.DragDrop;
namespace DropDemo
{
public class CopyDragHandler : IDropTarget
{
private IInsert _insert;
public CopyDragHandler(IInsert insert)
{
_insert = insert;
}
public void DragEnter(IDropInfo dropInfo)
{
}
public void DragLeave(IDropInfo dropInfo)
{
}
/// <summary>
/// 悬浮在Item上执行操作
/// </summary>
/// <param name="dropInfo"></param>
public void DragOver(IDropInfo dropInfo)
{
object sourceitem=dropInfo.Data;
object targetitem=dropInfo.TargetItem;//拖拽到上方的子项
if(sourceitem!=null && targetitem != null)
{
dropInfo.Effects = System.Windows.DragDropEffects.Copy;//显示可拖放
dropInfo.DropTargetAdorner=DropTargetAdorners.Insert;
}
}
public void Drop(IDropInfo dropInfo)
{
object sourceitem = dropInfo.Data;
ListDataRight targetitem = dropInfo.TargetItem as ListDataRight;//拖拽到上方的子项
int index = dropInfo.InsertIndex;//要插入到目标上的第几个位置
if(sourceitem.GetType() == typeof(ListDataLeft))//如果是不同的数据类型
{
ListDataLeft listDataLeft = (ListDataLeft)sourceitem;
ListDataRight listDataRight = new ListDataRight()
{
Id = listDataLeft.Id,
Name = listDataLeft.Name,
Description = "itemRight"
};
_insert.Insert(index, listDataRight);
}
else if(sourceitem.GetType() == typeof(ListDataRight))//如果是相同的数据类型
{
ListDataRight listDataright = (ListDataRight)sourceitem;
_insert.Insert(index, listDataright, true);
}
}
}
}
最终效果实现了两个ListBox的ItemSource不同数据类型的拖拽操作