如何将一个ScrollViewer放置在需要滚动的内容之上

10
我希望将我的ScrollViewer放置在内容上方,从而实现重叠/覆盖效果,然后设置ScrollViewer的不透明度,以使其下方的内容可见。
就我所了解的默认ScrollViewer而言,似乎无法直接实现这一点,因为内容被嵌套在ScrollViewer内部。
有什么想法可以让这个工作起来吗?
编辑:我知道ScrollViewer是一个Decorator,并且内容不知道ScrollViewer。这种分离很好,我不希望内容意识到ScrollViewer。我要做的只是一个纯粹的视觉(布局)问题。只需在内容上显示ScrollViewer即可,ScrollViewer的行为应保持不变。
3个回答

17

我现在明白了您所说的“在顶部”的意思 - 一种方法是使用控件模板,使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>
结果大致如下所示:

fancy transparent scrolling

可以简单地修改此设置,使得滚动条初始时非常透明(例如,不透明度为0.2),并在鼠标进入滚动条时让它们变得更加不透明。这将是一个不错的效果,并且在需要使用滚动条之前可以将其保持在边缘。

编辑:

我已经在我的博客上撰写了更详细的内容。


我正在将其与列表视图的标题组合使用。不幸的是,我的滚动条会覆盖标题。请问如何纠正这个问题?如果您愿意,我在这里提出了一个问题。先感谢您! - Ben Hayward
鼠标滚轮无法使用。 - CodingNinja

1

我不确定您是否希望将ScrollViewer的滚动条放置在内容上方-如果是,请选择答案1;如果您希望整个ScrollViewer位于内容上方,请选择答案2。

1)您可以通过应用模板来更改WPF中任何内容的可视化表示。在这种情况下的技巧是找到ScrollViewer的现有表示形式,然后基本上重新实现所有相同的可视化效果,只需根据需要更改ScrollBar的位置即可。有几种方法可以找到控件的所有可视化元素-最简单的方法是从WPF MSDN Samples中获取-并且非常好的是,Microsoft提供的ScrollViewer 示例显示了如何更改滚动条的位置。

顺便说一句,Microsoft倾向于在其示例中加载许多您实际上不需要的额外Xaml-使用模板进行操作(无情地削减代码),直到它仅按照您的要求执行操作。

2) 我在将滚动视图放置在内容上的方法是使用两个重叠的滚动视图。 "顶部" 是小的、半透明的(不透明度=50),用于处理滚动,底部是更大的并包含文档。将顶部ScrollViewer的滚动事件与底部的ScrollViewer绑定,以便它也可以滚动底部的那个。


太好了!谢谢。我会试一下的。顺便说一句,我想要第二个:把整个东西放在内容的顶部。 - Patrick Klug

0

这个想法是,ScrollViewer 是滚动和剪辑其内容的装饰器。被滚动的内容完全不知道滚动的存在。这很简单、优美,为什么在你的情况下不够用呢?

话虽如此,如果 ScrollViewer 不能满足您的需求,我建议您创建 ScrollBar 控件,并处理由它生成的事件,在事件处理程序中移动您希望滚动的内容。您甚至可以使用一些高级数据绑定来避免编写事件处理程序。我不确定您将如何正确地剪辑内容,但这是一个新的问题。

如果您需要在一个控件上方布局另一个控件,请使用 Canvas 控件。


谢谢你的回答,Daniel。我已经更新了问题。我想也许我可以为ScrollViewer创建一个ControlTemplate,将滚动条显示在内容上方而不是外部,但是由于Decorator没有继承自Control,所以无法为其编写模板... - Patrick Klug
抱歉,我想我误解了你想做的事情!请看我的另一个答案,它(我认为)可以实现你想要的。 - Daniel Paull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接