重写SurfaceListBox 完善DragDrop

刚才不小心睡着了一会,一醒,看到现在都是五点多了,头脑有点不清醒,就不继续coding了,整理一下今天修改的东西,重写SurfaceListBox的DragDrop

本次重写指在完善一下功能(如图所示):

  1,从下面的数据列表拖动数据到上面的列表中

  2,拖动下面的数据时,只有图片能拖进去,其他类型的会直接显示出来

  3,在拖进图片时,如果有别的元素遮挡,那么也是显示出图片而不是拖入(问题出现,标记为A)

  4,在界面显示的时候,除了图片以外,别的类型不能拖入,并保持拖入时其他元素的状态(问题标记为B)

下面介绍一下会出现的问题:

  A,在wpf中,Microsoft.Surface.Presentation.SurfaceDragDrop的事件,即使在你注册监听事件的元素上面还有元素遮挡,这个事件依旧会触发,触发的后果就是,你没有把元素添加进去,但是,鼠标数据依旧已经在此过程被处理,原因同B

  B,在鼠标数据触发到事件以后,哪怕是(SurfaceDragDrop.PreviewDragEnterEvent),在这个事件之中,鼠标数据的 DragDropEffects会被触发,表现在,这个事件之后数据没了,不相信的话,可以测试,使用代码中的 (thisParent.ItemContainerGenerator.ContainerFromItem(data) as ScatterViewItem),在【SurfaceDragDrop.AddDropHandler(this, OnCursorDrop);】中thisParent已经不包含鼠标数据了

  由于B的原因,我本想多实现一项功能(如果界面已经显示包含下面数据的元素,那么如果再拖拽到上面的列表时把元素移位到拖拽释放的位置,而不是直接屏蔽消息),可是我试了几种想法,都未曾能成功,也就暂时搁置这个功能了

View Code
**
* FileName:  SPListBox.cs
* Version:   1.0
* Date:      2012.05.22
* Author:    Ji
*========================================
* @namespace    Colavia.SPCommonControl
* @class        SPListBox
* @extends      SurfaceListBox
*
* 
*========================================
* Copyright (c) 2012 Colavia
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Surface.Presentation.Controls;
using System.Windows.Media;
using System.Windows;
using Microsoft.Surface.Presentation;
using System.Windows.Input;
using System.Diagnostics;
using Microsoft.Surface.Presentation.Input;
using System.Windows.Controls;
using System.Xml;
using Colavia.SPBaseDataInterface;
using Colavia.SPObjectInterface;
using Colavia.SPCommonControl;

namespace Colavia.SPToolsControl
{
    public class SPListBox : SurfaceListBox
    {
        public SPListBox()
        {
            Background = Brushes.Transparent;
            AllowDrop = true;

            this.Loaded += (s, e) =>
            {
                SurfaceDragDrop.AddDropHandler(this, OnCursorDrop);
            };
            this.Unloaded += (s, e) =>
            {
                SurfaceDragDrop.RemoveDropHandler(this, OnCursorDrop);
            };

            this.AddHandler(SPListBox.TouchDownEvent, new EventHandler<TouchEventArgs>(SPListBox_PreviewTouchDown), true);
            this.AddHandler(SPListBox.TouchUpEvent, new EventHandler<TouchEventArgs>(SPListBox_PreviewTouchUp), true);
            this.AddHandler(SPListBox.TouchMoveEvent, new EventHandler<TouchEventArgs>(SPListBox_PreviewTouchMove), true);

            this.AddHandler(SPListBox.MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnMouseLeftButtonDown), true);
            this.AddHandler(SPListBox.MouseLeftButtonUpEvent, new MouseButtonEventHandler(OnMouseLeftButtonUp), true);
            this.AddHandler(SPListBox.MouseMoveEvent, new MouseEventHandler(OnMouseMove), true);

            this.AddHandler(Microsoft.Surface.Presentation.SurfaceDragDrop.DragCompletedEvent, new System.EventHandler<Microsoft.Surface.Presentation.SurfaceDragCompletedEventArgs>(this.OnListDragCompleted));
            this.AddHandler(Microsoft.Surface.Presentation.SurfaceDragDrop.DragCanceledEvent, new System.EventHandler<Microsoft.Surface.Presentation.SurfaceDragDropEventArgs>(this.OnListDragCanceled));

