スクロールバーが一番下にあるときのみ要素の追加時に自動スクロールするBehavior
前提条件:
・Xaml.Behaviors.Wpf がインストール済
・言語バージョン C#9.0
・Null安全のオプションがON
class AutoScrollBehavior : Behavior<ListBox> { //-----------------依存関係プロパティ-------------------------------- public static readonly DependencyProperty EndMarginProperty = DependencyProperty.Register( "EndMargin", typeof(double), typeof(AutoScrollBehavior), new FrameworkPropertyMetadata { DefaultValue = 0.0, BindsTwoWayByDefault = true }); public double EndMargin { get { return (double)GetValue(EndMarginProperty); } set { SetValue(EndMarginProperty, value); } } //------------------------------------------------------------------- ScrollViewer? _listBoxScroll; bool _shouldAutoScroll = true; protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.Loaded += OnLoaded; } private void OnLoaded(object sender, RoutedEventArgs e) { _listBoxScroll = CaptureScrollViewer(); if (_listBoxScroll is not null) { _listBoxScroll.ScrollChanged += OnScrollChanged; } } private void OnScrollChanged(object sender, ScrollChangedEventArgs e) { if (e.VerticalChange != 0.0) { _shouldAutoScroll = e.ViewportHeight + e.VerticalOffset + EndMargin >= e.ExtentHeight; return; } if (_shouldAutoScroll) { _listBoxScroll = _listBoxScroll ?? CaptureScrollViewer(); _listBoxScroll?.ScrollToEnd(); } } protected override void OnDetaching() { base.OnDetaching(); if (_listBoxScroll is not null) { _listBoxScroll.ScrollChanged -= OnScrollChanged; } this.AssociatedObject.Loaded -= OnLoaded; } private ScrollViewer? CaptureScrollViewer() { var border = VisualTreeHelper.GetChild(AssociatedObject, 0) as Border; return border?.Child as ScrollViewer; } }