views:

102

answers:

1

Hi,

I have a TabControl with two tabs containing lists that should always be scrolled to the bottom:

    <TabControl>
        <TabItem Header="Tab1">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ListBox x:Name="List1">
                    <ListBox.ItemTemplate>
                        <DataTemplate DataType="SampleClass">
                            <TextBlock Text="{Binding SampleProperty}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </ScrollViewer>
        </TabItem>
        <TabItem Header="Tab2">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ListBox x:Name="List2">
                    <ListBox.ItemTemplate>
                        <DataTemplate DataType="OtherSampleClass">
                            <TextBlock Text="{Binding SampleProperty}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </ScrollViewer>
        </TabItem>
    </TabControl>

Now, I have events set up so that when the binding changes, the following code is executed to scroll to the bottom of the list (depends on the tab, this is an example of what happens when the first list's items are changed):

ListBox1.ScrollIntoView(items.Last<SampleClass>());

This works fine. When the binding is changed, the ListBox scrolls to the bottom as expected.

However, when I set the same code up to execute when tabs are changed (to scroll to bottom of a list when the tabs change), the lists do not scroll to the bottom as expected (and show up scrolled at the top).

I tried hooking into SelectionChanged event of the TabControl. My guess is that the layout isn't yet rendered when this event is executed, so calling ScrollIntoView() does nothing.

Is there any way around this?

Thanks.

A: 

You can delay your ScrollIntoView call using a Dispatcher.BeginInvoke with a low priority:

Dispatcher.BeginInvoke(DisplatcherPriority.Input, new Action(() =>
{
  ListBox1.ScrollIntoView(items.Last());
}));

Now ScrollIntoView won't actually be called until all processing above Input priority has completed.

Ray Burns
Works like a charm! Thanks!
thefactor