Элементы управления в WPF. ScrollViewer — прокрутка содержимого

При ограниченном пространстве окна программы нам периодически необходимо обеспечить прокрутку содержимого этого окна. Например, когда в окне программы размещается большое количество элементов управления или загружен текст большого объема. Для таких случаев в WPF используется элемент ScrollViewer, который и обеспечивает прокрутку содержимого.

Элемент ScrollViewer

Элемент ScrollViewer представляет собой контейнер содержимого с двумя полосами прокрутки — горизонтальной и вертикальной. ScrollViewer может содержать только один контейнер содержимого и, при этом, в качестве такого контейнера обычно выступает какой-либо предок элемента Panel (WrapPanel, StackPanel и т.д.). Рассмотрим следующий пример:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ScrollViewer>
            <StackPanel>
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Red"></Border>
                <Border Height="50" Background="Yellow"></Border>
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Yellow"></Border>
                <Border Height="50" Background="Blue"></Border>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Window>

Здесь мы используем ScrollViewer с настройками по умолчанию, поэтому в запущенном приложении вы увидите следующее окно приложения:ScrollViewer в WPF- прокрутка содержимого

Несмотря на то, что элементам Border внутри контейнера вполне хватает места. чтобы разместиться в нем и быть полностью видимыми, у ScrollViewer мы видим вертикальную полосу прокрутки, которая в данный момент неактивна. Измените высоту окна и вы увидите, что полоса прокрутки становится доступной и можно прокручивать содержимое контейнера. ScrollViewer в WPF- прокрутка содержимого

При этом, сколько бы мы не изменяли ширину окна — горизонтальная полоса прокрутки не появляется, так как все элементы внутри ScrollViewer автоматически меняют свою ширину. Рассмотрим основные свойства и методы ScrollViewer.

Свойства и события ScrollViewer

Среди основных свойств элемента ScrollViewer можно выделить следующие:

Свойство Тип Описание
HorizontalScrollBarVisibility ScrollBarVisibility Определяет видимость горизонтальной полосы прокрутки и может принимать следующие значения:

  • Auto — полоса прокрутки отображается автоматически, когда окно просмотра не может отобразить все содержимое.
  • Disabled полоса прокрутки не отображается, даже если окно просмотра не может показать все содержимое.
  • Hidden полоса прокрутки не отображается, даже если окно просмотра не может показать все содержимое.
  • Visible полоса прокрутки всегда отображается.
VerticalScrollBarVisibility ScrollBarVisibility Определяет видимость вертикальной полосы прокрутки. Возможные принимаемые значения см. выше.
HorizontalOffset double Возвращает горизонтальное смещение прокручиваемого содержимого. Свойство только для чтения.
VerticalOffset double Возвращает вертикальное смещение прокручиваемого содержимого. Свойство только для чтения.

Также, элемент ScrollViewer предоставляет нам следующее событие

Событие Описание
public eventScrollChangedEventHandler ScrollChanged;
Генерируется при обнаружении изменений положения полосы прокрутки или размера области просмотра.

Изменим код нашего приложения следующим образом:
1. Перепишем разметку XAML окна:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
        <ScrollViewer x:Name="scroll"  
                      HorizontalScrollBarVisibility="Auto" 
                      VerticalScrollBarVisibility="Auto"
                      ScrollChanged="scroll_ScrollChanged">
            <StackPanel Width="700" Height="400">
                
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Red"></Border>
                <Border Height="50" Background="Yellow">
                     <TextBlock x:Name="info"/>
                </Border>
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Yellow"></Border>
                <Border Height="50" Background="Blue"></Border>
            </StackPanel>
        </ScrollViewer>
</Window>

Во-первых, мы определили размеры контейнера StackPanel внутри ScrollViewer:

<StackPanel Width="700" Height="400">

Во-вторых, мы добавили текстовый блок с именем info для вывода информации о значении свойств ScrollViewer:

<Border Height="50" Background="Yellow"> 
   <TextBlock x:Name="info"/> 
</Border>

И, в-третьих, определили значение свойств HorizontalScrollBarVisibilityVerticalScrollBarVisibility и обработчик события ScrollChanged:

<ScrollViewer x:Name="scroll"  
              HorizontalScrollBarVisibility="Auto" 
              VerticalScrollBarVisibility="Auto"
              ScrollChanged="scroll_ScrollChanged">

Теперь полосы прокрутки будут показываться только, когда содержимому не будет хватать места в окне просмотра, а обработчик события будет следующим:

private void scroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    info.Text = $"HorizontalOffset {scroll.HorizontalOffset}; VerticalOffset {scroll.VerticalOffset}";
}

Запустим приложение и посмотрим на результат. При запуске приложения, всё содержимое полностью умещается и видимо в окне просмотра, поэтому полос прокрутки мы не видим:ScrollViewer в WPF- прокрутка содержимого

Изменим размер окна таким образом, чтобы увидеть полосы прокрутки и изменим положение «бегунков»:ScrollViewer в WPF- прокрутка содержимогоПри необходимости, мы можем управлять прокруткой в ScrollViewer автоматически, используя методы элемента.

Методы для программной прокрутки ScrollViewer

Для программной прокрутки ScrollViewer можно использовать следующие методы (в таблице представлена только часть методов):

Метод Описание
public void LineDown();
Прокрутка вниз на одну строку (обычно, на 16 единиц)
public void LineUp();
Прокрутка вверх на одну строку
public void LineLeft();
Прокрутка влево на одну строку
public void LineRight();
Прокрутка вправо на одну строку
public void PageDown();
Прокрутка на страницу вниз
public void PageLeft();
Прокрутка на страницу влево
public void PageRight();
Прокрутка на страницу вправо
public void PageUp();
Прокрутка на страницу вверх
public void ScrollToHorizontalOffset(double offset);
Прокрутка влево или вправо на определенное значение
public void ScrollToVerticalOffset(double offset);
Прокрутка вверх или вниз на определенное значение
ScrollToEnd()
Прокрутка в конец окна
ScrollToHome()
Прокрутка в самый вверх окна