            this.AddHandler(Microsoft.Surface.Presentation.SurfaceDragDrop.PreviewDragEnterEvent, new System.EventHandler<Microsoft.Surface.Presentation.SurfaceDragDropEventArgs>(this.dragEnterEvent));

        }

        List<string> ImageEndWith = new List<string>() { ".jpg", ".jpeg", ".ico", ".bmp", ".icon", ".gif", ".png" };

        private void dragEnterEvent(object sender, SurfaceDragDropEventArgs e)
        {
            var thisParent = Find<ScatterView>((DependencyObject)this);

            List<int> scatteritem = new List<int>();
            int slider = new int();
            foreach (var scatterViewItem in thisParent.Items)
            {
                var sviItem = thisParent.ItemContainerGenerator.ContainerFromItem(scatterViewItem) as ScatterViewItem;
                var hTest = VisualTreeHelper.HitTest(sviItem, Mouse.GetPosition(sviItem));
                if (hTest != null)
                {
                    var dataContext = (hTest.VisualHit as FrameworkElement).DataContext;

                    if (dataContext != null && e.Cursor.Data != null && e.Cursor.Data != dataContext)
                    {
                        if (dataContext is SPSlideEditor)
                        {
                            slider = sviItem.ZIndex;
                        }
                        else
                        {
                            scatteritem.Add(sviItem.ZIndex);
                        }
                    }
                }
            }
            var abri = scatteritem.FirstOrDefault(i => i > slider);

            SurfaceDragCursor droppingCursor = e.Cursor;
            if (droppingCursor.Data is SPObjectData || droppingCursor.Data is SPObjectBase)
            {
                if (this.Items.Count < MaxCount)
                {
                    var objPlugin = (droppingCursor.Data as SPObjectData) != null ? (droppingCursor.Data as SPObjectData).Object : droppingCursor.Data as SPObjectBase;

                    if (objPlugin != null)
                    {
                        if (objPlugin.ClipUri != null)
                        {
                            //如果当前场景中已经存在,即已经是ScatterViewItem项
                            if (thisParent.Items.Contains(droppingCursor.Data as SPObjectData))
                            {
                                // var o = (thisParent.ItemContainerGenerator.ContainerFromItem(droppingCursor.Data as SPObjectData) as ScatterViewItem);
                                var endJudge = ImageEndWith.FirstOrDefault(i => objPlugin.ClipUri.EndsWith(i));
                                if (endJudge == null)
                                {
                                    e.Handled = true;
                                    e.Effects = DragDropEffects.None;
                                    return;
                                }
                            }
                        }
                        //选项是从下面的轨道拖出
                        //移交给OnCursorDrop处理元素添加的位置
                        return;
                    }
                }
                else
                {
                    string str = string.Format("已经达到最大添加{0}数目,请删除后添加", MaxCount);
                    SPSplashControl.Show(str);
                }
            }

            e.Handled = true;
            e.Effects = DragDropEffects.None;
        }

        #region this.Event

        private const int DragThreshold = 15;
        private List<InputDevice> ignoredDeviceList = new List<InputDevice>();

        private void OnListDragCanceled(object sender, SurfaceDragDropEventArgs e)
        {
            var draggingData = e.Cursor.Data;
            if (draggingData != null && Items.Contains(draggingData))
            {
                ResetListBoxItem(draggingData);
            }
        }

        private void OnListDragCompleted(object sender, SurfaceDragCompletedEventArgs e)
        {
            object draggingData = e.Cursor.Data;
            if (draggingData != null && Items.Contains(draggingData))
            {
                ResetListBoxItem(draggingData);
            }
        }

