Прокрутка при перетаскивании (WPF)
Хорошо, ребята, я почесал голову, как сумасшедший по этой проблеме, и потратил несколько часов, пытаясь исследовать, как это работает, но я еще не нашел ответа, если вы хотите, чтобы какой-либо из моих SRC чувствовал себя свободно спросить об этом, и я посмотрю, смогу ли я помочь.
В основном проблема, с которой я сталкиваюсь, заключается в том, что у меня есть TreeView
папок в моем приложении i.e:
Catalog
Brands
Nike
Adidas
Lactose
Styles
Sandles
Trainers
Boots
Проблема, которую я пытаюсь исправить, заключается в том, что когда я перетаскиваю папку (это обрабатывается в классе DragDropManager
), я не могу прокручивать вверх или вниз (просто отображает прекрасный знак остановки). Я также не могу найти скроллер на самом деле в дереве, поэтому я не уверен, как он создается (это не мое собственное программное обеспечение, я недавно начал работать в компании, поэтому я не знаком с кодом, и никто другой похоже, знает.)
Это проблема, если я хочу переместить что-то с самого верхнего на самое нижнее.
Скроллинг работает отлично без перетаскивания.
Если кто-то хочет увидеть какую-либо часть моего кода, не стесняйтесь спрашивать, поскольку я не уверен, что на самом деле показать вам, ребята.
Я прочитал несколько хороших статей и просто оставил царапины на голове.
Ответы
Ответ 1
Я создал прикрепленное свойство для достижения такого поведения, посмотрите мой пост здесь -
Приложенное поведение для автоматической прокрутки контейнеров при выполнении Drag and 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 при перетаскивании
WPF ListView Databound Перетаскивание автоматической прокрутки
WPF Drag-to-scroll работает неправильно
Ответ 2
Я знаю этот вопрос очень старый, но вот 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>