编辑
2025-10-03
C#
00

目录

基本特性
基础用法
简单示例
常用属性
高级用法示例
自定义滚动条样式
滚动到特定位置
监听滚动事件
常见应用场景
虚拟化列表滚动
图片查看器
文档阅读器
性能优化技巧
启用延迟滚动
使用虚拟化
优化滚动性能
总结

ScrollViewer 是WPF中的一个重要容器控件,它为内容提供滚动功能。与WinForm中的Panel.AutoScroll不同,ScrollViewer提供了更丰富的滚动特性和更好的可定制性。

基本特性

  • 支持水平和垂直滚动
  • 可自定义滚动条样式
  • 支持触摸滚动
  • 提供丰富的滚动事件

基础用法

简单示例

XML
<ScrollViewer Height="200" Width="300"> <!-- 内容区域 --> <StackPanel> <TextBlock Text="这是一段很长的内容..." TextWrapping="Wrap"/> <Button Content="按钮1"/> <Button Content="按钮2"/> <!-- 更多内容 --> </StackPanel> </ScrollViewer>

image.png

常用属性

XML
<ScrollViewer Height="200" Width="300" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" CanContentScroll="True" PanningMode="Both"> <StackPanel> <!-- 内容 --> </StackPanel> </ScrollViewer>

高级用法示例

自定义滚动条样式

XML
<Window.Resources> <Style x:Key="CustomScrollViewerStyle" TargetType="ScrollViewer"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ScrollViewer"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- 内容区域 --> <ScrollContentPresenter Grid.Column="0" Grid.Row="0"/> <!-- 垂直滚动条 --> <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="1" Grid.Row="0" Value="{TemplateBinding VerticalOffset}" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/> <!-- 水平滚动条 --> <ScrollBar x:Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Column="0" Grid.Row="1" Value="{TemplateBinding HorizontalOffset}" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <ScrollViewer Style="{StaticResource CustomScrollViewerStyle}"> <!-- 内容 --> </ScrollViewer>

滚动到特定位置

