Okay guys, I have been scratching my head like mad over this issue and have spent a good few hours trying to research how it works but I am yet to find an answer, if you wish to see any of my SRC feel free to ask about it and I will see if I can help.
Basically the issue I am having is that I have a TreeView
of folders in my application i.e.:
Catalog
Brands
Nike
Adidas
Lactose
Styles
Sandles
Trainers
Boots
The issue that I am trying to fix is that when I drag a folder around (This is handled in my DragDropManager
class), I am unable to scroll up or down(simply displays a lovely stop sign). I am also unable to find a scroller actually within the TreeView, so I am unsure how it is being generated (This is not my own software, I have recently started working for a company so I am not familiar with the code and no one else seems to know.)
This is a problem if I want to move something from the very top to the very bottom.
The scrolling works fine on its own without the dragging being done.
If anyone wishes to see any part of my code feel free to ask as I am unsure what to actually show you guys.
I have read through a good few articles and am just left scratching my head.
I have created an attached property for achieving this behavior, have a look at my post here -
Attached Behavior for auto scrolling containers while doing Drag & Drop
Main logic is something like this -
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);
}
}
Similar questions on SO (although they are mostly for ListBox
/ListView
but should work for TreeView
too) -
WPF Listbox auto scroll while dragging
WPF ListView Databound Drag/Drop Auto Scroll
WPF Drag-to-scroll doesn't work correctly
I know this question really old, but here is the MVVM way as attached property:
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
}
}
And it can be used like:
<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="tool:TreeItemAttach.BringIntoView" Value="True"/>
</Style>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With