拖放时滚动(WPF)

rn0zuynd  于 2023-06-07  发布在  其他
关注(0)|答案(3)|浏览(164)

好吧,伙计们,我一直在为这个问题疯狂地挠头,并花了几个小时试图研究它是如何工作的,但我还没有找到答案,如果你想看到我的任何SRC随时询问它,我会看看我是否能提供帮助。
基本上,我遇到的问题是,我有一个TreeView的文件夹在我的应用程序,即:

Catalog

  Brands
    Nike
    Adidas
    Lactose

  Styles
    Sandles
    Trainers
    Boots

我试图解决的问题是,当我拖动一个文件夹时(这是在我的DragDropManager类中处理的),我无法向上或向下滚动(只是显示一个可爱的停止符号)。我也无法在TreeView中找到滚动器,所以我不确定它是如何生成的(这不是我自己的软件,我最近开始为一家公司工作,所以我不熟悉代码,似乎也没有其他人知道。)
这是一个问题,如果我想把东西从最上面移到最下面。
滚动本身工作正常,而不需要拖动。
如果任何人希望看到我的代码的任何部分,请随时询问,因为我不确定实际上要向你们展示什么。
我读了好几篇文章,只是挠头。

bmvo0sr5

bmvo0sr51#

我已经创建了一个附加的属性来实现这个行为,看看我的帖子在这里-
Attached Behavior for auto scrolling containers while doing Drag & Drop
主要逻辑是这样的-

private static void OnContainerPreviewDragOver(object sender, DragEventArgs e)
{
    FrameworkElement container = sender as FrameworkElement;

    if (container == null) { return; }

    ScrollViewer scrollViewer = GetFirstVisualChild<ScrollViewer>(container);

    if (scrollViewer == null) { return; }

    double tolerance = 60;
    double verticalPos = e.GetPosition(container).Y;
    double offset = 20;

    if (verticalPos < tolerance) // Top of visible list? 
    {
        //Scroll up
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - offset);
    }
    else if (verticalPos > container.ActualHeight - tolerance) //Bottom of visible list? 
    {
        //Scroll down
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset);     
    }
}

SO上类似的问题(虽然它们主要针对ListBox/ListView,但也应该适用于TreeView)-
WPF Listbox auto scroll while dragging
WPF ListView Databound Drag/Drop Auto Scroll
WPF Drag-to-scroll doesn't work correctly

u3r8eeie

u3r8eeie2#

我知道这个问题很老了,但这里是MVVM作为附加属性的方式:

using System.Windows;
    using System.Windows.Controls;

    namespace AndroidCtrlUI.XTools.Behaviors
    {
        ///<summary>
        /// TreeItemAttach 
        ///<para/> TreeViewItem
        ///</summary>
        public sealed class TreeItemAttach
        {
            #region BringIntoView

            ///<summary>
            /// DependencyProperty
            ///</summary>
            public static readonly DependencyProperty BringIntoViewProperty = DependencyProperty.RegisterAttached("BringIntoView", typeof(bool), typeof(TreeItemAttach), new UIPropertyMetadata(false, (s, e) =>
            {
                if ((bool)e.NewValue != (bool)e.OldValue && s is TreeViewItem t)
                {
                    if ((bool)e.NewValue)
                    {
                        t.Selected += BringIntoView;
                    }
                    else
                    {
                        t.Selected -= BringIntoView;
                    }
                }
            }));

            ///<summary>
            /// Get
            ///</summary>
            ///<param name="target">DependencyObject</param>
            ///<returns>ICommand</returns>
            public static bool GetBringIntoView(DependencyObject target)
            {
                return (bool)target.GetValue(BringIntoViewProperty);
            }

            ///<summary>
            /// Set
            ///</summary>
            ///<param name="target">DependencyObject</param>
            ///<param name="value">ICommand</param>
            public static void SetBringIntoView(DependencyObject target, bool value)
            {
                target.SetValue(BringIntoViewProperty, value);
            }

            private static void BringIntoView(object sender, RoutedEventArgs e)
            {
                if (e.Source is TreeViewItem s)
                {
                    double h = s.ActualHeight;
                    if (s.IsExpanded && s.Items.Count > 0)
                    {
                        h = s.ActualHeight / TreeWalker(s);
                    }
                    s.BringIntoView(new Rect(0, h * -1, s.ActualWidth, h * 2.5));
                }
            }

            private static long TreeWalker(TreeViewItem item)
            {
                long c = item.Items.Count;
                foreach (object i in item.Items)
                {
                    if (i != null && item.ItemContainerGenerator.ContainerFromItem(i) is TreeViewItem t && t.IsExpanded && t.Items.Count > 0)
                    {
                        c += TreeWalker(t);
                    }
                }
                return c;
            }
            #endregion
        }
    }

它可以像这样使用:

<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
    <Setter Property="tool:TreeItemAttach.BringIntoView" Value="True"/>
</Style>
3htmauhk

3htmauhk3#

基于@akjoshi的回答,但我想要变速,同时像这样下降:

我的PreviewDragOver处理程序是这样的:

private static void container_PreviewDragOver(object sender, DragEventArgs e)
{
    if (!(sender is FrameworkElement container))
        return;

    var scrollViewer = findChildOfType<ScrollViewer>(container);
    if (scrollViewer == null)
        return;

    const double heightOfAutoScrollZone = 25;
    double mouseYRelativeToContainer = e.GetPosition(container).Y;

    if (mouseYRelativeToContainer < heightOfAutoScrollZone)
    {
        double offsetChange = heightOfAutoScrollZone - mouseYRelativeToContainer;
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - offsetChange);
    }
    else if (mouseYRelativeToContainer > container.ActualHeight - heightOfAutoScrollZone)
    {
        double offsetChange = mouseYRelativeToContainer - (container.ActualHeight - heightOfAutoScrollZone);
        scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offsetChange);
    }
}

完整的代码和示例github.

相关问题