ListBox and scrolling

When the listbox is bound to some data and when the data changes we may want to make the first item in the list visible.  That is not the default behaviour and ScrollIntoView(Item[0]) wont work. here is a way to reset the scrollposition

In the sample, I had the listbox’s  are bound to 200 items and when the button is clicked I set the items to 20. the listbox on the left shows the default behaviour , the listbox on the right  has the ScrollViewer position changed to show the first item  listbox scrolling
update: Looks like this method still has issues when the number of items changes from a very low number to  high number where the scrollbar appears and disappears as pointed out in this post. May be a bug?

update 2: Mog Liang (Microsoft Online Community Support) says “This is an known issue caused by ListBox virtualization. Currently, an workaround is replace VirtualizingStackPanel with StackPanel, however, this will drop the listbox performance.”

Here is the XAML and codebehind used in the sample

<Grid x:Name=”LayoutRoot” Margin=”5″>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            </Grid.ColumnDefinitions>
      <Button Content=”set to 20 items” Height=”28″ Width=”100″  HorizontalAlignment=”Right” Click=”Button_Click”/>
            <ListBox Grid.Column=”1″  Height=”200″ x:Name=”list1″ ItemsSource=”{Binding MyList}”/>
        <ListBox Grid.Column=”2″  Height=”200″ x:Name=”list2″ ItemsSource=”{Binding MyList}”/>
    </Grid>

 

public partial class MainPage : UserControl, INotifyPropertyChanged
    {
        public IEnumerable<string> MyList { get; set; }
        public MainPage()
        {
            InitializeComponent();
            MyList = Enumerable.Range(0, 200).Select(i => “Item..” + i.ToString()).ToList();
            this.DataContext = this;
           
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MyList = Enumerable.Range(0, 20).Select(i => “Item..” + i.ToString()).ToList();
            NotifyPropertyChanged(“MyList”);
            ScrollViewer sv = GetChild<ScrollViewer>(list2);
            sv.ScrollToVerticalOffset(0);
        }

        public static T GetChild<T>(DependencyObject obj) where T : DependencyObject
        {
            DependencyObject child = null; for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child.GetType() == typeof(T))
                {
                    break;
                }
                else if (child != null)
                {
                    child = GetChild<T>(child);
                    if (child != null && child.GetType() == typeof(T))
                    {
                        break;
                    }
                }
            }
            return child as T;
        }
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        } 

       
        #endregion
    }

Advertisements

One thought on “ListBox and scrolling

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s