Pergunta

Gostaria de colocar meu scrollViewer de tal maneira que ele se sobreponda/fica na parte superior do conteúdo que ele rola. Eu definiria a opacidade do scrollViewer para que o conteúdo seja visível por baixo.

Até onde eu entendo o scrollViewer padrão, isso não parece ser possível fora da caixa, pois o conteúdo está aninhado dentro do scrollViewer.

Alguma idéia de como fazer isso funcionar?

EDIT: Entendo que o ScrollViewer é um decorador e que o conteúdo não está ciente do ScrollViewer. Essa separação é boa e não quero que o conteúdo esteja ciente do scrollViewer. O que tento fazer é uma coisa puramente visual (layout). Basta mostrar o scrollViewer no topo do conteúdo. O comportamento do scrollViewer deve permanecer inalterado.

Foi útil?

Solução

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.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top