拖拽和滚动(WPF)

3

好的,大家好,我一直在为这个问题苦苦思索,已经花费了数小时来研究它的工作原理,但是我还没有找到答案。

基本上,我遇到的问题是我的应用程序中有一个文件夹的树形视图,例如:

Catalog

  Brands
    Nike
    Adidas
    Lactose


  Styles
    Sandles
    Trainers
    Boots

我试图解决的问题是,当我拖动文件夹时(这由我的DragDropManager类处理),我无法上下滚动(只会显示一个美丽的停止标志)。
如果要将某物从顶部移动到底部,则会出现问题。
单独进行滚动时,滚动正常工作。
如果有人想查看我的代码的任何部分,请随时提问,因为我不确定实际上应该向你们展示什么。
我已经阅读了很多文章,但只会让我感到困惑。
1个回答

2

也许有更好的方法,但我所做的是:

  • 在拖动到目标元素上方时(QueryContinueDrag),检查您正在其上方的控件是否在其可视树中具有滚动查看器。

  • 现在检查您是否靠近滚动查看器的边缘,例如离10像素。

  • 滚动滚动查看器

以下是一些代码:

查找相关的ScrollViewer:

var _scrollViewerControl = FindVisualChild<ScrollViewer>(treeView);

private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
  for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
  {
    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
    if (child != null && child is childItem)
      return (childItem)child;
    else
    {
      childItem childOfChild = FindVisualChild<childItem>(child);
      if (childOfChild != null)
        return childOfChild;
    }
  }
  return null;
}

在 QueryContinueDrag 中确定当前位置和滚动视图的增量:
// as we don't have eventargs here exposing the current mouse position we use the
// win32 API to get the current mouse position
Win32.POINT p;
if (!Win32.GetCursorPos(out p))
{
    return;
}

//this is the point on the screen
Point point = new Point(p.X, p.Y);

//get position relative to scrollViewerControl
Point controlPoint = _scrollViewerControl.PointFromScreen(point);

if (controlPoint.Y < 10 && -10 < controlPoint.Y)
{
    _scrollViewerControl.LineUp();
}
else if (controlPoint.Y > _scrollViewerControl.ViewportHeight - 10 && _scrollViewerControl.ViewportHeight + 10 > controlPoint.Y)
{
    _scrollViewerControl.LineDown();
}

if (controlPoint.X < 10 && -10 < controlPoint.X)
{
    _scrollViewerControl.LineLeft();
}
else if (controlPoint.X > _scrollViewerControl.ViewportWidth - 10 && _scrollViewerControl.ViewportWidth + 10 > controlPoint.X)
{
    _scrollViewerControl.LineRight();
}

这听起来很蠢,但我该如何实现呢?我应该在DragDropManager类中完成吗? - Hello World
我不知道你的DragDropManager类实现是什么样子的,但我已经在那里实现了它。我猜你已经在那里有一些事件钩子,并且你知道拖放操作的细节。例如,谁开始了拖动操作。最好你在问题中展示一小部分你的实现,这样我们可以更好地了解。 - SvenG
好的,关于你之前的回答,我其实不知道滚动视图在哪里,因为我相当确定TreeView模板已经内置了它,因为据我所见,没有任何东西在初始化滚动条。 - Hello World
是的,这是真的,ScrollViewer是TreeView控件模板的一部分。这就是为什么你需要使用FindVisualChild方法。如果你正在拖动一个带有ScrollViewer的控件,比如TreeView,你需要调用FindVisualChild(TreeView treeViewControlYouareCurrentlyOver)方法,然后你可以使用第二个代码片段来确定当前点和ScrollViewer之间的距离。 - SvenG
哦,我明白了,我想我现在理解了。我以前没有接触过VisualChild的东西,再次感谢。 - Hello World

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接