Question

I would like to put my ScrollViewer in such a way that it overlaps/sits on top of the content it scrolls. I would set the Opacity of the ScrollViewer so that the content is visible underneath.

As far as I understand the default ScrollViewer, this doesn't seem to be possible out of the box since the content is nested inside the ScrollViewer.

Any ideas on how to make this work?

EDIT: I understand that the ScrollViewer is a Decorator and that the content is not aware of the ScrollViewer. This separation is good and I don't want the content to be aware of the ScrollViewer. What I try to do is a purely visual (layout) thing. Simply show the ScrollViewer on top of the content.The behavior of the ScrollViewer should remain unchanged.

Was it helpful?

Solution

I think I now understand what you mean by "on top" - one way to do it is to use a control template that makes the ScrollContentPresenter span two rows and columns of a grid while the ScrollBars are in the 2nd rows and columns. The ScrollBars are set to be semi-transparent. The content will now draw under the scrollbars!

The Style I tried that works is as follows:

<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>

Example usage:

<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>

The result is along the lines of this:

fancy transparent scrolling

It would be simple modify this so that the ScrollBars are initially very transparent (say, Opacity = 0.2) and have them become more opaque when the mouse enters the ScrollBar. That would be a nice effect and would keep the ScrollBars out the way until they're needed.

EDIT:

I've written this up on my blog for those who would like a little more detail.

OTHER TIPS

The idea is that the ScrollViewer is a decorator for the thing that it scrolls and clips. The thing being scrolled is completely unaware of the scrolling. This is simple and elegant - why is it not sufficient in your case?

Having said that, if the ScrollViewer does not do what you want, I suggest that you create ScrollBar controls and handle the events generated by it, moving the content that you wish to scroll in the event handlers. You may even be able to do some fancy data binding to avoid writing event handlers. I'm not sure how you are going to clip the content correctly, but that's a new can of worms.

If you need to layout one control on top of another, use a canvas control.

I'm not sure if you wish to place the scrollbar of the scrollviewer on top of the content - if so answer 1, if you want the whole scrollViewer ontop of the content see answer 2.

1) You can change the visual representation of anything in WPF by applying a template. The trick in this case is to find what the existing representation of the ScrollViewer is, and then essentially re-implement all the same visuals just changeing the position of the ScrollBar as required. There are a couple of ways of finding all the visuals for a control - the easiest is from the WPF MSDN Samples - and nicely enough the ScrollViewer example provided by Microsoft shows how to change the position of the scrollbar.

BTW Microsoft tend to load their examples with lots of extra Xaml that you don't really need - play (ruthlessly cut out code) with the template until it does just what you want and no more.

2) My approach to placing the scroll view ontop of the content, would be to use two scrollviewers placed on top of each other. The 'top' is small, translucent (opacity = 50) and handles scrolling, the bottom is larger and has the document. Wire the scroll event from the top ScrollViewer so that it will also scroll the bottom one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top