122 lines
3.3 KiB
C#
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);
|
|
}
|
|
}
|