1
votes

So I have a Grid>Canvas>Image which I've placed inside a scrollviewer.

I have placed a RenderTransform> ScaleTransform into Grid and am using mousewheel event over it to scale it.

When I use it, it's zooms in and out, but the scrollviewer keeps it's initial setting which seems to me that the actual width and height are not changing when I scale (which I don't want to change anyway).

The idea I want though is to scale the scrollviewer range as well by the same percent as the grid tying the scaled Width and scaled Height to.

I was looking at ScrollViewer class in MSDN and can't find where the range of the scrollviewer is saved. I'm looking at ExtentHeight and ExtentWidth, at ScrollableHeight and ScrollableWidth but I'm sort of fumbling in the dark.

How can I programmatically get the pixel/numerical range of the scrollViewer horizontal and vertical bars? How can I change them? I want to do this on the mousewheel event of the grid.

What is the practical difference between: ViewportWidth, ExtentWidth, ScrollableWidth, Width?

XAML:

<ScrollViewer Grid.Row="0" Grid.Column="1" Name="sourcePicScroll" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Height="Auto" Width="Auto">
        <Grid Name="sourceGrid" Background="Gray" MouseWheel="sourceGrid_MouseWheel">
            <Grid.RenderTransform>
                <ScaleTransform x:Name="sourceGridScaleTransform"/>
            </Grid.RenderTransform>
           <Canvas Name="sourceCanvas" Width="0" Height="0" Background="White" MouseMove="sourceCanvas_MouseMove" PreviewMouseLeftButtonDown="sourceCanvas_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="sourceCanvas_PreviewMouseLeftButtonUp" HorizontalAlignment="Left" VerticalAlignment="Top" MouseWheel="sourceCanvas_MouseWheel">
                <Canvas.RenderTransform>
                    <ScaleTransform x:Name="sourceScaleTransform"/>
                </Canvas.RenderTransform>
                <Image Name="sourcePic" HorizontalAlignment="Left" VerticalAlignment="Top" Panel.ZIndex="1" Stretch="None"></Image>
                <Rectangle Name="sourceSelectionBox" Visibility="Collapsed" Stroke="Black" StrokeThickness="1" Panel.ZIndex="50"/>
                <Ellipse Name="sourceSelectionEllipse" Visibility="Collapsed" Stroke="Black" StrokeThickness="1" Panel.ZIndex="51"/>
            </Canvas>
        </Grid>
    </ScrollViewer>

C# code:

double ScaleRate = 1.1;
        if (e.Delta > 0)
        {
            sourceGridScaleTransform.ScaleX *= ScaleRate;
            sourceGridScaleTransform.ScaleY *= ScaleRate;
        }
        else
        {
            sourceGridScaleTransform.ScaleX /= ScaleRate;
            sourceGridScaleTransform.ScaleY /= ScaleRate;
        }
1

1 Answers

5
votes

Two problems

  1. Render transform only apply to the rendering which does not affect the layout hence scroll viewer does not reflect the same
  2. Canvas does not have a size, defaults to 0 so applying a transform does not affect canvas sizing unless a size is specified on the canvas.

since you are not using any canvas properties on children you can safely remove the same unless needed.

so you may try this sample

<ScrollViewer Grid.Row="0"
              Grid.Column="1"
              Name="sourcePicScroll"
              VerticalScrollBarVisibility="Visible"
              HorizontalScrollBarVisibility="Visible"
              Height="Auto"
              Width="Auto">
    <Grid Name="sourceGrid"
          HorizontalAlignment="Left"
          VerticalAlignment="Top"
          Background="Gray"
          MouseWheel="sourceGrid_MouseWheel">
        <Grid.LayoutTransform>
            <ScaleTransform x:Name="sourceGridScaleTransform" />
        </Grid.LayoutTransform>
        <Image Name="sourcePic"
               HorizontalAlignment="Left"
               VerticalAlignment="Top"
               Panel.ZIndex="1"
               Source="pr.png"
               Stretch="None"></Image>
        <Rectangle Name="sourceSelectionBox"
                   Visibility="Collapsed"
                   Stroke="Black"
                   StrokeThickness="1"
                   Panel.ZIndex="50" />
        <Ellipse Name="sourceSelectionEllipse"
                 Visibility="Collapsed"
                 Stroke="Black"
                 StrokeThickness="1"
                 Panel.ZIndex="51" />
    </Grid>
</ScrollViewer>

changes are

  • RenderTransform to LayoutTransform

  • added HorizontalAlignment="Left" & VerticalAlignment="Top" to grid

  • removed inner canvas

give it a try and see if this is what you are looking for, note that mouse wheel will only work on the inner grid.

here is a modified sample if you need the scroll to work on full scroll viewer

<Grid>
    <ScrollViewer Grid.Row="0"
                  Grid.Column="1"
                  Name="sourcePicScroll"
                  VerticalScrollBarVisibility="Visible"
                  HorizontalScrollBarVisibility="Visible"
                  Height="Auto"
                  Width="Auto">
        <Grid Name="sourceGrid"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Background="Gray">
            <Grid.LayoutTransform>
                <ScaleTransform x:Name="sourceGridScaleTransform" />
            </Grid.LayoutTransform>
            <Image Name="sourcePic"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Panel.ZIndex="1"
                   Source="pr.png"
                   Stretch="None"></Image>
            <Rectangle Name="sourceSelectionBox"
                       Visibility="Collapsed"
                       Stroke="Black"
                       StrokeThickness="1"
                       Panel.ZIndex="50" />
            <Ellipse Name="sourceSelectionEllipse"
                     Visibility="Collapsed"
                     Stroke="Black"
                     StrokeThickness="1"
                     Panel.ZIndex="51" />

        </Grid>
    </ScrollViewer>
    <Grid MouseWheel="sourceGrid_MouseWheel"
          Background="Transparent"></Grid>
</Grid>