XML
<Window x:Class="AppScrollViewer.Window2" 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:AppScrollViewer" xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" Title="Window2" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- ScrollViewer --> <ScrollViewer x:Name="MyScrollViewer" Grid.Row="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"> <StackPanel> <!-- 内容区域 --> <TextBlock Text="滚动演示标题" FontSize="24" FontWeight="Bold" Margin="10,10,10,20"/> <!-- 生成多个内容项 --> <ItemsControl> <ItemsControl.ItemsSource> <x:Array Type="{x:Type sys:String}"> <sys:String>第1段内容:这是一段示例文本,用于演示滚动效果。</sys:String> <sys:String>第2段内容:ScrollViewer是WPF中非常实用的控件,可以方便地管理可滚动内容。</sys:String> <sys:String>第3段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <sys:String>第4段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <sys:String>第5段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <sys:String>第6段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <sys:String>第7段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <sys:String>第8段内容:通过设置不同的滚动条可见性,可以精确控制滚动行为。</sys:String> <!-- 重复多次以创建滚动效果 --> </x:Array> </ItemsControl.ItemsSource> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" Margin="10" TextWrapping="Wrap" FontSize="16"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </ScrollViewer> <!-- 控制按钮 --> <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10"> <Button Content="滚动到顶部" Click="ScrollToTop_Click" Margin="5,0"/> <Button Content="滚动到底部" Click="ScrollToBottom_Click" Margin="5,0"/> <Button Content="滚动到指定位置" Click="ScrollToSpecificOffset_Click" Margin="5,0"/> </StackPanel> </Grid> </Window>
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace AppScrollViewer { /// <summary> /// Interaction logic for Window2.xaml /// </summary> public partial class Window2 : Window { private ScrollViewer _scrollViewer; public Window2() { InitializeComponent(); _scrollViewer = MyScrollViewer; } private void ScrollToTop_Click(object sender, RoutedEventArgs e) { _scrollViewer.ScrollToTop(); } private void ScrollToBottom_Click(object sender, RoutedEventArgs e) { _scrollViewer.ScrollToBottom(); } private void ScrollToSpecificOffset_Click(object sender, RoutedEventArgs e) { // 滚动到垂直100像素位置 _scrollViewer.ScrollToVerticalOffset(100); } } }

image.png

监听滚动事件

XML
<ScrollViewer ScrollChanged="ScrollViewer_ScrollChanged" > <!-- 内容 --> </ScrollViewer>
C#
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { // 获取滚动信息 if (e.VerticalChange != 0) { double verticalOffset = e.VerticalOffset; double scrollableHeight = e.ExtentHeight - e.ViewportHeight; // 计算滚动百分比 double scrollPercentage = (verticalOffset / scrollableHeight) * 100; Debug.WriteLine($"垂直滚动位置:{scrollPercentage:F2}%"); } }

image.png

常见应用场景

虚拟化列表滚动

XML
<ScrollViewer> <ListBox x:Name="DataListBox" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.IsDeferredScrollingEnabled="True"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel/> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <Border Padding="10" BorderBrush="LightGray" BorderThickness="0,0,0,1"> <StackPanel> <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="16"/> <TextBlock Text="{Binding Description}" Foreground="Gray"/> </StackPanel> </Border> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </ScrollViewer>

image.png

XML
<Window x:Class="AppScrollViewer.Window3" 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:AppScrollViewer" mc:Ignorable="d" Title="Window3" Height="450" Width="800"> <Grid> <DataGrid x:Name="VirtualDataGrid" AutoGenerateColumns="False" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.IsDeferredScrollingEnabled="True" GridLinesVisibility="None" HeadersVisibility="Column"> <DataGrid.Columns> <DataGridTextColumn Header="名称" Width="*" Binding="{Binding Name}"/> <DataGridTextColumn Header="描述" Width="2*" Binding="{Binding Description}"/> </DataGrid.Columns> </DataGrid> </Grid> </Window>
C#
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace AppScrollViewer { /// <summary> /// Interaction logic for Window3.xaml /// </summary> public partial class Window3 : Window { public Window3() { InitializeComponent(); LoadVirtualData(); } private void LoadVirtualData() { // 使用更高效的数据源 var items = GenerateLargeDataSet(100000); VirtualDataGrid.ItemsSource = items; } // 快速生成大数据集的方法 private IEnumerable<ItemData> GenerateLargeDataSet(int count) { for (int i = 0; i < count; i++) { yield return new ItemData { Name = $"项目 {i}", Description = $"详细描述 {i}" }; } } } // 数据模型 public class ItemData { public string Name { get; set; } public string Description { get; set; } } }

image.png

图片查看器

XML
<ScrollViewer x:Name="ImageScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" PanningMode="Both"> <Image x:Name="DisplayImage" Stretch="None" RenderOptions.BitmapScalingMode="HighQuality"/> </ScrollViewer>

文档阅读器

XML
<FlowDocumentReader ViewingMode="Scroll"> <FlowDocument> <Paragraph> <Run Text="这是一个可滚动的文档内容..."/> </Paragraph> <!-- 更多段落 --> </FlowDocument> </FlowDocumentReader>

image.png

性能优化技巧

启用延迟滚动

XML
<ScrollViewer IsDeferredScrollingEnabled="True"> <!-- 内容 --> </ScrollViewer>

使用虚拟化

XML
<ScrollViewer> <ItemsControl VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"> <!-- 项目模板 --> </ItemsControl> </ScrollViewer>

优化滚动性能

C#
// 禁用动画以提高性能 ScrollViewer.SetCanContentScroll(myScrollViewer, true); // 设置缓存大小 VirtualizingPanel.SetCacheLength(myItemsControl, new VirtualizationCacheLength(1,1));

总结

ScrollViewer是WPF中非常强大的滚动容器控件,相比WinForm中的滚动面板,它提供了更多的功能和更好的可定制性。掌握ScrollViewer的使用技巧,对于开发高质量的WPF应用程序至关重要。

关键要点:

  1. 理解ScrollViewer的基本属性和用法
  2. 掌握自定义样式和事件处理
  3. 注意性能优化
  4. 处理好触摸支持和嵌套滚动问题

通过合理使用ScrollViewer,我们可以为用户提供更好的滚动体验,同时保持应用程序的高性能和可维护性。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!