Answered Scroll Listview to specific line

  • Friday, October 17, 2008 12:40 PM
     
     
    WPF, Browserlike app.
    I got one page containing a ListView.  I call a PageFunction. On return of the PageFunction, I add one line to the ListView, scroll the line into view, set focus on the line.

          ListViewItem item = ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;

          SelectedIndex = index;

          if (item != null)

          {

            ScrollIntoView(item);

            item.Focus();

          }


    This works. As long as the new line is in view the line gets the focus like it should.

    Problem is, things don't work when the line is not visible.
    If the line is not visible, there is no ListViewItem for the line generated, so ItemContainerGenerator.ContainerFromIndex returns null.

    But without the item, how do I scroll the line into view? I need the item to call ScrollIntoView().



    thanks,
    Sam


    • Edited by Sam Jost Friday, October 17, 2008 12:45 PM
    • Edited by Sam Jost Friday, October 17, 2008 12:48 PM
    • Edited by Sam Jost Friday, October 17, 2008 12:59 PM
    •  

All Replies

  • Friday, October 17, 2008 1:10 PM
     
     
    Hi,

    Can you provide the full code of what you are trying to do.

    Thank You

    FEAR NOT TO BE JUST
  • Friday, October 17, 2008 1:23 PM
     
     
    I just found I phrased my question way too complicated. In reality it is much simpler.


    I got a WPF ListView.
    I want to scroll the last line into view.
    I can't use ScrollIntoView() since the last line is virtualised.

    So how do I scroll the last line into view then?
  • Friday, October 17, 2008 1:28 PM
     
     
    as a quick fix, disable UI Virtualization on the ListView. Then it would work. But if you have too many items in the listview, it would be darn slow.

    When virtualization is enabled, only visible elements woudl be loaded (so only they are inside the Visual Tree). So the list basically has no clue if there are any more items left. Disable it and try out.

    Associate Software Engineer http://krishnabhargav.blogspot.com
  • Friday, October 17, 2008 1:32 PM
     
     
    trueBuddi said:

    When virtualization is enabled, only visible elements woudl be loaded (so only they are inside the Visual Tree). So the list basically has no clue if there are any more items left. Disable it and try out.



    Is there any other way to scroll the ListView down to the bottom? I don't need to scroll using BringIntoView, some other way would be ok, too.
  • Friday, October 17, 2008 1:41 PM
     
     
    Try this:

    lv.ScrollIntoView(lv.Items[lv.Items.Count-1]);

    where "lv" is the name of the ListView control.

    By the way, I did not disable virtualization. Just did that on a virtualization-enabled listview.

    Associate Software Engineer http://krishnabhargav.blogspot.com
  • Monday, October 20, 2008 1:30 AM
     
     Answered Has Code
    would something like this work for you? Let me know if this helps.

    ScrollToAddedItem.xaml

    <Window x:Class="DUC.ScrollToAddedItem"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="ScrollToAddedItem" Height="500" Width="300">

        <StackPanel>

            <Button x:Name="btn" Content="AddNScroll" Margin="10" VerticalAlignment="Top" HorizontalAlignment="Center" Click="btn_Click"/>

            <ListView x:Name="lv" MaxHeight="250" MaxWidth="250" HorizontalAlignment="Center" />

        </StackPanel>

    </Window>


    ScrollToAddedItem.xaml.cs


    namespace DUC

    {

        /// <summary>

        /// Interaction logic for ScrollToAddedItem.xaml

        /// </summary>

        public partial class ScrollToAddedItem : Window

        {

            ObservableCollection<int> rows = new ObservableCollection<int>();

            Random rg = new Random();

            delegate void ScrollToLastItemDelegate();


            public ScrollToAddedItem()

            {

                InitializeComponent();

                InitItems();

                lv.ItemsSource = rows;

            }


            private void InitItems()

            {

                for (int i = 1; i < 100; i++)

                {

                    rows.Add(rg.Next(10000));

                }

            }


            private void btn_Click(object sender, RoutedEventArgs e)

            {

                rows.Add(rg.Next(10000));

                lv.Dispatcher.BeginInvoke(DispatcherPriority.Background,

                    new ScrollToLastItemDelegate(ScrollToLastItem));


            }


            public void ScrollToLastItem()

            {

                lv.SelectedItem = lv.Items.GetItemAt(rows.Count - 1);

                lv.ScrollIntoView(lv.SelectedItem);

                ListViewItem item = lv.ItemContainerGenerator.ContainerFromItem(lv.SelectedItem) as ListViewItem;

                item.Focus();

            }

        }

    }


    Evan Chua-Yap
    • Proposed As Answer by Evan Chua-Yap Monday, October 20, 2008 8:10 PM
    • Marked As Answer by Jim Zhou - MSFT Thursday, October 23, 2008 9:40 AM
    •  
  • Thursday, October 23, 2008 10:27 AM
     
     
    Yes, that does work!

    It seems the GetItemAt() is the main difference to my futile attempts.

    Thanks!