1

Is there a way to keep a ListView scrolling vertically as data is updated via a binding to the ListView's ItemsSource property? I can't seem to find a property in either the ListView or its underlying GridView control to achieve the desired result. I would like it to scroll so that the newest information is always visible to the user. A scroll bar already appears as the rows add to the control but the most current row is not presented.

Should I consider using a different type of control that has auto-scroll capability? I only have two columns: one contains DateTimes and the other contains a simple string. I'm starting to think that my control choice may be too limited.

My XAML looks roughly like this:

<ListView ItemsSource="{Binding Updates}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Timestamp" DisplayMemberBinding="{Binding TimeStamp}"/>
            <GridViewColumn DisplayMemberBinding="{Binding UpdateString}" />
        </GridView>
    </ListView.View>
</ListView>
2
  • Considering @Daniel's answer, are you looking to make the GridView able to scroll when needed, ie. when it contains more than a screen of data, or are you looking to have the scrolling itself occur automatically, so that older data is pushed out of the viewport, and newer data scrolled in as it is added? @Daniel answers the first, but the second will require animations / EventTriggers. :) Commented Nov 22, 2010 at 17:01
  • Good point, I should have clarified. I need it to scroll when there is more than a screen of data and then scroll as data populates the GridView. I'll add that information. Commented Nov 22, 2010 at 18:16

4 Answers 4

2

I found away to expose the ListView's ScrollViewer object to manipulate scrolling. My DataContext contains a collection derived from ObservableCollection and in the code behind I wired an eventhandler to the CollectionChanged event. I used a Decorator to expose the the first child of the ListView (the border) and it's child is the ScrollViewer. From there I call the ScrollToBottom() method to attain the desired behavior.

In the code behind for my View which contains the ListView, this is how it's coded

MyViewModel viewModel = DataContext as MyViewModel;

viewModel.MyCollection.CollectionChanged += (sender,e) =>
{
    if(e.NewItems != null)
    {
        Decorator border = VisualTreeHelper.GetChild(SummaryListView, 0) as Decorator;
        ScrollViewer scroll = border.Child as ScrollViewer;
        scroll.ScrollToBottom();
    }
};

I found how to expose the ScrollViewer on Anshulee's WindowsClient blog post.

Edit Previously, I was checking if the max number of items in the custom collection was met and then scrolled to bottom. That did not work so well with different screen resolutions because the app might display 15 lines in the ListView on one machine and 25 lines on another. So now I always have it scroll to bottom to bring the newest item into view.

Sign up to request clarification or add additional context in comments.

Comments

1

you should use a scrollviewer object, it will automatically scroll when needed its contents (you can also specify if you always want horizontal or vertical scroll regardless where it's needed or not, and some other things as well)

<ScrollViewer>
   <GridView>
       <!-- gridview definition -->
   <GridView>
</ScrollViewer>

more info on MSDN

2 Comments

Unfortunately this doesn't work for me because the GridView headers scroll out of view.
Any way I could wrap just the items and not the whole GridView. I want to avoid scrolling the header out of view.
0

I'm pretty sure that a VirtualizingStackPanel is being used under the covers...which means that the items do no exist until they are needed. Therefore if you have 15000 items, rendering those 15000 items before needed makes no sense.

An easier approach may be to force a sort so the newest data remains on the top. It will then give you the appearance of pushing items down but they will be the oldest items so scrolling to see them doesn't matter unless the user initiates it.

Comments

0

A Listview has a method called ScrollIntoView(object item).

This will scroll the Listview to the position where the specified item is.

When you have a collection that is binded to the Listview, you can call this method when your collection has changed, something like:

private void myCollectionChanged()
{
    myListView.ScrollIntoView(myCollection.Last());
}

2 Comments

I tried that method as well, it didn't scroll to the bottom item. My accepted answer (and the one I provided) is what worked in my application.
Yes, because that would be far simpler than what I had to do. I prefer simple and readable to minimize complexity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.