Статьи

WinRT XAML: автоматическая прокрутка ListView и обнаружение

Для одного из наших приложений Windows 8 WinRT требуется ListView с двумя функциями:

  1. «Авто-палки». ListView должен автоматически прокручиваться вниз, когда к нему добавляется новое сообщение.
  2. «Обнаружение прокрутки». Пользователь может отключить «Автоматическую ручку», прокручивая ListView вручную. Если пользователь прокручивает ListView вниз, «Auto-stick» включен, в противном случае он отключен.

Вот несколько советов о том, как добиться этих функций в приложении WinRT с использованием C # и XAML.

Автоматическая прокрутка ListView вниз

ListView можно программно прокручивать с помощью метода ScrollIntoView . Вы можете передать элемент, и ListView перейдет, чтобы показать его. Вот как вы можете автоматически прокручивать ListView, чтобы показать последний элемент, когда ItemsSource списка является ObservableCollection и новый элемент добавляется в коллекцию:

1. Зарегистрируйте слушателя коллекции CollectionChanged-события:
private readonly ObservableCollection<string> items = new ObservableCollection<string>();
...

        private void MyListviewLoaded(object sender, RoutedEventArgs e)
        {
            this.MyListView.ItemsSource = items;

            items.CollectionChanged += (s, args) => ScrollToBottom();
        }
2. В методе ScrollToBottom установите для SelectedIndex объекта ListView последний элемент в коллекции, а затем используйте ScrollIntoView для прокрутки до элемента SelectedItem:
private void ScrollToBottom()
        {
            var selectedIndex = MyListView.Items.Count - 1;
            if (selectedIndex < 0)
                return;

            MyListView.SelectedIndex = selectedIndex;
            MyListView.UpdateLayout();

            MyListView.ScrollIntoView(MyListView.SelectedItem);
        }

 Другая опция (используемая WinRT XAML Toolkit) заключается в получении ScrollViewer -control из ListView и вызове его ScrollToVerticalOffset -method :

private void ScrollToBottom()
        {
            var scrollViewer = MyListView.GetFirstDescendantOfType<ScrollViewer>();
            scrollViewer.ScrollToVerticalOffset(scrollViewer.ScrollableHeight);
        }

GetFirstDescendantOfType является частью набора WinRT XAML . Вот класс VisualTreeHelperExtensions из инструментария, который включает этот метод расширения:

Обнаружение, когда ListView прокручивается вниз

В нашем случае авто-джойстик включается или отключается в зависимости от того, где пользователь прокручивает ListView. Это требует, чтобы мы могли определить, когда прокручивается ListView (или фактически, когда прокрутка заканчивается), а также нам нужно знать, прокручивается ли ListView до конца. Для того , чтобы достичь этого, мы в первую очередь необходимо получить доступ к ListView в ScrollViewer , а затем Вертикально ScrollViewer в ScrollBar . Мы можем использовать методы GetFirstDescendantOfType и GetDescendantsOfType из расширения WinRT XAML Toolkit (как показано выше), чтобы получить следующие элементы управления:

var scrollViewer = MyListView.GetFirstDescendantOfType<ScrollViewer>();

var scrollbars = scrollViewer.GetDescendantsOfType<ScrollBar>().ToList();

var verticalBar = scrollbars.FirstOrDefault(x => x.Orientation == Orientation.Vertical);

Теперь, когда у нас есть вертикальная полоса прокрутки, мы можем зарегистрировать обработчик события в его Scroll -event:

if (verticalBar != null)
                verticalBar.Scroll += BarScroll;

В BarScroll-методе мы получаем и аргумент события типа ScrollEventargs . Этот аргумент говорит нам, когда прокрутка закончилась. Убедившись, что мы получили нужное нам событие, мы можем использовать аргумент NewValue -property, чтобы убедиться, что мы прокрутили до конца:

void BarScroll(object sender, ScrollEventArgs e)
        {
            if (e.ScrollEventType != ScrollEventType.EndScroll) return;

            var bar = sender as ScrollBar;
            if (bar == null)
                return;

            System.Diagnostics.Debug.WriteLine("Scrolling ended");

            if (e.NewValue >= bar.Maximum)
            {
                System.Diagnostics.Debug.WriteLine("We are at the bottom");
                LockToBottom = true;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("We are away from the bottom");
                LockToBottom = false;
            }
        }

Теперь нам просто нужно отредактировать метод ScrollToBottom, чтобы автоматическая прокрутка происходила только в том случае, если для свойства LockToBottom установлено значение true:

private void ScrollToBottom()
        {
            if (!LockToBottom)
                return;

            var selectedIndex = MyListView.Items.Count - 1;
            if (selectedIndex < 0)
                return;

            MyListView.SelectedIndex = selectedIndex;
            MyListView.UpdateLayout();

            MyListView.ScrollIntoView(MyListView.SelectedItem);
        }

Образец:

Пример приложения, если оно доступно на GitHub .

образ

Добавьте несколько сообщений в список, чтобы увидеть, как он автоматически прокручивается, потому что «Auto Stick» включен по умолчанию. Затем прокрутите список вверх, и автопридерживание отключено.