Для одного из наших приложений Windows 8 WinRT требуется ListView с двумя функциями:
- «Авто-палки». ListView должен автоматически прокручиваться вниз, когда к нему добавляется новое сообщение.
- «Обнаружение прокрутки». Пользователь может отключить «Автоматическую ручку», прокручивая 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» включен по умолчанию. Затем прокрутите список вверх, и автопридерживание отключено.