就我所了解的默认ScrollViewer而言,似乎无法直接实现这一点,因为内容被嵌套在ScrollViewer内部。
有什么想法可以让这个工作起来吗?
编辑:我知道ScrollViewer是一个Decorator,并且内容不知道ScrollViewer。这种分离很好,我不希望内容意识到ScrollViewer。我要做的只是一个纯粹的视觉(布局)问题。只需在内容上显示ScrollViewer即可,ScrollViewer的行为应保持不变。
我现在明白了您所说的“在顶部”的意思 - 一种方法是使用控件模板,使ScrollContentPresenter跨越网格的两行和两列,而ScrollBars位于第二行和第二列。 ScrollBars设置为半透明。 现在内容将在滚动条下绘制!
我尝试过的有效样式如下:
<Style x:Key="SVStyle" TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<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>
<ScrollContentPresenter Grid.ColumnSpan="2" Grid.RowSpan="2"/>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Opacity="0.5"
Grid.Column="1"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Opacity="0.5"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
使用示例:
<ScrollViewer HorizontalScrollBarVisibility="Auto" Style="{StaticResource SVStyle}" >
<StackPanel>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >World World</Button>
<Button Height="100" Width="800" >Hello World</Button>
<Button Height="100" Width="800" >Hello World</Button>
</StackPanel>
</ScrollViewer>
结果大致如下所示:
可以简单地修改此设置,使得滚动条初始时非常透明(例如,不透明度为0.2),并在鼠标进入滚动条时让它们变得更加不透明。这将是一个不错的效果,并且在需要使用滚动条之前可以将其保持在边缘。
编辑:
我已经在我的博客上撰写了更详细的内容。
我不确定您是否希望将ScrollViewer的滚动条放置在内容上方-如果是,请选择答案1;如果您希望整个ScrollViewer位于内容上方,请选择答案2。
1)您可以通过应用模板来更改WPF中任何内容的可视化表示。在这种情况下的技巧是找到ScrollViewer的现有表示形式,然后基本上重新实现所有相同的可视化效果,只需根据需要更改ScrollBar的位置即可。有几种方法可以找到控件的所有可视化元素-最简单的方法是从WPF MSDN Samples中获取-并且非常好的是,Microsoft提供的ScrollViewer 示例显示了如何更改滚动条的位置。
顺便说一句,Microsoft倾向于在其示例中加载许多您实际上不需要的额外Xaml-使用模板进行操作(无情地削减代码),直到它仅按照您的要求执行操作。
2) 我在将滚动视图放置在内容上的方法是使用两个重叠的滚动视图。 "顶部" 是小的、半透明的(不透明度=50),用于处理滚动,底部是更大的并包含文档。将顶部ScrollViewer的滚动事件与底部的ScrollViewer绑定,以便它也可以滚动底部的那个。
这个想法是,ScrollViewer 是滚动和剪辑其内容的装饰器。被滚动的内容完全不知道滚动的存在。这很简单、优美,为什么在你的情况下不够用呢?
话虽如此,如果 ScrollViewer 不能满足您的需求,我建议您创建 ScrollBar 控件,并处理由它生成的事件,在事件处理程序中移动您希望滚动的内容。您甚至可以使用一些高级数据绑定来避免编写事件处理程序。我不确定您将如何正确地剪辑内容,但这是一个新的问题。
如果您需要在一个控件上方布局另一个控件,请使用 Canvas 控件。