ListBoxのスクロール状態が変更した時のイベントを拾う

ListBoxをグリグリ動かしている時にスクロール中か非スクロール中かを判定したい時があると思います。スクロール状態が変更した時のイベントを拾ってみましょう。

        bool alreadyHookedScrollEvents = false;
 
        VisualStateGroup FindVisualState(FrameworkElement element, string name) {
            if (element == null)
                return null;
            IList groups = VisualStateManager.GetVisualStateGroups(element);
            foreach (VisualStateGroup group in groups)
                if (group.Name == name)
                    return group;
            return null;
        }
 
        T FindSimpleVisualChild<T>(DependencyObject element) where T : class {
            while (element != null) {
                if (element is T)
                    return element as T;
                element = VisualTreeHelper.GetChild(element, 0);
            }
            return null;
        } 
 
        /// <summary>
        /// ビジュアルステートの変更イベントを定義する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainListBox_Loaded(object sender, RoutedEventArgs e) {
            if (alreadyHookedScrollEvents) {
                return;
            }
 
            alreadyHookedScrollEvents = true;
            ScrollViewer viewer = FindSimpleVisualChild<ScrollViewer>(MainListBox);
            if (viewer == null) {
                return;
            }
 
            FrameworkElement element = VisualTreeHelper.GetChild(viewer, 0) as FrameworkElement;
            if (element == null) {
                return;
            }
 
            VisualStateGroup group = FindVisualState(element, "ScrollStates");
            if (group == null) {
                return;
            }
 
            group.CurrentStateChanging += (s, args) => {
                PageTitle.Text = args.NewState.Name;
            };
        }