Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

WinRT XAML: Automatically Scrolling ListView and Detection

DZone's Guide to

WinRT XAML: Automatically Scrolling ListView and Detection

· Mobile Zone
Free Resource

Launching an app doesn’t need to be daunting. Whether you’re just getting started or need a refresher on mobile app testing best practices, this guide is your resource! Brought to you in partnership with Perfecto

One of our Windows 8 WinRT apps requires a ListView with two features:

  1. "Auto-stick". The ListView must automatically scroll to the bottom when a new message is added to it.
  2. "Scroll detection". User can disable the "Auto-stick" by manually scrolling the ListView. If the user scrolls the ListView to bottom, the "Auto-stick" is enabled, otherwise it's disabled.

Here's some guidance on how you can achieve these features in a WinRT app using C# and XAML.

Automatically scrolling ListView to bottom

The ListView can be programmatically scrolled using the ScrollIntoView-method. You can pass in the item and the ListView jumps to show it. Here's how you can automatically scroll the ListView to show the last item when the list's ItemsSource is an ObservableCollection and a new item is added to the collection:

1. Register a listener to collection's CollectionChanged-event:
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. In the ScrollToBottom-method, set the ListView's SelectedIndex to the last item in the collection, then use ScrollIntoView to scroll to the SelectedItem:
private void ScrollToBottom()
        {
            var selectedIndex = MyListView.Items.Count - 1;
            if (selectedIndex < 0)
                return;

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

            MyListView.ScrollIntoView(MyListView.SelectedItem);
        }

 Another option (used by the WinRT XAML Toolkit) is to get the ScrollViewer-control from inside the ListView, and call its ScrollToVerticalOffset-method:

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

GetFirstDescendantOfType is part of the WinRT XAML toolkit. Here's the VisualTreeHelperExtensions -class from the toolkit which includes this extension method:

Detecting when ListView is scrolled to the bottom

In our case the auto-stick is enabled or disabled based on where the user scrolls the ListView. This requires that we can detect when the ListView is scrolled (or actually, when the scrolling ends) and also we need to know if the ListView is scrolled to the bottom. In order to achieve these, we first need to access the ListView's ScrollViewer and then the ScrollViewer's vertical ScrollBar. We can use the GetFirstDescendantOfType and GetDescendantsOfType -extension methods from WinRT XAML Toolkit (shown above) to get these controls:

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

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

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

Now that we have the vertical scroll bar, we can register an event handler to its Scroll-event:

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

In the BarScroll-method we receive and event argument of type ScrollEventargs. This argument tells us when the scrolling has ended. After making sure that we have received the event we need, we can use the argument's NewValue-property to make sure if we have scrolled to the bottom:

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;
            }
        }

Now we just need to the edit the ScrollToBottom-method so that the automatic scrolling happens only if the LockToBottom-property is set to 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);
        }

Sample:

A sample app if available from the GitHub.

image

Add few messages to the list to see how it auto scrolls, because the “Auto Stick” is enabled by default. Then scroll the list up and auto stick is disabled.

Keep up with the latest DevTest Jargon with the latest Mobile DevTest Dictionary. Brought to you in partnership with Perfecto.

Topics:
mobile ,xaml ,windows phone ,winrt

Published at DZone with permission of Mikael Koskinen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}