#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

#888 – Different Ways to Scroll Content in a ScrollViewer

There are several different ways that you can scroll content within a ScrollViewer.

To scroll content vertically:

  • Click and drag the vertical scrollbar with the mouse
  • Click the up/down arrow widgets at either end of the scrollbar  (scroll small amount)
  • Tab through control that can receive focus.  When you tab to a control, it is scrolled into view.
  • Use the mouse scroll wheel
  • Press up / down arrow keys  (scroll small amount)
  • Press Page Up Page Down keys  (scroll by full page)
  • Ctrl-Home to scroll to beginning, Ctrl-End to scroll to end

To scroll content horizontally:

  • Click and drag the horizontal scrollbar with the mouse
  • Click the up/down arrow widgets at either end of the scrollbar  (scroll small amount)
  • Tab through control that can receive focus.  When you tab to a control, it is scrolled into view.
  • Press left / right arrow keys  (scroll small amount)

#887 – The Difference between Disabled and Hidden Scrollbar Visibility

ScrollViewer allows setting the horizontal or vertical scrollbar visibility to AutoDisabledHidden or Visible.  The Disabled and Hidden options are similiar, but subtly different.

  • Hidden – Scrollbar is not shown, but content is allowed to scroll (e.g. using arrow keys).  Content in ScrollViewer is given an infinite amount of space in the scrolling direction.  (E.g. Infinite width if HorizontalScrollBarVisibility is set to Hidden).
  • Disabled – Content cannot scroll and is not allowed to be larger than the ScrollViewer’s size in the scrolling direction.

We can see how this works by placing a horizontally-oriented WrapPanel inside a ScrollViewer.  When the HorizontalScrollBarVisibility is set to Hidden, the WrapPanel is infinitely wide and therefore never wraps.  (You can still scroll the content using the arrow keys).

887-001

If the HorizontalScrollBarVisibility is set to Disabled, the WrapPanel can’t scroll horizontally and its width is constrained to the width of the ScrollViewer, causing it to wrap.

887-002

#886 – Wrapping a Canvas in a ScrollViewer

Because the ScrollViewer control is a ContentControl, it can contain any single element.  It most often contains a single Panel, which in turn contains child elements.

Below is an example of a ScrollViewer that contains a Canvas, which in turn contains several different elements.  When the containing window is sized to be smaller than the Canvas element, the scrollbars automatically appear.

    <ScrollViewer HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto">
        <Canvas Width="340" Height="330">
            <Image Canvas.Left="15" Canvas.Top="5"
                   Source="Augustus.jpg" Height="100" Margin="10"/>
            <Label Canvas.Left="0" Canvas.Top="120"
                Grid.Column="1" Content="Augustus - 63BC - 14AD" />

            <Image Canvas.Top="180" Canvas.Left="200"
                   Grid.Column="2" Source="Tiberius.jpg" Height="100" Margin="10"/>
            <Label Canvas.Top="295" Canvas.Left="180"
                   Grid.Column="3" Content="Tiberius - 42BC - 37AD"/>

            <Line Canvas.Left="140" Canvas.Top="140" X2="65" Y2="50"
                  Stroke="RoyalBlue"/>
        </Canvas>
    </ScrollViewer>

886-001