WPF-DragDrop拖拽文字、文件、图片...
是否允许作为拖拽目标:进入容器边缘触发:拖拽放下触发。
目录
拖拽说明
拖拽推荐框架:gong-wpf-dragdrop
GitHub地址:Usage · punker76/gong-wpf-dragdrop Wiki (github.com)
本章主要使用拖拽三个相关属性及事件:
属性AllowDrop:是否允许作为拖拽目标
事件DragDrop.DragEnter:当对象源进入目标容器边缘时触发
事件DragDrop.Drop:将对象拖放到放置目标时触发
一、拖拽文字
拖拽任意文字到Label中显示
示例代码:见拖拽文件
二、拖拽文件
拖拽文件到Label显示文件内容
示例代码:
<Label Width="300"
Height="300"
AllowDrop="True"
Background="White"
DragDrop.DragEnter="Label_DragEnter"
DragDrop.Drop="Label_Drop" />
private void Label_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Button)))
{
e.Effects= DragDropEffects.Copy;
}
}
private void Label_Drop(object sender, DragEventArgs e)
{
Label label=sender as Label;
if (e.Data.GetDataPresent(DataFormats.Text))
{
var data = e.Data.GetData(DataFormats.Text);
label.Content = data.ToString();
}
else if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string path=((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
label.Content =File.ReadAllText(path);
}
}
三、拖拽图片
拖拽图片到图片控件显示
示例代码;
<Grid Width="300" Background="LightBlue" AllowDrop="True" DragDrop.DragEnter="Grid_DragEnter" DragDrop.Drop="Grid_Drop">
<Image x:Name="img"/>
</Grid>
private void Grid_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
}
private void Grid_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string path = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
Bitmap bitmap=new Bitmap(path);
ImageSource source =Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());
img.Source=source;
}
}
四、控件随鼠标移动
主要通过三个鼠标事件实现:
事件PreviewMouseDown:鼠标按下触发
事件PreviewMouseMove:鼠标移动触发
事件PreviewMouseUp :鼠标松开触发
示例代码:
<Button Width="50"
Height="40"
Background="LightBlue"
Content="Move" HorizontalAlignment="Left" VerticalAlignment="Top"
PreviewMouseDown="Button_PreviewMouseDown"
PreviewMouseMove="Button_PreviewMouseMove"
PreviewMouseUp="Button_PreviewMouseUp" />
RenderTransform:元素呈现位置的转换信息
public bool isMouseDown = false;
public Point mouseDownPosition;
public Point mouseDownControlPosition;
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
isMouseDown = true;
mouseDownPosition = e.GetPosition(this);
var ctl = sender as UIElement;
var transform = ctl.RenderTransform as TranslateTransform;
if (transform == null)
{
transform = new TranslateTransform();
ctl.RenderTransform = transform;
}
mouseDownControlPosition = new Point(transform.X, transform.Y);
ctl.CaptureMouse();
}
private void Button_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown)
{
var ctl = sender as UIElement;
var pos = e.GetPosition(this);
var dp = pos - mouseDownControlPosition;
var translate = ctl.RenderTransform as TranslateTransform;
translate.X = mouseDownControlPosition.X + dp.X;
translate.Y = mouseDownControlPosition.Y + dp.Y;
}
}
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
var ctl = sender as UIElement;
isMouseDown = false;
ctl.ReleaseMouseCapture();
}
五、托拽集合控件数据项
主要实现代码如下:
private void ListView_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var listView = sender as ListView;
if (listView.SelectedItem != null)
{
var vector = listView.SelectedItem as VectorBase;
var dragData = new DataObject(typeof(VectorBase), vector);
DragDrop.DoDragDrop(listView, dragData, DragDropEffects.Move);
}
}
}
private void ListView_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(VectorBase)))
{
var listView = sender as ListView;
var vector = e.Data.GetData(typeof(VectorBase)) as VectorBase;
var pos = e.GetPosition(listView);
var oldIndex = listView.Items.IndexOf(vector);
var newIndex = GetIndexOfPoint(listView, pos);
if (newIndex != -1)
{
var list = listView.ItemsSource as ObservableCollection<VectorBase>;
list.Move(oldIndex, newIndex);
}
}
}
/// <summary>
/// 获取指定Point在ListView对应项的索引
/// </summary>
/// <param name="listView"></param>
/// <param name="pos"></param>
/// <returns></returns>
private int GetIndexOfPoint(ListView listView, Point pos)
{
for (int i = 0; i < listView.Items.Count; i++)
{
var item = listView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
if (item != null)
{
var itemPos = item.TranslatePoint(new Point(0, 0), listView);
Rect itemBound = new Rect(itemPos, new Size(item.ActualWidth, item.ActualHeight));
if (itemBound.Contains(pos))
{
return i;
}
}
}
return -1;
}
六、拖拽移动控件
主要用到MouseLeftButtonDown、Drop两个事件实现移动控件
示例代码:
前端:
<WrapPanel x:Name="wrap1"
Width="300"
Height="400"
HorizontalAlignment="Left"
VerticalAlignment="Top"
AllowDrop="True"
Background="YellowGreen"
Drop="WrapPanel_Drop" />
<WrapPanel Name="wrap2"
Grid.Column="1"
Width="300"
Height="400"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Background="DarkMagenta"
MouseLeftButtonDown="WrapPanel_MouseLeftButtonDown">
<ItemsControl d:ItemsSource="{d:SampleData ItemCount=5}" ItemsSource="{Binding MyList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer hc:ScrollViewerAttach.Orientation="Horizontal"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Hidden">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type model:Student}">
<Border BorderBrush="Black"
BorderThickness="2"
CornerRadius="3">
<Label Width="80" Height="40"
Background="YellowGreen"
Content="{Binding Name}"
FontSize="20"
FontWeight="Bold" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>
后台:
private void WrapPanel_Drop(object sender, DragEventArgs e)
{
var obj=e.Data;
object data = obj.GetData(obj.GetFormats()[0]);
if (data is UIElement)
{
wrap2.Children.Remove(data as UIElement);
wrap1.Children.Add(data as UIElement);
}
}
private void WrapPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var obj=e.Source;
if (obj is UIElement )
{
DragDrop.DoDragDrop(obj as UIElement, obj, DragDropEffects.Move);
}
}
效果展示:
拖拽后
七、使用gong-wpf-dragdrop拖拽框架
拖拽推荐框架:gong-wpf-dragdrop
GitHub地址:Usage · punker76/gong-wpf-dragdrop Wiki (github.com)
主要使用框架依赖属性:
dd:DragDrop.IsDragSource="True"//是否作为拖拽源
dd:DragDrop.IsDropTarget="False"//是否作为投递目标dd:DragDrop.UseDefaultDragAdorner="True"//使用默认的拖拽装饰器
dd:DragDrop.UseDefaultEffectDataTemplate="True"//使用默认的阴影数据模板
dd:DragDrop.EffectMoveAdornerTemplate//指定移动时的阴影装饰器模板
dd:DragDrop.DropHandler="{Binding MyDropHandler}"//投下时执行处理器
注意 :框架默认行为是移动,可通过DropHandler实现复制功能
1、DropHandler实现复制(非移动)示例代码
参考GitHub中Demo代码
internal class CopyDropHandler : IDropTarget
{
#if true
/// <summary>
/// Test the specified drop information for the right data.
/// </summary>
/// <param name="dropInfo">The drop information.</param>
public static bool CanAcceptData(IDropInfo dropInfo)
{
if (dropInfo?.DragInfo == null)
{
return false;
}
if (!dropInfo.IsSameDragDropContextAsSource)
{
return false;
}
// do not drop on itself
var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter)
&& dropInfo.VisualTargetItem is TreeViewItem;
if (isTreeViewItem && dropInfo.VisualTargetItem == dropInfo.DragInfo.VisualSourceItem)
{
return false;
}
if (dropInfo.TargetCollection is null)
{
return false;
}
if (ReferenceEquals(dropInfo.DragInfo.SourceCollection, dropInfo.TargetCollection))
{
var targetList = dropInfo.TargetCollection.TryGetList();
return targetList != null;
}
if (TestCompatibleTypes(dropInfo.TargetCollection, dropInfo.Data))
{
var isChildOf = IsChildOf(dropInfo.VisualTargetItem, dropInfo.DragInfo.VisualSourceItem);
return !isChildOf;
}
return false;
}
public static IEnumerable ExtractData(object data)
{
if (data is IEnumerable enumerable and not string)
{
return enumerable;
}
return Enumerable.Repeat(data, 1);
}
/// <summary>
/// Clears the current selected items and selects the given items.
/// </summary>
/// <param name="dropInfo">The drop information.</param>
/// <param name="items">The items which should be select.</param>
/// <param name="applyTemplate">if set to <c>true</c> then for all items the ApplyTemplate will be invoked.</param>
/// <param name="focusVisualTarget">if set to <c>true</c> the visual target will be focused.</param>
/// <exception cref="System.ArgumentNullException"><paramref name="dropInfo" /> is <see langword="null" /></exception>
/// <exception cref="System.ArgumentNullException"><paramref name="dropInfo" /> is <see langword="null" /></exception>
public static void SelectDroppedItems(IDropInfo dropInfo, IEnumerable items, bool applyTemplate = true, bool focusVisualTarget = true)
{
if (dropInfo == null) throw new ArgumentNullException(nameof(dropInfo));
if (items == null) throw new ArgumentNullException(nameof(items));
if (dropInfo.VisualTarget is ItemsControl itemsControl)
{
var tvItem = dropInfo.VisualTargetItem as TreeViewItem;
var tvItemIsExpanded = tvItem != null && tvItem.HasHeader && tvItem.HasItems && tvItem.IsExpanded;
var itemsParent = tvItemIsExpanded
? tvItem
: dropInfo.VisualTargetItem != null
? ItemsControl.ItemsControlFromItemContainer(dropInfo.VisualTargetItem)
: itemsControl;
itemsParent ??= itemsControl;
(dropInfo.DragInfo.VisualSourceItem as TreeViewItem)?.ClearSelectedItems();
itemsParent.ClearSelectedItems();
var selectDroppedItems = dropInfo.VisualTarget is TabControl || (dropInfo.VisualTarget != null && DragDrop.GetSelectDroppedItems(dropInfo.VisualTarget));
if (selectDroppedItems)
{
foreach (var item in items)
{
if (applyTemplate)
{
// call ApplyTemplate for TabItem in TabControl to avoid this error:
//
// System.Windows.Data Error: 4 : Cannot find source for binding with reference
var container = itemsParent.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
container?.ApplyTemplate();
}
itemsParent.SetItemSelected(item, true);
}
if (focusVisualTarget)
{
itemsControl.Focus();
}
}
}
}
/// <summary>
/// Determines whether the data of the drag drop action should be copied otherwise moved.
/// </summary>
/// <param name="dropInfo">The DropInfo with a valid DragInfo.</param>
public static bool ShouldCopyData(IDropInfo dropInfo)
{
// default should always the move action/effect
if (dropInfo?.DragInfo == null)
{
return false;
}
var copyData = ((dropInfo.DragInfo.DragDropCopyKeyState != default) && dropInfo.KeyStates.HasFlag(dropInfo.DragInfo.DragDropCopyKeyState))
|| dropInfo.DragInfo.DragDropCopyKeyState.HasFlag(DragDropKeyStates.LeftMouseButton);
copyData = copyData
&& dropInfo.DragInfo.SourceItem is not HeaderedContentControl
&& dropInfo.DragInfo.SourceItem is not HeaderedItemsControl
&& dropInfo.DragInfo.SourceItem is not ListBoxItem;
return copyData;
}
protected static int GetInsertIndex(IDropInfo dropInfo)
{
var insertIndex = dropInfo.UnfilteredInsertIndex;
if (dropInfo.VisualTarget is ItemsControl itemsControl)
{
if (itemsControl.Items is IEditableCollectionView editableItems)
{
var newItemPlaceholderPosition = editableItems.NewItemPlaceholderPosition;
if (newItemPlaceholderPosition == NewItemPlaceholderPosition.AtBeginning && insertIndex == 0)
{
++insertIndex;
}
else if (newItemPlaceholderPosition == NewItemPlaceholderPosition.AtEnd && insertIndex == itemsControl.Items.Count)
{
--insertIndex;
}
}
}
return insertIndex;
}
protected static void Move(IList list, int sourceIndex, int destinationIndex)
{
if (!list.IsObservableCollection())
{
throw new ArgumentException("ObservableCollection<T> was expected", nameof(list));
}
if (sourceIndex != destinationIndex)
{
var method = list.GetType().GetMethod("Move", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
_ = method?.Invoke(list, new object[] { sourceIndex, destinationIndex });
}
}
protected static bool IsChildOf(UIElement targetItem, UIElement sourceItem)
{
var parent = ItemsControl.ItemsControlFromItemContainer(targetItem);
while (parent != null)
{
if (parent == sourceItem)
{
return true;
}
parent = ItemsControl.ItemsControlFromItemContainer(parent);
}
return false;
}
protected static bool TestCompatibleTypes(IEnumerable target, object data)
{
bool InterfaceFilter(Type t, object o) => (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));
var enumerableInterfaces = target.GetType().FindInterfaces(InterfaceFilter, null);
var enumerableTypes = from i in enumerableInterfaces
select i.GetGenericArguments().Single();
if (enumerableTypes.Any())
{
var dataType = TypeUtilities.GetCommonBaseClass(ExtractData(data));
return enumerableTypes.Any(t => t.IsAssignableFrom(dataType));
}
else
{
return target is IList or ICollectionView;
}
}
#if !NETCOREAPP3_1_OR_GREATER
/// <inheritdoc />
public void DragEnter(IDropInfo dropInfo)
{
// nothing here
}
#endif
/// <inheritdoc />
public virtual void DragOver(IDropInfo dropInfo)
{
if (CanAcceptData(dropInfo))
{
var copyData = ShouldCopyData(dropInfo);
var sourceList = dropInfo.DragInfo.SourceCollection.TryGetList();
var destinationList = dropInfo.TargetCollection.TryGetList();
var isSameCollection = sourceList.IsSameObservableCollection(destinationList);
if (isSameCollection)
dropInfo.Effects = DragDropEffects.Move;
else
dropInfo.Effects = copyData ? DragDropEffects.Move : DragDropEffects.Copy;
var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem;
dropInfo.DropTargetAdorner = isTreeViewItem ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert;
//var copyData = ShouldCopyData(dropInfo);
//dropInfo.Effects = copyData ? DragDropEffects.Move : DragDropEffects.Copy;
//var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem;
//dropInfo.DropTargetAdorner = isTreeViewItem ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert;
}
}
#if !NETCOREAPP3_1_OR_GREATER
/// <inheritdoc />
public void DragLeave(IDropInfo dropInfo)
{
// nothing here
}
#endif
/// <inheritdoc />
public virtual void Drop(IDropInfo dropInfo)
{
if (dropInfo?.DragInfo == null)
{
return;
}
var insertIndex = GetInsertIndex(dropInfo);
var destinationList = dropInfo.TargetCollection.TryGetList();
var data = ExtractData(dropInfo.Data).OfType<object>().ToList();
bool isSameCollection = false;
var sourceList = dropInfo.DragInfo.SourceCollection.TryGetList();
isSameCollection = sourceList.IsSameObservableCollection(destinationList);
#if false
var copyData = ShouldCopyData(dropInfo);
if (!copyData)
{
var sourceList = dropInfo.DragInfo.SourceCollection.TryGetList();
if (sourceList != null)
{
isSameCollection = sourceList.IsSameObservableCollection(destinationList);
if (!isSameCollection)
{
foreach (var o in data)
{
var index = sourceList.IndexOf(o);
if (index != -1)
{
sourceList.RemoveAt(index);
// If source is destination too fix the insertion index
if (destinationList != null && ReferenceEquals(sourceList, destinationList) && index < insertIndex)
{
--insertIndex;
}
}
}
}
}
}
#endif
if (destinationList != null)
{
var objects2Insert = new List<object>();
// check for cloning
var cloneData = dropInfo.Effects.HasFlag(DragDropEffects.Copy) || dropInfo.Effects.HasFlag(DragDropEffects.Link);
foreach (var o in data)
{
var obj2Insert = o;
if (cloneData)
{
if (o is ICloneableDragItem cloneableItem)
{
obj2Insert = cloneableItem.CloneItem(dropInfo);
}
else if (o is ICloneable cloneable)
{
obj2Insert = cloneable.Clone();
}
}
objects2Insert.Add(obj2Insert);
if (!cloneData && isSameCollection)
{
var index = destinationList.IndexOf(o);
if (index != -1)
{
if (insertIndex > index)
{
insertIndex--;
}
Move(destinationList, index, insertIndex++);
}
}
else
{
destinationList.Insert(insertIndex++, obj2Insert);
}
if (obj2Insert is IDragItemSource dragItemSource)
{
dragItemSource.ItemDropped(dropInfo);
}
}
SelectDroppedItems(dropInfo, objects2Insert);
}
}
}
#else
public void DragEnter(IDropInfo dropInfo)
{
}
public void DragOver(IDropInfo dropInfo)
{
var itemsouce = dropInfo.Data as Student;
if (itemsouce != null)
{
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
dropInfo.Effects = DragDropEffects.Copy;
}
}
public void DragLeave(IDropInfo dropInfo)
{
}
public void Drop(IDropInfo dropInfo)
{
var sourceitem = dropInfo.Data as Student;
var targetitem = dropInfo.TargetItem as ObservableCollection<Student>;
targetitem.Add(sourceitem);
}
}
#endif
2、DropHandler实现删除
只需更改DragOver与Drop逻辑
示例代码:
public virtual void DragOver(IDropInfo dropInfo)
{
if (CanAcceptData(dropInfo))
{
var sourceControl = dropInfo.DragInfo.VisualSource;
var candelete = (bool)sourceControl.GetValue(Attach.DragDropAttach.CanDeleteProperty);
if (candelete)
dropInfo.Effects = DragDropEffects.Move;
else
dropInfo.Effects = DragDropEffects.None;
var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem;
dropInfo.DropTargetAdorner = isTreeViewItem ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert;
}
}
public virtual void Drop(IDropInfo dropInfo)
{
if (dropInfo?.DragInfo == null)
{
return;
}
var data = ExtractData(dropInfo.Data).OfType<object>().ToList();
var sourceList = dropInfo.DragInfo.SourceCollection.TryGetList();
if (dropInfo.Effects.HasFlag(DragDropEffects.Move))
{
foreach (var o in data)
{
var index = sourceList.IndexOf(o);
if (index != -1)
{
sourceList.RemoveAt(index);
}
}
}
}
3、Xaml示例代码
<Window.DataContext>
<vm:MainWinViewModelcs />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid>
<GroupBox Width="NaN"
Background="LightBlue"
FontSize="20"
FontStyle="Italic"
FontWeight="ExtraBlack"
Header="源区">
<ItemsControl Margin="5"
attach:DragDropAttach.CanDelete="False"
d:ItemsSource="{d:SampleData ItemCount=3}"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="False"
dd:DragDrop.UseDefaultDragAdorner="True"
Background="White"
FontFamily="{Binding ElementName=listbox, Path=SelectedItem}"
ItemsSource="{Binding Students}">
<dd:DragDrop.EffectMoveAdornerTemplate>
<DataTemplate>
<Border BorderBrush="Blue" BorderThickness="2">
<TextBlock Text="移动到这" />
</Border>
</DataTemplate>
</dd:DragDrop.EffectMoveAdornerTemplate>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type model:Student}">
<Border BorderBrush="Black" BorderThickness="3">
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</GroupBox>
</Grid>
<GroupBox Grid.Column="1"
Background="LightGreen"
FontSize="20"
FontStretch="UltraExpanded"
FontWeight="ExtraBlack"
Header="目标区">
<ListBox Margin="5"
attach:DragDropAttach.CanDelete="True"
d:ItemsSource="{d:SampleData ItemCount=4}"
dd:DragDrop.DropHandler="{Binding CopyDropHandler}"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.UseDefaultDragAdorner="True"
ItemsSource="{Binding StudentsTar}"
SelectedIndex="{Binding SelectIndex}"
SelectedItem="{Binding SelectStu}">
<dd:DragDrop.EffectMoveAdornerTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock FontSize="20"
Foreground="Black"
Text="移动到这" />
</Border>
</DataTemplate>
</dd:DragDrop.EffectMoveAdornerTemplate>
<ListBox.Resources>
<depend:MyProxy x:Key="myproxy" DataContext="{Binding}" />
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type model:Student}">
<Border BorderBrush="Black" BorderThickness="3">
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding Source={StaticResource myproxy}}">
<MenuItem Command="{Binding DataContext.CopyItemCmd}" Header="复制" />
<MenuItem Command="{Binding DataContext.DeleteCmd}" Header="删除" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</GroupBox>
<GroupBox Grid.Column="2"
Background="LightGray"
FontSize="20"
FontWeight="ExtraBlack"
Header="字体选择">
<StackPanel>
<ListBox x:Name="listbox"
Height="300"
FontSize="20"
FontWeight="DemiBold" />
<TextBox x:Name="tbox"
Height="30"
Text="@@@@@@"
TextDecorations="Underline" />
<ItemsControl Width="150"
Height="80"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
dd:DragDrop.DropHandler="{Binding DeleteDropHandler}"
dd:DragDrop.IsDropTarget="True"
Background="LightGreen">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<Border Width="NaN"
BorderBrush="Red"
BorderThickness="5">
<StackPanel>
<TextBlock Height="40"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="30"
FontWeight="Heavy"
Foreground="Red"
Text="垃圾箱" />
<TextBlock Height="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
FontWeight="ExtraLight"
Foreground="Red"
Text="垃圾往这扔" />
</StackPanel>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ToolTip>
<TextBlock Text="放进这里删除" />
</ItemsControl.ToolTip>
</ItemsControl>
</StackPanel>
</GroupBox>
</Grid>
注意:示例代码中使用了菜单项,菜单项无法直接实现命令绑定:
原因:由于菜单项属于控件细节,存在于视觉树中,逻辑树中看不到,无法找到逻辑树中的DataContext上下文资源,所以绑定失败。
解决方法:使用代理方式,将细节控件中的DataContext绑定到逻辑树中控件的DataContext,这样就能找到逻辑树中的DataContext资源了。
4、业务逻辑示例代码
internal class MainWinViewModelcs:BindableBase
{
private int _selectIndex;
public int SelectIndex
{
get => _selectIndex;
set => SetProperty(ref _selectIndex, value);
}
private Student _selectStu;
public Student SelectStu
{
get => _selectStu;
set => SetProperty(ref _selectStu, value);
}
private ObservableCollection<Student> _students;
public ObservableCollection<Student> Students
{
get => _students;
set => SetProperty(ref _students, value);
}
private ObservableCollection<Student> _studentsTar;
public ObservableCollection<Student> StudentsTar
{
get => _studentsTar;
set => SetProperty(ref _studentsTar, value);
}
public DelegateCommand DeleteCmd { get; set; }
public DelegateCommand CopyItemCmd { get; set; }
/// <summary>
/// 移除选中项
/// </summary>
public void Delete()
{
StudentsTar.RemoveAt(SelectIndex);
}
/// <summary>
/// 复制选中项
/// </summary>
public void CopyItem()
{
StudentsTar.Add(SelectStu.Clone() as Student);
}
/// <summary>
/// 投下复制Handler
/// </summary>
public CopyDropHandler CopyDropHandler { get; set; }
/// <summary>
/// 投下删除Handler
/// </summary>
public DeleteDropHandler DeleteDropHandler { get; set; }
public MainWinViewModelcs()
{
DeleteDropHandler = new DeleteDropHandler();
CopyDropHandler = new CopyDropHandler();
StudentsTar = new ObservableCollection<Student>();
CopyItemCmd = new DelegateCommand(CopyItem);
DeleteCmd = new DelegateCommand(Delete);
Students = new ObservableCollection<Student>() {
new Student(){ Id=1,Name="Auston1"},
new Student(){ Id=2,Name="Auston2"},
new Student(){ Id=3,Name="Auston3"},
new Student(){ Id=4,Name="Auston4"},
};
}
}
5、效果图
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)