#1,007 – Changing Scrollbar Settings for a ListBox

By default, the visibility of both horizontal and vertical scrollbars for a ListBox is set to Auto, indicating that the scrollbars should show up automatically, as needed.

You can change this behavior by setting the value of the ScrollViewer.HorizontalScrollBarVisibility or ScrollViewer.VerticalScrollBarVisibility properties.  They can take one of the following values:

  • Auto – Scrollbar visible if required
  • Visible – Scrollbar always visible
  • Hidden – Scrollbar not shown, but content allowed to scroll (e.g. using arrow keys)
  • Disabled – Content does not scroll
        <ListBox ItemsSource="{Binding ActorList}" Margin="10"
                 ScrollViewer.VerticalScrollBarVisibility="Auto"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Image}" Height="100"/>
                        <StackPanel Margin="10,0">
                            <TextBlock Text="{Binding FullName}" FontWeight="Bold" />
                            <TextBlock Text="{Binding Dates}"/>
                            <TextBlock Text="{Binding KnownFor}" FontStyle="Italic"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

1007-001

#1,006 – Scrollbars in a ListBox Appear as Needed

Scrolling in a ListBox is managed by a ScrollViewer, which contains the items panel of the ListBox.  The ScrollViewer provides scrolling logic and makes available both a horizontal and a vertical scrollbar.

The visibility of the scrollbars in a ScrollViewer is controlled by the HorizontalScrollBarVisibility and VerticalScrollBarVisibility properties.  By default, both of these properties are set to Auto for the ScrollViewer used in a ListBox.  This means that the scrollbar only appears if the content of the ListBox does not fit in the associated dimension.

1006-0011006-002

 

1006-003

#1,005 – Enabling Deferred Scrolling for Better Performance

By default, when you drag the thumb portion of a scrollbar, the content being scrolled updates as you move the thumb.  In some cases, this can make scrolling slow if the content being scrolled takes a long time to update.

You can improve the performance of the user interface while scrolling by telling the associated ScrollViewer not to scroll the content until you let go of the scrollbar’s thumb.  This is known as deferred scrolling.

You can enable deferred scrolling by setting the IsDeferredScrollingEnabled property of the associated ScrollViewer to true.  Below is an example of doing this for a ListBox.

        <ListBox ItemsSource="{Binding ActorList}" Width="300"
                 ScrollViewer.IsDeferredScrollingEnabled="True">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Image}" Height="100"/>
                        <StackPanel Margin="10,0">
                            <TextBlock Text="{Binding FullName}" FontWeight="Bold" />
                            <TextBlock Text="{Binding Dates}"/>
                            <TextBlock Text="{Binding KnownFor}" FontStyle="Italic"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

#1,003 – Set CanContentScroll to False for Smooth Scrolling in a ListBox

By default, the ListBox control scrolls intelligently, one item at a time.  Scrolling behavior in a ListBox is provided by a ScrollViewer.  By default, the CanContentScroll property of the containing ScrollViewer is set to true, indicating that the items panel (e.g. a StackPanel) is responsible for the scrolling.  The StackPanel scrolls one item at a time as you drag the scrollbar thumb.

1003-001 1003-002

If you want to allow scrolling by pixels, rather than by items, you can set the ScrollViewer.CanContentScroll property on the ListBox to false.  This delegates scrolling responsibility back to the ScrollViewer.

        <ListBox ItemsSource="{Binding ActorList}" Width="300"
                 ScrollViewer.CanContentScroll="False">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Image}" Height="100"/>
                        <StackPanel Margin="10,0">
                            <TextBlock Text="{Binding FullName}" FontWeight="Bold" />
                            <TextBlock Text="{Binding Dates}"/>
                            <TextBlock Text="{Binding KnownFor}" FontStyle="Italic"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

1003-003

#901 – Scrolling Content within a TabControl