Все эти методы можно сгруппировать по трем группам:

  1. Прокрутка на элемент (методы вида Line[Up, Down, Left, Right]())
  2. Прокрутка на страницу (методы вида Page[Up, Down, Left, Right]())
  3. Прокрутка на определенное значение (методы вида ScrollTo)

Чтобы продемонстрировать работу этих методов, перепишем код нашего приложения следующим образом:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel Orientation="Vertical">
        <ScrollViewer x:Name="scroll"  
              HorizontalScrollBarVisibility="Auto" 
              VerticalScrollBarVisibility="Auto"
              ScrollChanged="scroll_ScrollChanged"
              Height="400">
            <StackPanel Width="700" Height="400">
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Red"></Border>
                <Border Height="50" Background="Yellow">
                    <TextBlock x:Name="info"/>
                </Border>
                <Border Height="50" Background="Blue"></Border>
                <Border Height="50" Background="Green"></Border>
                <Border Height="50" Background="Yellow"></Border>
                <Border Height="50" Background="Blue"></Border>
            </StackPanel>
        </ScrollViewer>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Button Content="Вверх" Grid.Column="0" Margin="4" Click="Button_Click" />
            <Button Content="Вниз" Grid.Column="1" Margin="4" Click="Button_Click_1" />
            <Button Content="Влево" Grid.Column="2" Margin="4" Click="Button_Click_2" />
            <Button Content="Вправо" Grid.Column="3" Margin="4" Click="Button_Click_3"/>
        </Grid>
    </StackPanel>
</Window>

Здесь мы добавили контейнер Grid с четырьмя кнопками для программной прокрутки ScrollViewer вверх, вниз, вправо и влево:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Button Content="Вверх" Grid.Column="0" Margin="4" Click="Button_Click" />
    <Button Content="Вниз" Grid.Column="1" Margin="4" Click="Button_Click_1" />
    <Button Content="Влево" Grid.Column="2" Margin="4" Click="Button_Click_2" />
    <Button Content="Вправо" Grid.Column="3" Margin="4" Click="Button_Click_3"/>
</Grid>

У каждой из кнопок мы определили обработчики события Click. В этих обработчиках мы будем использовать методы из той или иной группы для прокрутки. Например,

private void Button_Click(object sender, RoutedEventArgs e)
{
    scroll.LineUp();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    scroll.LineDown();
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
   scroll.LineLeft();
}

private void Button_Click_3(object sender, RoutedEventArgs e)
{
    scroll.LineRight();
}

Запустим приложение и попробуем, управляя кнопками выполнить прокрутку:ScrollViewer в WPF- прокрутка содержимогоПрокрутка с помощью методов типа Line...() осуществляет переход к следующему элементу в логическом дереве. Обычно, смещение идет на 16 единиц в заданном направлении.  Немного по другому работают методы прокрутки на страницу.

Изменим обработчики кнопок следующим образом:

private void Button_Click(object sender, RoutedEventArgs e)
{
    scroll.PageUp();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    scroll.PageDown();
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
   scroll.PageLeft();
}

private void Button_Click_3(object sender, RoutedEventArgs e)
{
    scroll.PageRight();
}

А также изменим высоту ScrollViewer, установив её равной 100:

<ScrollViewer x:Name="scroll"  
      ...
      Height="100">
      ...
</ScrollViewer>

Теперь запустите приложение и убедитесь, что ScrollViewer пытает прокрутить содержимое на размер своей высоты (или ширины) или же, если оставшееся расстояние прокрутки меньше этого значения, то прокрутка идёт до конца:ScrollViewer в WPF- прокрутка содержимогоИ, наконец, продемонстрируем прокрутку на произвольное значение. Изменим обработчики кнопок следующим образом:

private void Button_Click(object sender, RoutedEventArgs e)
{
    scroll.ScrollToVerticalOffset(-25);
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    scroll.ScrollToVerticalOffset(25);
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
   scroll.ScrollToHorizontalOffset(25);
}

private void Button_Click_3(object sender, RoutedEventArgs e)
{
    scroll.ScrollToHorizontalOffset(-25);
}

Обратите внимание, что для прокрутки вверх и влево мы используем отрицательные значения смещения, а для прокрутки вниз и влево — положительные. При этом, прокрутка производится один раз, то есть, сколько бы раз мы не нажимали на кнопку — величина прокрутки не изменится после первого нажатия. Поэтому, если вам необходимо программно прокручивать содержимое ScrollViewer на произвольное значение, то необходимо изменить код обработчиков следующим образом (на примере прокрутки вверх и вниз)

private void Button_Click(object sender, RoutedEventArgs e)
{
    scroll.ScrollToVerticalOffset(scroll.ContentVerticalOffset - 25);
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    
    scroll.ScrollToVerticalOffset(scroll.ContentVerticalOffset + 25);
}

Теперь текущее значение прокрутки будет браться из свойства scroll.ContentVerticalOffset и можно программно пролистывать ScrollViewer на 25 единиц в обоих направлениях до конца.

ScrollViewer в WPF- прокрутка содержимого

Итого

Элемент ScrollViewer позволяет организовать прокрутку содержимого, когда оно полностью не умещается в доступную область просмотра. Прокрутка может осуществляться как с использование полос прокрутки, так и программно на один элемент, на страницу или на произвольное значение.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии