XAML: make a ScrollViewer show scrollbars when the ScaleTransform of a child object gets big

scaletransform, scrollviewer, silverlight, silverlight-3.0, xaml

Solution

Yeah, the problem is that there is no `LayoutTransform` in Silverlight. There are some workarounds to this problem listed here.

The idea here is to provide an intermediate canvas that gets resized and as a result, resizes the scrollable area. For example, if I have the following XAML:

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="200" />
        <RowDefinition Height="25" />
    </Grid.RowDefinitions>
        <ScrollViewer Grid.Row="0" x:Name="sc" VerticalScrollBarVisibility="Auto" 
                      HorizontalScrollBarVisibility="Auto" Width="200" Height="200" >
        <Canvas x:Name="sizer" Width="200" Height="200">
            <Rectangle x:Name="gradientRect" Width="200" Height="200">
            <Rectangle.RenderTransform>
                <ScaleTransform ScaleX="1" ScaleY="1"/>
            </Rectangle.RenderTransform>
                <Rectangle.Fill>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                        <GradientStop Color="Red" Offset="0.1"/>
                        <GradientStop Color="Yellow" Offset="0.5"/>
                        <GradientStop Color="Red" Offset="0.9"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>
        </Canvas>
    </ScrollViewer>
    <Button Grid.Row="1" Content="Multiply by Two" Click="ScaleRect" Width="100" Height="25"></Button>
</Grid>

You'll notice that I put the `<Canvas x:Name="sizer"/>` between the `<ScrollViewer/>` and `<Rectangle/>` and the click event of `ScaleRect` in the `<Button/>`.

The `ScaleRect` sub simply scales the rectangle by 2. That value is then used to change the `sizer` `Width` and `Height`, thus updating the ScrollViewer's scrollbars. Here's the sub for `ScaleRect`:

Private Sub ScaleRect(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim zoom As Double = 2.0
    Dim scaleX = gradientRect.RenderTransform.GetValue(ScaleTransform.ScaleXProperty)
    Dim scaleY = gradientRect.RenderTransform.GetValue(ScaleTransform.ScaleYProperty)
    gradientRect.RenderTransform.SetValue(ScaleTransform.ScaleXProperty, scaleX * zoom)
    gradientRect.RenderTransform.SetValue(ScaleTransform.ScaleYProperty, scaleY * zoom)
    sizer.Height *= zoom
    sizer.Width *= zoom
End Sub

Problem

I am making a sort of "print preview" control for some documents in my Silverlight 3 application. I have a Canvas (for showing the document) inside of a ScrollViewer, and I have zoom in / zoom out buttons that control the X and Y Scale properties of the ScaleTransform for the Canvas.RenderTransform property. I want the scrollbars of the ScrollViewer to show up when I "zoom in" enough such that the canvas is no longer visible in the ScrollViewer area, but it seems that they only show up depending on the Width/Height of the Canvas itself, regardless of whether it is zoomed in or not. Can anyone help?

Original source