using System.Windows; using System.Windows.Controls; namespace Azaion.Annotator.Extensions; public class ScrollViewerExtensions { public static readonly DependencyProperty AlwaysScrollToEndProperty = DependencyProperty.RegisterAttached("AlwaysScrollToEnd", typeof(bool), typeof(ScrollViewerExtensions), new PropertyMetadata(false, AlwaysScrollToEndChanged)); private static bool _autoScroll; private static void AlwaysScrollToEndChanged(object sender, DependencyPropertyChangedEventArgs e) { if (sender is not ScrollViewer scroll) throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances."); var alwaysScrollToEnd = e.NewValue != null && (bool)e.NewValue; if (alwaysScrollToEnd) { scroll.ScrollToEnd(); scroll.ScrollChanged += ScrollChanged; } else scroll.ScrollChanged -= ScrollChanged; } public static bool GetAlwaysScrollToEnd(ScrollViewer scroll) { if (scroll == null) throw new ArgumentNullException("scroll"); return (bool)scroll.GetValue(AlwaysScrollToEndProperty); } public static void SetAlwaysScrollToEnd(ScrollViewer scroll, bool alwaysScrollToEnd) { if (scroll == null) throw new ArgumentNullException("scroll"); scroll.SetValue(AlwaysScrollToEndProperty, alwaysScrollToEnd); } private static void ScrollChanged(object sender, ScrollChangedEventArgs e) { var scroll = sender as ScrollViewer; if (scroll == null) throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to ScrollViewer instances."); if (e.ExtentHeightChange == 0) _autoScroll = scroll.VerticalOffset == scroll.ScrollableHeight; if (_autoScroll && e.ExtentHeightChange != 0) scroll.ScrollToVerticalOffset(scroll.ExtentHeight); } }