wpf 拖拽 且元素跟随
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; namespace DragDrop { public class DragDropAdorner : Adorner { public DragDropAdorner(UIElement parent) : base(parent) { IsHitTestVisible = false; mDraggedElement = parent as FrameworkElement; } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if (mDraggedElement != null) { Win32.POINT screenPos = new Win32.POINT(); if (Win32.GetCursorPos(ref screenPos)) { Point pos = PointFromScreen(new Point(screenPos.X, screenPos.Y)); //Point elementPos = mDraggedElement.PointFromScreen(new Point()); Point elementPos2 = mDraggedElement.PointToScreen(new Point()); Rect rect = new Rect(pos.X - elementPos2.X/2, pos.Y- mDraggedElement.ActualHeight/2, mDraggedElement.ActualWidth, mDraggedElement.ActualHeight); drawingContext.PushOpacity(1.0); Brush highlight = mDraggedElement.TryFindResource(SystemColors.HighlightBrushKey) as Brush; if (highlight != null) drawingContext.DrawRectangle(highlight, new Pen(Brushes.Red, 0), rect); drawingContext.DrawRectangle(new VisualBrush(mDraggedElement), new Pen(Brushes.Transparent, 0), rect); drawingContext.Pop(); } } } FrameworkElement mDraggedElement = null; } public static class Win32 { public struct POINT { public Int32 X; public Int32 Y; } [DllImport("user32.dll")] public static extern bool GetCursorPos(ref POINT point); } }
前端
<Window x:Class="WpfDragExample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfDragExample" xmlns:dragDrop="clr-namespace:DragDrop" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <DataTemplate x:Key="listBoxTemplate" DataType="{x:Type dragDrop:DataItem}"> <TextBlock Text="{Binding Header}"/> </DataTemplate> <HierarchicalDataTemplate x:Key="treeViewTemplate" DataType="{x:Type dragDrop:DataItem}" ItemsSource="{Binding Items}"> <TextBlock Text="{Binding Header}"/> </HierarchicalDataTemplate> </Window.Resources> <Grid x:Name="mTopLevelGrid"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="10"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ListBox x:Name="mListBox" Grid.Column="0" ItemsSource="{Binding Source={x:Static dragDrop:Data.Instance}, Path=ListBoxItems}" ItemTemplate="{StaticResource listBoxTemplate}"/> <TreeView x:Name="mTreeView" Grid.Column="2" ItemsSource="{Binding Source={x:Static dragDrop:Data.Instance}, Path=TreeViewItems}" ItemTemplate="{StaticResource treeViewTemplate}" AllowDrop="True" DragDrop.DragOver="OnDragOver" DragDrop.Drop="OnDrop"/> </Grid> </Window>
后台
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using DragDrop; namespace WpfDragExample { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); AttachEvents(); } private void AttachEvents() { mListBox.PreviewMouseMove += OnPreviewListBoxMouseMove; mListBox.QueryContinueDrag += OnQueryContinueDrag; } private void OnPreviewListBoxMouseMove(object sender, MouseEventArgs e) { if (Mouse.LeftButton != MouseButtonState.Pressed) return; Point pos = e.GetPosition(mListBox); HitTestResult result = VisualTreeHelper.HitTest(mListBox, pos); if (result == null) return; ListBoxItem listBoxItem = Utils.FindVisualParent<ListBoxItem>(result.VisualHit); if (listBoxItem == null || listBoxItem.Content != mListBox.SelectedItem || !(mListBox.SelectedItem is DataItem)) return; DragDropAdorner adorner = new DragDropAdorner(listBoxItem); mAdornerLayer = AdornerLayer.GetAdornerLayer(mTopLevelGrid); mAdornerLayer.Add(adorner); DataItem dataItem = listBoxItem.Content as DataItem; DataObject dataObject = new DataObject(dataItem.Clone()); System.Windows.DragDrop.DoDragDrop(mListBox, dataObject, DragDropEffects.Copy); mStartHoverTime = DateTime.MinValue; mHoveredItem = null; mAdornerLayer.Remove(adorner); mAdornerLayer = null; } private void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e) { mAdornerLayer.Update(); UpdateTreeViewExpandingState(); } private void OnDragOver(object sender, DragEventArgs e) { e.Effects = DragDropEffects.None; Point pos = e.GetPosition(mTreeView); HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos); if (result == null) return; TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit); if (selectedItem != null) selectedItem.IsSelected = true; e.Effects = DragDropEffects.Copy; } private void OnDrop(object sender, DragEventArgs e) { Point pos = e.GetPosition(mTreeView); HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos); if (result == null) return; TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit); if (selectedItem == null) return; DataItem parent = selectedItem.Header as DataItem; DataItem dataItem = e.Data.GetData(typeof(DataItem)) as DataItem; if (parent != null && dataItem != null) parent.Items.Add(dataItem); } private void UpdateTreeViewExpandingState() { Win32.POINT point = new Win32.POINT(); if (Win32.GetCursorPos(ref point)) { Point pos = new Point(point.X, point.Y); pos = mTreeView.PointFromScreen(pos); HitTestResult result = VisualTreeHelper.HitTest(mTreeView, pos); if (result != null) { TreeViewItem selectedItem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit); if (selectedItem != null) { if (mHoveredItem != selectedItem) { mHoveredItem = selectedItem; mStartHoverTime = DateTime.Now; } else { if (mHoveredItem.Items.Count > 0 && !mHoveredItem.IsExpanded && DateTime.Now - mStartHoverTime > TimeSpan.FromSeconds(2)) mHoveredItem.IsExpanded = true; } } } } } DateTime mStartHoverTime = DateTime.MinValue; TreeViewItem mHoveredItem = null; AdornerLayer mAdornerLayer = null; } internal static class Utils { public static T FindVisualParent<T>(DependencyObject obj) where T : class { while (obj != null) { if (obj is T) return obj as T; obj = VisualTreeHelper.GetParent(obj); } return null; } } }
数据
using System; using System.Collections.ObjectModel; namespace DragDrop { class DataItem : ICloneable { public DataItem(string header) { mHeader = header; } public object Clone() { DataItem dataItem = new DataItem(mHeader); foreach (DataItem item in Items) dataItem.Items.Add((DataItem)item.Clone()); return dataItem; } public string Header { get { return mHeader; } } public ObservableCollection<DataItem> Items { get { if (mItems == null) mItems = new ObservableCollection<DataItem>(); return mItems; } } private string mHeader = string.Empty; private ObservableCollection<DataItem> mItems = null; } class Data { private static Data mInstance = new Data(); public static Data Instance { get { return mInstance; } } private ObservableCollection<DataItem> GenerateTreeViewItems() { ObservableCollection<DataItem> items = new ObservableCollection<DataItem>(); DataItem item1 = new DataItem("Item1"); item1.Items.Add(new DataItem("SubItem1")); item1.Items.Add(new DataItem("SubItem2")); item1.Items.Add(new DataItem("SubItem3")); item1.Items.Add(new DataItem("SubItem4")); items.Add(item1); DataItem item2 = new DataItem("Item2"); item2.Items.Add(new DataItem("SubItem1")); item2.Items.Add(new DataItem("SubItem2")); items.Add(item2); return items; } private ObservableCollection<DataItem> GenerateListItems() { ObservableCollection<DataItem> items = new ObservableCollection<DataItem>(); items.Add(new DataItem("Item1")); items.Add(new DataItem("Item2")); items.Add(new DataItem("Item3")); items.Add(new DataItem("Item4")); items.Add(new DataItem("Item5")); return items; } public ObservableCollection<DataItem> TreeViewItems { get { if (mTreeViewItems == null) mTreeViewItems = GenerateTreeViewItems(); return mTreeViewItems; } } public ObservableCollection<DataItem> ListBoxItems { get { if (mListBoxItems == null) mListBoxItems = GenerateListItems(); return mListBoxItems; } } private ObservableCollection<DataItem> mTreeViewItems = null; private ObservableCollection<DataItem> mListBoxItems = null; } }
拷贝的代码 忘了出处了,有知道的告诉我一下 我注明出处
不想平凡,奈何太懒 T_T