刚才不小心睡着了一会,一醒,看到现在都是五点多了,头脑有点不清醒,就不继续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的原因,我本想多实现一项功能(如果界面已经显示包含下面数据的元素,那么如果再拖拽到上面的列表时把元素移位到拖拽释放的位置,而不是直接屏蔽消息),可是我试了几种想法,都未曾能成功,也就暂时搁置这个功能了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
** * 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; } } }