WPF:如何防止滚动条在列表类型视图中覆盖 headers
WPF: How to prevent scrollbar from overlaying headers in list type views
我制作了一个 ScrollViewer 样式,旨在显示覆盖可滚动内容的滚动条。我根据其他 Whosebug 帖子 such as this.
制作了它
许多其他场景与我的场景之间的区别在于,我将滚动查看器样式应用于包含 header 的 ListView。通常,用户希望滚动查看器不会像我下面的图片那样覆盖 headers。 (我用橙色突出显示了该栏以使其更加明显)
(该条应该在 header 开始之前停止。重要的是要提到可滚动内容的第一个元素没有隐藏在 header 下面。在我的图像中将栏向下滚动 ~15%。)
我尝试将滚动查看器中的滚动条固定在底部并将它们的高度设置为 "ViewportHeight",还尝试将各种元素放置在网格的第二行(第 1 行)中(参见下面的代码)无济于事。
如何让滚动查看器在 header 的底部之前停止?
<Style x:Key="StandardScrollViewer" TargetType="{x:Type ScrollViewer}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource BackgroundGreyLevel2}" />
<Setter Property="Background" Value="{DynamicResource CollectionControlBackgroundGradient}" />
<Setter Property="VerticalScrollBarVisibility" Value="Hidden"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}" Grid.ColumnSpan="2" Grid.RowSpan="1">
<ScrollViewer DockPanel.Dock="Top" Grid.ColumnSpan="2" Grid.RowSpan="2" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="False">
<GridViewHeaderRowPresenter x:Name="GridViewHeaderRowPresenter" Margin="2,0,2,0" Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
</DockPanel>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Grid.Column="1"
Grid.Row="0"
VerticalAlignment="Stretch"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
这比我想象的更容易修复,部分原因是(与我的信念相反)WPF 对于呈现滚动内容的元素的源 WPF ordering/positioning 并不重要和滚动条(停靠面板和上面两个滚动条中的所有内容)。
因此,只需在视图中添加一个额外的(第 3 行)行,我可以在其中放置我的 headers。然后我简单地将内容和垂直滚动条的指定行更改为 +1 之前的内容。
结果是滚动条包含在与滚动内容相同的行中,因此不会泄漏到 headers 上。
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GridViewHeaderRowPresenter x:Name="GridViewHeaderRowPresenter" Margin="2,0,2,0" Grid.Row="0" Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DockPanel Margin="{TemplateBinding Padding}" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="1">
<ScrollViewer DockPanel.Dock="Top" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="False">
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
</DockPanel>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Grid.Column="1"
Grid.Row="1"
VerticalAlignment="Stretch"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
以上是我修改的唯一一段代码。
此外,作为参考,this article 非常有帮助。
我制作了一个 ScrollViewer 样式,旨在显示覆盖可滚动内容的滚动条。我根据其他 Whosebug 帖子 such as this.
制作了它许多其他场景与我的场景之间的区别在于,我将滚动查看器样式应用于包含 header 的 ListView。通常,用户希望滚动查看器不会像我下面的图片那样覆盖 headers。 (我用橙色突出显示了该栏以使其更加明显)
(该条应该在 header 开始之前停止。重要的是要提到可滚动内容的第一个元素没有隐藏在 header 下面。在我的图像中将栏向下滚动 ~15%。)
我尝试将滚动查看器中的滚动条固定在底部并将它们的高度设置为 "ViewportHeight",还尝试将各种元素放置在网格的第二行(第 1 行)中(参见下面的代码)无济于事。
如何让滚动查看器在 header 的底部之前停止?
<Style x:Key="StandardScrollViewer" TargetType="{x:Type ScrollViewer}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource BackgroundGreyLevel2}" />
<Setter Property="Background" Value="{DynamicResource CollectionControlBackgroundGradient}" />
<Setter Property="VerticalScrollBarVisibility" Value="Hidden"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}" Grid.ColumnSpan="2" Grid.RowSpan="1">
<ScrollViewer DockPanel.Dock="Top" Grid.ColumnSpan="2" Grid.RowSpan="2" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="False">
<GridViewHeaderRowPresenter x:Name="GridViewHeaderRowPresenter" Margin="2,0,2,0" Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
</DockPanel>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Grid.Column="1"
Grid.Row="0"
VerticalAlignment="Stretch"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
这比我想象的更容易修复,部分原因是(与我的信念相反)WPF 对于呈现滚动内容的元素的源 WPF ordering/positioning 并不重要和滚动条(停靠面板和上面两个滚动条中的所有内容)。
因此,只需在视图中添加一个额外的(第 3 行)行,我可以在其中放置我的 headers。然后我简单地将内容和垂直滚动条的指定行更改为 +1 之前的内容。
结果是滚动条包含在与滚动内容相同的行中,因此不会泄漏到 headers 上。
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GridViewHeaderRowPresenter x:Name="GridViewHeaderRowPresenter" Margin="2,0,2,0" Grid.Row="0" Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DockPanel Margin="{TemplateBinding Padding}" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="1">
<ScrollViewer DockPanel.Dock="Top" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Focusable="False">
</ScrollViewer>
<ScrollContentPresenter Name="PART_ScrollContentPresenter" KeyboardNavigation.DirectionalNavigation="Local" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
</DockPanel>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Grid.Column="1"
Grid.Row="1"
VerticalAlignment="Stretch"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
以上是我修改的唯一一段代码。
此外,作为参考,this article 非常有帮助。