You can scroll content within a given tab of a TabControl by placing the content of each tab into a ScrollViewer.  In the example below, the first tab contains a ScrollViewer, which in turns contains a Grid containing the tab’s content.

    <TabControl Margin="10">
        <TabItem Header="Romans">
            <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>

                    <Image Source="Augustus.jpg" Height="60" Margin="5"/>
                    <TextBlock Grid.Row="1" Text="Augustus"/>

                    <Image Grid.Column="1" Source="Tiberius.jpg" Height="60" Margin="5"/>
                    <TextBlock Grid.Row="1" Grid.Column="1" Text="Tiberius"/>

                    <Image Grid.Column="2" Source="Caligula.jpeg" Height="60" Margin="5"/>
                    <TextBlock Grid.Row="1" Grid.Column="2" Text="Caligula"/>

                    <Image Grid.Column="3" Source="Claudius.jpg" Height="60" Margin="5"/>
                    <TextBlock Grid.Row="1" Grid.Column="3" Text="Claudius"/>

                    <Image Grid.Column="4" Source="Nero.jpg" Height="60" Margin="5"/>
                    <TextBlock Grid.Row="1" Grid.Column="4" Text="Nero"/>
                </Grid>
            </ScrollViewer>
        </TabItem>
        <TabItem Header="Greeks">
        </TabItem>
    </TabControl>

901-001

#890 – Bringing a Control into View within a ScrollViewer

If you have a particular control contained within a ScrollViewer and you want to programmatically scroll to that control, you can use its BringIntoView method.

For example, when we click the “Find Nero” in the sample below, we’ll scroll the image of Nero into view.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Button Content="Find Nero" Click="btnFindNero_Click"
                HorizontalAlignment="Center" Margin="5"
                Padding="10,5"/>
        <ScrollViewer Grid.Row="1" Name="svMain" VerticalScrollBarVisibility="Visible">
            <StackPanel>
                <Image Source="Augustus.jpg" Height="100" Margin="5"/>
                <Image Source="Tiberius.jpg" Height="100" Margin="5"/>
                <Image Source="Caligula.jpeg" Height="100" Margin="5"/>
                <Image Source="Claudius.jpg" Height="100" Margin="5"/>
                <Image Name="imgNero" Source="Nero.jpg" Height="100" Margin="5"
                       ToolTip="Yup, I'm Nero"/>
                <Image Source="Galba.jpg" Height="100" Margin="5"/>
            </StackPanel>
        </ScrollViewer>
    </Grid>
        private void btnFindNero_Click(object sender, RoutedEventArgs e)
        {
            imgNero.BringIntoView();
        }

890-001

#889 – Scrolling a ScrollViewer from Code

You can programmatically cause a ScrollViewer’s content to scroll by using one or more of the ScrollViewer’s methods listed below.

To scroll content vertically:

  • Call LineUp to scroll up one line
  • Call LineDown to scroll down one line
  • Call PageUp to scroll up one page
  • Call PageDown to scroll down one page
  • Call ScrollToHome to scroll to the top
  • Call ScrollToEnd to scroll to the bottom

To scroll horizontally, use the corresponding methods LineLeftLineRightPageLeft, PageRight, ScrollToLeftEnd and ScrollToRightEnd.

        <StackPanel Orientation="Horizontal">
            <Button Content="Up 1" Click="btnUpOne_Click"/>
            <Button Content="Down 1" Click="btnDownOne_Click"/>
        </StackPanel>
        <ScrollViewer Grid.Row="1" Name="svMain" VerticalScrollBarVisibility="Visible">
            <StackPanel>
                <Image Source="Augustus.jpg" Height="100" Margin="5"/>
                <Image Source="Tiberius.jpg" Height="100" Margin="5"/>
                <Image Source="Caligula.jpeg" Height="100" Margin="5"/>
                <Image Source="Claudius.jpg" Height="100" Margin="5"/>
                <Image Source="Nero.jpg" Height="100" Margin="5"/>
                <Image Source="Galba.jpg" Height="100" Margin="5"/>
            </StackPanel>
        </ScrollViewer>

 

        private void btnUpOne_Click(object sender, RoutedEventArgs e)
        {
            svMain.LineUp();
        }

        private void btnDownOne_Click(object sender, RoutedEventArgs e)
        {
            svMain.LineDown();
        }

889-001