滚动时禁用拖放 [英] Disable drag and drop when scrolling
问题描述
我已经实现拖放在WPF一个TreeView拖放功能。
一切工作正常,但是当在树状视图显示在滚动,如果我选择一个项目在树中,然后,尝试滚动(垂直或水平)在TreeView试图执行拖放操作。
有人能帮助我吗?这里是源代码:
类TreeViewRearranger
{
私人的TreeView mTreeView;
私人INT MOVE_TOLERANCE = 10;
私人树型视图mDraggedItem = NULL;
私人树型视图mTargetDrop = NULL;
私人DropAdorner mDropAdorner = NULL;
公共无效初始化(TreeView控件TreeView控件)
{
mTreeView =树视图;
SetupDragDropEvents();
}
私人无效SetupDragDropEvents()
{
mTreeView.MouseDown + = mTreeView_MouseDown;
mTreeView.MouseMove + = mTreeView_MouseMove;
mTreeView.DragOver + = mTreeView_DragOver;
mTreeView.Drop + = mTreeView_Drop;
mTreeView.DragEnter + = mTreeView_DragEnter;
mTreeView.DragLeave + = mTreeView_DragLeave;
}
无效mTreeView_MouseDown(对象发件人,MouseButtonEventArgs E)
{
如果(e.ChangedButton = MouseButton.Left!)
的回报;
mLastMouseDown = e.GetPosition(mTreeView);
}
无效mTreeView_MouseMove(对象发件人,MouseEventArgs E)
{
如果(e.LeftButton = MouseButtonState.Pressed!)
的回报;
点currentPosition = e.GetPosition(mTreeView);
如果((Math.Abs(currentPosition.X - mLastMouseDown.X)下; = MOVE_TOLERANCE)及&放大器;
(Math.Abs(currentPosition.Y - mLastMouseDown.Y)下= MOVE_TOLERANCE))
的回报;
的startDrag();
}
无效mTreeView_DragLeave(对象发件人,DragEventArgs E)
{
RemoveAdorners();
}
无效mTreeView_DragEnter(对象发件人,DragEventArgs E)
{
AdornerLayer层= AdornerLayer.GetAdornerLayer(mTreeView);
mDropAdorner =新DropAdorner(mTreeView);
layer.Add(mDropAdorner);
}
私人点mLastMouseDown;
私人无效的startDrag()
{
mDraggedItem = mTreeView.SelectedItem为树型视图;
如果(mDraggedItem == NULL)回报;
DragDropEffects finalDropEffect =
DragDrop.DoDragDrop(
mTreeView,mTreeView.SelectedValue,DragDropEffects.Move);
//检查目标不为空并且产品
//拖动(移动)
如果((finalDropEffect!= DragDropEffects.Move)||( mTargetDrop == NULL))
的回报;
// A将下降被接受
如果(mDraggedItem.Header.ToString()等于(mTargetDrop.Header.ToString()))
的回报;
PerformDragDrop(mDraggedItem,mTargetDrop);
mTargetDrop = NULL;
mDraggedItem = NULL;
}
私人无效PerformDragDrop(树型视图源,树型视图目标)
{
如果(来源== NULL ||目的地== NULL)
返回;
OnRearrange(源,目的);
}
私有静态树型视图GetParentTreeViewItem(DependencyObject的项目)
{
如果(项目== NULL)
返回NULL;
的DependencyObject父= VisualTreeHelper.GetParent(项目);
树型视图parentTreeViewItem =父为树型视图;
返回parentTreeViewItem? GetParentTreeViewItem(父);
}
私人无效OnRearrange(树型视图源,树型视图目标)
{
如果(来源== NULL ||目的地== NULL)
返回;
树节点sourceNode = source.Tag作为树节点;
树节点destinationNode = destination.Tag作为树节点;
树节点targetNode = destinationNode;
如果
{
树型视图parentItem = GetParentTreeViewItem(目标)(destination.IsExpanded || destination.Items.Count == 0!);
如果(parentItem == NULL)
{
targetNode = mTreeView.Tag作为树节点;
}
,否则
{
targetNode = parentItem.Tag作为树节点;
}
}
INT指数= targetNode.Children.IndexOf(destinationNode)+ 1; //索引
}
无效mTreeView_DragOver(对象发件人,DragEventArgs E)
{
进行了重新排列,从sourceNode到targetNode
点currentPosition = e.GetPosition(mTreeView);
如果((Math.Abs(currentPosition.X - mLastMouseDown.X)下; = MOVE_TOLERANCE)及&放大器;
(Math.Abs(currentPosition.Y - mLastMouseDown.Y)下= MOVE_TOLERANCE))
的回报;
//确认这是一个有效的下拉,然后储存放置目标
树型视图项= GetNearestContainer(e.OriginalSource为的UIElement);
如果(CheckDropTarget(mDraggedItem,项目))
{
e.Effects = DragDropEffects.Move;
UpdateDropAdorner(项目);
}
,否则
{
e.Effects = DragDropEffects.None;
UpdateDropAdorner(NULL);
}
e.Handled = TRUE;
}
无效mTreeView_Drop(对象发件人,DragEventArgs E)
{
e.Effects = DragDropEffects.None;
e.Handled = TRUE;
//确认这是一个有效的下拉,然后储存放置目标
树型视图targetItem = GetNearestContainer
(e.OriginalSource为的UIElement);
如果(targetItem == NULL || mDraggedItem == NULL)
的回报;
mTargetDrop = targetItem;
e.Effects = DragDropEffects.Move;
UpdateDropAdorner(mTargetDrop);
RemoveAdorners();
}
私人无效UpdateDropAdorner(树型视图targetItem)
{
mDropAdorner.UpdateTargetPosition(targetItem);
}
私人树型视图GetNearestContainer(的UIElement元素)
{
//行走了元素树到最近的树视图项。
的TreeViewItem容器=元素树型视图;
,而((容器== NULL)及和放大器;!(元= NULL))
{
元素= VisualTreeHelper.GetParent(元素)作为的UIElement;
容器=元素树型视图;
}
返回容器中;
}
私人布尔CheckDropTarget(树型视图sourceItem,树型视图targetItem)
{
如果(sourceItem == NULL || targetItem == NULL)
返回假;
如果(sourceItem.Header.ToString()等于(targetItem.Header.ToString()))
返回FALSE;
如果(targetItem.IsDescendantOf(sourceItem))
返回false;
返回真;
}
私人无效RemoveAdorners()
{
AdornerLayer层= AdornerLayer.GetAdornerLayer(mTreeView);
layer.Remove(mDropAdorner);
mDropAdorner = NULL;
}
}
您可能有自己附加到scrollviewers ScrollChanged事件并在触发该事件禁用拖放。我还没有尝试过,但我认为,这可能是一个起点,试图
的ScrollViewer的ScrollViewer = GetVisualChild<的ScrollViewer>( mTreeView);
scrollViewer.ScrollChanged + =新ScrollChangedEventHandler(ScrollViewer中
I have implemented drag and drop functionality for a TreeView in WPF.
All works fine but when the scrolls are shown in the tree view, if I select an item in the tree and then and try to scroll (vertical or horizontal) the TreeView tries to perform a drag drop operation.
Somebody can help me? Here is the source code:
class TreeViewRearranger
{
private TreeView mTreeView;
private int MOVE_TOLERANCE = 10;
private TreeViewItem mDraggedItem = null;
private TreeViewItem mTargetDrop = null;
private DropAdorner mDropAdorner = null;
public void Initialize(TreeView treeView)
{
mTreeView = treeView;
SetupDragDropEvents();
}
private void SetupDragDropEvents()
{
mTreeView.MouseDown += mTreeView_MouseDown;
mTreeView.MouseMove += mTreeView_MouseMove;
mTreeView.DragOver += mTreeView_DragOver;
mTreeView.Drop += mTreeView_Drop;
mTreeView.DragEnter += mTreeView_DragEnter;
mTreeView.DragLeave += mTreeView_DragLeave;
}
void mTreeView_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left)
return;
mLastMouseDown = e.GetPosition(mTreeView);
}
void mTreeView_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
return;
Point currentPosition = e.GetPosition(mTreeView);
if ((Math.Abs(currentPosition.X - mLastMouseDown.X) <= MOVE_TOLERANCE) &&
(Math.Abs(currentPosition.Y - mLastMouseDown.Y) <= MOVE_TOLERANCE))
return;
StartDrag();
}
void mTreeView_DragLeave(object sender, DragEventArgs e)
{
RemoveAdorners();
}
void mTreeView_DragEnter(object sender, DragEventArgs e)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(mTreeView);
mDropAdorner = new DropAdorner(mTreeView);
layer.Add(mDropAdorner);
}
private Point mLastMouseDown;
private void StartDrag()
{
mDraggedItem = mTreeView.SelectedItem as TreeViewItem;
if (mDraggedItem == null) return;
DragDropEffects finalDropEffect =
DragDrop.DoDragDrop(
mTreeView, mTreeView.SelectedValue, DragDropEffects.Move);
// Check that target is not null and item is
// dragging(moving)
if ((finalDropEffect != DragDropEffects.Move) || (mTargetDrop == null))
return;
// A Move drop was accepted
if (mDraggedItem.Header.ToString().Equals(mTargetDrop.Header.ToString()))
return;
PerformDragDrop(mDraggedItem, mTargetDrop);
mTargetDrop = null;
mDraggedItem = null;
}
private void PerformDragDrop(TreeViewItem source, TreeViewItem destination)
{
if (source == null || destination == null)
return;
OnRearrange(source, destination);
}
private static TreeViewItem GetParentTreeViewItem(DependencyObject item)
{
if (item == null)
return null;
DependencyObject parent = VisualTreeHelper.GetParent(item);
TreeViewItem parentTreeViewItem = parent as TreeViewItem;
return parentTreeViewItem ?? GetParentTreeViewItem(parent);
}
private void OnRearrange(TreeViewItem source, TreeViewItem destination)
{
if (source == null || destination == null)
return;
TreeNode sourceNode = source.Tag as TreeNode;
TreeNode destinationNode = destination.Tag as TreeNode;
TreeNode targetNode = destinationNode;
if (!destination.IsExpanded || destination.Items.Count == 0)
{
TreeViewItem parentItem = GetParentTreeViewItem(destination);
if (parentItem == null)
{
targetNode = mTreeView.Tag as TreeNode;
}
else
{
targetNode = parentItem.Tag as TreeNode;
}
}
int index = targetNode.Children.IndexOf(destinationNode) + 1;
// performed a rearrange from sourceNode to targetNode at index
}
void mTreeView_DragOver(object sender, DragEventArgs e)
{
Point currentPosition = e.GetPosition(mTreeView);
if ((Math.Abs(currentPosition.X - mLastMouseDown.X) <= MOVE_TOLERANCE) &&
(Math.Abs(currentPosition.Y - mLastMouseDown.Y) <= MOVE_TOLERANCE))
return;
// Verify that this is a valid drop and then store the drop target
TreeViewItem item = GetNearestContainer(e.OriginalSource as UIElement);
if (CheckDropTarget(mDraggedItem, item))
{
e.Effects = DragDropEffects.Move;
UpdateDropAdorner(item);
}
else
{
e.Effects = DragDropEffects.None;
UpdateDropAdorner(null);
}
e.Handled = true;
}
void mTreeView_Drop(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
e.Handled = true;
// Verify that this is a valid drop and then store the drop target
TreeViewItem targetItem = GetNearestContainer
(e.OriginalSource as UIElement);
if (targetItem == null || mDraggedItem == null)
return;
mTargetDrop = targetItem;
e.Effects = DragDropEffects.Move;
UpdateDropAdorner(mTargetDrop);
RemoveAdorners();
}
private void UpdateDropAdorner(TreeViewItem targetItem)
{
mDropAdorner.UpdateTargetPosition(targetItem);
}
private TreeViewItem GetNearestContainer(UIElement element)
{
// Walk up the element tree to the nearest tree view item.
TreeViewItem container = element as TreeViewItem;
while ((container == null) && (element != null))
{
element = VisualTreeHelper.GetParent(element) as UIElement;
container = element as TreeViewItem;
}
return container;
}
private bool CheckDropTarget(TreeViewItem sourceItem, TreeViewItem targetItem)
{
if (sourceItem == null || targetItem == null)
return false;
if (sourceItem.Header.ToString().Equals(targetItem.Header.ToString()))
return false;
if (targetItem.IsDescendantOf(sourceItem))
return false;
return true;
}
private void RemoveAdorners()
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(mTreeView);
layer.Remove(mDropAdorner);
mDropAdorner = null;
}
}
You may have to attach yourself to the scrollviewers ScrollChanged event and when that event is triggered you disable drag and drop. I haven't tried it but I think that it might be a starting place to try
ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(mTreeView);
scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer
这篇关于滚动时禁用拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!