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