        //<summary>
        //接受事件--自身处理
        //</summary>
        //<param name="itemData"></param>
        private void ResetListBoxItem(object itemData)
        {

            if (GetDragDelete(this) && self)
            {
                try
                {
                    Items.Remove(itemData);
                }
                catch { }
            }
            else
            {
                SurfaceListBoxItem sourceListBoxItem = null;
                foreach (object item in this.Items)
                {
                    if (item == itemData)
                    {
                        sourceListBoxItem = this.ItemContainerGenerator.ContainerFromItem(item) as SurfaceListBoxItem;
                    }
                }
                if (sourceListBoxItem != null)
                {
                    sourceListBoxItem.Opacity = 1;
                }
            }
            if (!self)
            {
                self = true;
            }
        }

        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ignoredDeviceList.Remove(e.Device);
            InputDeviceHelper.ClearDeviceState(e.Device);
            InputDeviceHelper.InitializeDeviceState(e.Device);
        }

        private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            ignoredDeviceList.Remove(e.MouseDevice);
            InputDeviceHelper.ClearDeviceState(e.Device);
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            AllowDrop = true;
            if (InputDeviceHelper.GetDragSource(e.Device) != null)
            {
                StartDragDrop(this, e);
            }
        }

        private void SPListBox_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            ignoredDeviceList.Remove(e.Device);
            InputDeviceHelper.ClearDeviceState(e.Device);
            InputDeviceHelper.InitializeDeviceState(e.Device);
        }

        private void SPListBox_PreviewTouchUp(object sender, TouchEventArgs e)
        {
            ignoredDeviceList.Remove(e.Device);
            InputDeviceHelper.ClearDeviceState(e.Device);
        }

        private void SPListBox_PreviewTouchMove(object sender, TouchEventArgs e)
        {
            AllowDrop = true;
            if (InputDeviceHelper.GetDragSource(e.Device) != null)
            {
                StartDragDrop(this, e);
            }
        }

        //<summary>
        //拖动事件
        //</summary>
        //<param name="sender"></param>
        //<param name="args"></param>
        private void StartDragDrop(ListBox sourceListBox, InputEventArgs e)
        {
            if (ignoredDeviceList.Contains(e.Device))
            {
                return;
            }
            InputDeviceHelper.InitializeDeviceState(e.Device);
            Vector draggedDelta = InputDeviceHelper.DraggedDelta(e.Device, (UIElement)sourceListBox);
            if (Math.Abs(draggedDelta.Y) > DragThreshold)
            {
                ignoredDeviceList.Add(e.Device);
                return;
            }
            if (Math.Abs(draggedDelta.X) < DragThreshold)
            {
                return;
            }
            ignoredDeviceList.Add(e.Device);
            DependencyObject downSource = InputDeviceHelper.GetDragSource(e.Device);

            SurfaceListBoxItem draggedListBoxItem = GetVisualAncestor<SurfaceListBoxItem>(downSource);
            if (draggedListBoxItem == null)
            {
                return;
            }
            object data = draggedListBoxItem.Content;

            Image image = new Image();
            image.Source = (data as SliderData).Plugin.Icon as ImageSource;

            IEnumerable<InputDevice> devices = null;
            TouchEventArgs touchEventArgs = e as TouchEventArgs;
            if (touchEventArgs != null)
            {
                devices = MergeInputDevices(draggedListBoxItem.TouchesCapturedWithin, e.Device);
            }
            else
            {
                devices = new List<InputDevice>(new InputDevice[] { e.Device });
            }

            IList<SliderData> itemsSource = ItemsSource as IList<SliderData>;


            object dd = new object();
            if ((data as SliderData).ObjectData != null)
            {
                dd = (data as SliderData).ObjectData;
            }
            else
            {
                dd = (data as SliderData).Plugin;
            }

            SurfaceDragCursor cursor = SurfaceDragDrop.BeginDragDrop(this, draggedListBoxItem, image, dd, devices, DragDropEffects.Move);

            itemsSource.Remove(data as SliderData);

            if (cursor == null)
            {
                return;
            }

            InputDeviceHelper.ClearDeviceState(e.Device);
            ignoredDeviceList.Remove(e.Device);

            draggedListBoxItem.Opacity = 0.5;
        }

        private static T GetVisualAncestor<T>(DependencyObject descendent) where T : class
        {
            T ancestor = null;
            DependencyObject scan = descendent;
            ancestor = null;

            while (scan != null && ((ancestor = scan as T) == null))
            {
                scan = VisualTreeHelper.GetParent(scan);
            }

            return ancestor;
        }

        private static IEnumerable<InputDevice> MergeInputDevices(IEnumerable<TouchDevice> existingInputDevices, InputDevice extraInputDevice)
        {
            var result = new List<InputDevice> { extraInputDevice };

            foreach (InputDevice inputDevice in existingInputDevices)
            {
                if (inputDevice != extraInputDevice)
                {
                    result.Add(inputDevice);
                }
            }
            return result;
        }

        private bool self = true;

        //<summary>
        //接受事件
        //</summary>
        //<param name="sender"></param>
        //<param name="args"></param>
        private void OnCursorDrop(object sender, SurfaceDragDropEventArgs args)
        {
            var thisParent = Find<ScatterView>((DependencyObject)this);

            List<int> scatteritem = new List<int>();
            int slider = new int();
            foreach (var scatterViewItem in thisParent.Items)
            {
                var sviItem = thisParent.ItemContainerGenerator.ContainerFromItem(scatterViewItem) as ScatterViewItem;
                var hTest = VisualTreeHelper.HitTest(sviItem, Mouse.GetPosition(sviItem));
                if (hTest != null)
                {
                    var dataContext = (hTest.VisualHit as FrameworkElement).DataContext;

                    if (dataContext != null && args.Cursor.Data != null && args.Cursor.Data != dataContext)
                    {
                        if (dataContext is SPSlideEditor)
                        {
                            slider = sviItem.ZIndex;
                        }
                        else
                        {
                            scatteritem.Add(sviItem.ZIndex);
                        }
                    }
                }
            }
            var abri = scatteritem.FirstOrDefault(i => i > slider);

            SurfaceDragCursor droppingCursor = args.Cursor;
            SPObjectBase objPlugin = null;
            objPlugin = (droppingCursor.Data as SPObjectData) != null ? (droppingCursor.Data as SPObjectData).Object : droppingCursor.Data as SPObjectBase;

            //对于从下面拖拽的元素类型判断
            if (objPlugin != null )
            {
                if (objPlugin.ClipUri != null)
                {
                    var endJudge = ImageEndWith.FirstOrDefault(i => objPlugin.ClipUri.EndsWith(i));
                    if (endJudge == null)
                    {
                        abri = 1;
                    }
                }
                else
                {
                    abri = 2;
                }
            }

            if (abri == 0)
            {
                #region Add into items

                IList<SliderData> itemsSource = ItemsSource as IList<SliderData>;
                SliderData dataDrop = new SliderData();

                if ((droppingCursor.Data is SPObjectData) || droppingCursor.Data is SPObjectBase)
                {

                    if (objPlugin == null)
                    {
                        return;
                    }

                    try
                    {
                        dataDrop = itemsSource.FirstOrDefault(i => i.Plugin == objPlugin);
                        itemsSource.Remove(dataDrop);
                    }
                    catch { }

                    if (dataDrop == null)
                    {
                        dataDrop = new SliderData();
                    }

                    dataDrop.Plugin = objPlugin;
                    dataDrop.ObjectData = (droppingCursor.Data as SPObjectData);
                    if (droppingCursor.CurrentTarget == this)
                    {
                        //if (droppingCursor.DragSource != this)
                        {
                            try
                            {
                                var exsit = itemsSource.FirstOrDefault(i => i.Plugin == dataDrop.Plugin);
                                try
                                {
                                    if (exsit != null)
                                    {
                                        itemsSource.Remove(exsit);
                                    }
                                }
                                catch { }

                                {
                                    var h = VisualTreeHelper.HitTest(this, Mouse.GetPosition(this));
                                    if (h != null)
                                    {
                                        var obj = h.VisualHit;
                                        SurfaceListBoxItem lb = new SurfaceListBoxItem();
                                        itemsSource.Remove(exsit);
                                        if (obj != null)
                                        {
                                            lb = Find<SurfaceListBoxItem>((DependencyObject)obj);

                                            if (lb != null)
                                            {
                                                var mouseIndex = itemsSource.IndexOf(this.ItemContainerGenerator.ItemFromContainer((DependencyObject)lb) as SliderData);
                                                itemsSource.Insert(mouseIndex, dataDrop);
                                            }
                                            else
                                            {
                                                itemsSource.Add(dataDrop);
                                            }
                                            this.ScrollIntoView(dataDrop);
                                        }
                                    }
                                    else
                                    {
                                        if (dataDrop != null)
                                        {
                                            itemsSource.Add(dataDrop);
                                            this.ScrollIntoView(dataDrop);
                                            return;
                                        }
                                    }
                                }
                            }
                            catch { }
                        }
                    }
                }
                else if ((droppingCursor.Data is SliderData))
                {
                    dataDrop = droppingCursor.Data as SliderData;
                    SurfaceListBoxItem sourceListBoxItem = null;
                    foreach (SliderData item in itemsSource)
                    {
                        if (item == dataDrop)
                        {
                            sourceListBoxItem = this.ItemContainerGenerator.ContainerFromItem(item) as SurfaceListBoxItem;
                        }
                    }
                    var h = VisualTreeHelper.HitTest(this, Mouse.GetPosition(this));
                    if (h != null)
                    {
                        var obj = h.VisualHit;
                        SurfaceListBoxItem lb = new SurfaceListBoxItem();
                        if (obj != null)
                        {
                            try
                            {
                                itemsSource.Remove(dataDrop);
                                lb = Find<SurfaceListBoxItem>((DependencyObject)obj);
                                if (lb != null)
                                {
                                    var mouseIndex = itemsSource.IndexOf(this.ItemContainerGenerator.ItemFromContainer((DependencyObject)lb) as SliderData);
                                    if (mouseIndex < 0) mouseIndex = 0;
                                    itemsSource.Insert(mouseIndex, dataDrop);
                                }
                                else
                                {
                                    itemsSource.Add(dataDrop);
                                }
                                this.ScrollIntoView(dataDrop);
                            }
                            catch { }
                        }
                    }
                    self = false;
                }
                #endregion
            }
            else
            {
                var data = droppingCursor.Data as SPObjectData;
                if (data != null)
                {
                    double orientation = (thisParent.ItemContainerGenerator.ContainerFromItem(data) as ScatterViewItem) != null ? (thisParent.ItemContainerGenerator.ContainerFromItem(data) as ScatterViewItem).ActualOrientation : 0;
                    if (thisParent.Items.Contains(data))
                    {
                        thisParent.Items.Remove(data);
                    }
                    thisParent.Items.Add(data);
                    var sviItem = thisParent.ItemContainerGenerator.ContainerFromItem(data) as ScatterViewItem;
                    sviItem.Center = Mouse.GetPosition(thisParent);
                    sviItem.Orientation = orientation;
                }
            }
        }

        #endregion

        #region Public Properties

        public static readonly DependencyProperty DragDeleteProperty = DependencyProperty.Register("DragDelete", typeof(bool), typeof(SPListBox), new PropertyMetadata(true));

        public static bool GetDragDelete(DependencyObject element)
        {
            return (bool)element.GetValue(DragDeleteProperty);
        }

        public static void SetDragDelete(DependencyObject element, bool value)
        {
            element.SetValue(DragDeleteProperty, value);
        }

        public Style DragCursorStyle
        {
            get { return (Style)GetValue(DragCursorStyleProperty); }
            set { SetValue(DragCursorStyleProperty, value); }
        }
        public static readonly DependencyProperty DragCursorStyleProperty =
            DependencyProperty.Register("DragCursorStyle", typeof(Style), typeof(SPListBox), new UIPropertyMetadata(null));


        public int MaxCount
        {
            get { return (int)GetValue(MaxCountProperty); }
            set { SetValue(MaxCountProperty, value); }
        }
        public static readonly DependencyProperty MaxCountProperty =
            DependencyProperty.Register("MaxCount", typeof(int), typeof(SPListBox), new PropertyMetadata(20));


        #endregion

        public T Find<T>(DependencyObject v) where T : DependencyObject
        {
            DependencyObject res = v;
            while (res != null && !(res is T))
            {
                res = VisualTreeHelper.GetParent(res);
            }
            return (T)res;
        }

    }
}
 
原文地址:https://www.cnblogs.com/Leo_wl/p/2682546.html