DragDrop鼠标拖动跟随

  

从此图很容易看出来,本程序主要实现的是鼠标Drag时 源跟随鼠标移动,这样更直观方便的让操作者清楚自己所操控的数据

DragDropAdoorner.cs

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));
                    Rect rect = new Rect(pos.X, pos.Y, 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);
    }
}

Data.cs

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;
    }
}

窗口后台代码

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace DragDrop
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            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;
        }
    }
}

UI

<Window x:Class="DragDrop.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DragDrop"
    Title="Window1" Height="400" Width="500">
    <Window.Resources>
        <DataTemplate x:Key="listBoxTemplate" DataType="{x:Type local:DataItem}">
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>
        <HierarchicalDataTemplate x:Key="treeViewTemplate" DataType="{x:Type local: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 local:Data.Instance}, Path=ListBoxItems}" ItemTemplate="{StaticResource listBoxTemplate}"/>
        <TreeView x:Name="mTreeView" Grid.Column="2" ItemsSource="{Binding Source={x:Static local:Data.Instance}, Path=TreeViewItems}" ItemTemplate="{StaticResource treeViewTemplate}"
                  AllowDrop="True" DragDrop.DragOver="OnDragOver" DragDrop.Drop="OnDrop"/>
    </Grid>
</Window>

 

转载于:https://www.cnblogs.com/sai777/p/4077841.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值