• 重写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
Copyright © 2020-2023  润新知