none
Scrolling the Itemscontrol scrollviewer to the bottom by default with Virtualization RRS feed

  • Question

  • I had developed the  chat application with a combination of text ,Image and video inside a itemscontrol and it should show the recent messages. Implemented the Scrollviewer.ScrollToBottom to acheive the functionality and it is working fine.

    Later i have Enabled the Virtualization to the items control due to the performance issue.Now the scroll to bottom  functionality is not working as expected  and i have tried the following things to make it work and  still no solution.

    soln1:  get the last item and tried BringintoView (not working) .

    soln2:  Get the VirtualizingStackPanel and invoked the BringIndexIntoViewPublic method. (not working)

    The above two solutions working only if my chat history contains few text/image .

    Please provide a solution to make the functionality work.

    thanks in advance...........


    Sudhesh. G <br/> <a href="http://gurucoders.blogspot.com" target="_blank">http://gurucoders.blogspot.com</a><br/>

    Wednesday, September 30, 2015 5:34 AM

Answers

  • The built-in ItemsControl class doesn't support virtualization. So the question is what control you are using and what you are trying to do. You should always include reproducible code when asking a code related question.

    A ListBox uses UI virtualization by default. And the following code that uses the ScrollIntoView to scroll to the last item in the Items collection of the ListBox works as expected. Please refer to it.

    public MainWindow()
            {
                InitializeComponent();
                lb.ItemsSource = Enumerable.Range(1, 100);
                this.Loaded += (s, e) => 
                {
                    lb.ScrollIntoView(lb.Items[lb.Items.Count - 1]);
                };
            }


            <ListBox x:Name="lb" Height="50">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>


    Hope that helps.

    Please upload a reproducible sample of your issue to OneDrive and post the link to it here if you need any further help. I am afraid we cannot guess how your code looks like.

    Please also remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Wednesday, September 30, 2015 3:27 PM
  • I suggest you change your itemscontrol to a listbox.

    An itemscontrol doesn't have a built in scrollviewer, the listbox does.

    You should then be able to use bringintoview.

    http://stackoverflow.com/questions/2006729/how-can-i-have-a-listbox-auto-scroll-when-a-new-item-is-added

    You could alternatively adapt the approach I use in this:

    http://social.technet.microsoft.com/wiki/contents/articles/26673.aspx

    The two behaviours DataGridRowBehavior and ScrollDataGridRowIntoView

    That'd pretty much be a case of substituting listbox for datagrid and listboxitem for datagridrow.

    That allows you to make an item in a collection current in a view model and by setting:

            <DataGrid 
               .....
                      IsSynchronizedWithCurrentItem="True"

    That then becomes the selected item in the datagrid ( you would of course be using listbox ).

    .

    Or if you prefer everything in code behind then you could adapt this:

    http://matthamilton.net/focus-a-virtualized-listboxitem

    private void FocusTweetList()
    {
        tweetList.Focus();
        if (tweetList.Items.Count == 0) return;
    
        var index = tweetList.SelectedIndex;
        if (index < 0) return;
    
        Action action = () =>
            {
                tweetList.ScrollIntoView(tweetList.SelectedItem);
    
                var item = tweetList.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem;
                if (item == null) return;
    
                item.Focus();
            };
    
        Dispatcher.BeginInvoke(DispatcherPriority.Background, action);
    }

    Note that his purpose is to return to something already selected so you would need to substitute the last entry instead.


    Wednesday, September 30, 2015 8:17 AM
    Moderator

All replies

  • I suggest you change your itemscontrol to a listbox.

    An itemscontrol doesn't have a built in scrollviewer, the listbox does.

    You should then be able to use bringintoview.

    http://stackoverflow.com/questions/2006729/how-can-i-have-a-listbox-auto-scroll-when-a-new-item-is-added

    You could alternatively adapt the approach I use in this:

    http://social.technet.microsoft.com/wiki/contents/articles/26673.aspx

    The two behaviours DataGridRowBehavior and ScrollDataGridRowIntoView

    That'd pretty much be a case of substituting listbox for datagrid and listboxitem for datagridrow.

    That allows you to make an item in a collection current in a view model and by setting:

            <DataGrid 
               .....
                      IsSynchronizedWithCurrentItem="True"

    That then becomes the selected item in the datagrid ( you would of course be using listbox ).

    .

    Or if you prefer everything in code behind then you could adapt this:

    http://matthamilton.net/focus-a-virtualized-listboxitem

    private void FocusTweetList()
    {
        tweetList.Focus();
        if (tweetList.Items.Count == 0) return;
    
        var index = tweetList.SelectedIndex;
        if (index < 0) return;
    
        Action action = () =>
            {
                tweetList.ScrollIntoView(tweetList.SelectedItem);
    
                var item = tweetList.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem;
                if (item == null) return;
    
                item.Focus();
            };
    
        Dispatcher.BeginInvoke(DispatcherPriority.Background, action);
    }

    Note that his purpose is to return to something already selected so you would need to substitute the last entry instead.


    Wednesday, September 30, 2015 8:17 AM
    Moderator
  • The built-in ItemsControl class doesn't support virtualization. So the question is what control you are using and what you are trying to do. You should always include reproducible code when asking a code related question.

    A ListBox uses UI virtualization by default. And the following code that uses the ScrollIntoView to scroll to the last item in the Items collection of the ListBox works as expected. Please refer to it.

    public MainWindow()
            {
                InitializeComponent();
                lb.ItemsSource = Enumerable.Range(1, 100);
                this.Loaded += (s, e) => 
                {
                    lb.ScrollIntoView(lb.Items[lb.Items.Count - 1]);
                };
            }


            <ListBox x:Name="lb" Height="50">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>


    Hope that helps.

    Please upload a reproducible sample of your issue to OneDrive and post the link to it here if you need any further help. I am afraid we cannot guess how your code looks like.

    Please also remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Wednesday, September 30, 2015 3:27 PM