emby-toolbox/EmbyToolbox/Behaviors/ListBoxAutoScrollBehavior.cs
Emby Toolbox 6264b487fe Initial commit: Emby Toolbox (conversion scroll fix, bulk Del for tracks).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 21:33:47 +05:00

122 lines
3.3 KiB
C#

using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
namespace EmbyToolbox.Behaviors;
public static class ListBoxAutoScrollBehavior
{
public static readonly DependencyProperty AutoScrollToEndProperty =
DependencyProperty.RegisterAttached(
"AutoScrollToEnd",
typeof(bool),
typeof(ListBoxAutoScrollBehavior),
new PropertyMetadata(false, OnAutoScrollToEndChanged));
public static bool GetAutoScrollToEnd(DependencyObject obj)
{
return (bool)obj.GetValue(AutoScrollToEndProperty);
}
public static void SetAutoScrollToEnd(DependencyObject obj, bool value)
{
obj.SetValue(AutoScrollToEndProperty, value);
}
private static void OnAutoScrollToEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not ListBox listBox)
{
return;
}
if ((bool)e.NewValue)
{
listBox.Loaded += ListBoxOnLoaded;
}
else
{
listBox.Loaded -= ListBoxOnLoaded;
UnhookCollection(listBox);
}
}
private static void ListBoxOnLoaded(object sender, RoutedEventArgs e)
{
if (sender is not ListBox listBox)
{
return;
}
HookCollection(listBox);
ScrollToLast(listBox);
}
private static void HookCollection(ListBox listBox)
{
if (listBox.ItemsSource is INotifyCollectionChanged collection)
{
collection.CollectionChanged -= OnCollectionChanged;
collection.CollectionChanged += OnCollectionChanged;
}
}
private static void UnhookCollection(ListBox listBox)
{
if (listBox.ItemsSource is INotifyCollectionChanged collection)
{
collection.CollectionChanged -= OnCollectionChanged;
}
}
private static void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (sender is not INotifyCollectionChanged collection)
{
return;
}
foreach (Window window in Application.Current.Windows)
{
var listBox = FindListBoxForCollection(window, collection);
if (listBox is not null)
{
ScrollToLast(listBox);
return;
}
}
}
private static ListBox? FindListBoxForCollection(DependencyObject root, INotifyCollectionChanged collection)
{
if (root is ListBox listBox && ReferenceEquals(listBox.ItemsSource, collection))
{
return listBox;
}
var childrenCount = System.Windows.Media.VisualTreeHelper.GetChildrenCount(root);
for (var i = 0; i < childrenCount; i++)
{
var child = System.Windows.Media.VisualTreeHelper.GetChild(root, i);
var found = FindListBoxForCollection(child, collection);
if (found is not null)
{
return found;
}
}
return null;
}
private static void ScrollToLast(ListBox listBox)
{
if (listBox.Items.Count <= 0)
{
return;
}
var last = listBox.Items[listBox.Items.Count - 1];
listBox.ScrollIntoView(last);
}
}