重写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; } } }
分类: WP7-迹`@柳燕
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于重写SurfaceListBox 完善DragDrop的详细内容...