title: WPF Scrollviewer scroll to mouse position
body: <p>I am working on an image viewer control that consists of an image inside of a scrollviewer.
  To zoom, I use a scaletransform within the image's layouttransform.
  Zoomin is happening on mouse click. If the user clicks on the image, I would like the pixel at the mouse position to be located at the center of the visual area of the scrollviewer.
  To achieve this I want to modify the scrollviewer offsets, but I am not sure about how to calculate the correct offset that places the pixel unter the mouse pointer at the center.</p>
  
  <p><a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5202aae5-b2cc-4fc3-aa43-4541fcc856fb" rel="noreferrer">Here</a> is a description of how to keep the scrollbars at their relative position. That works fine, but is not what I am looking for.</p>
  
  <p>How do you calculate the offsets correctly?</p>
  
  <p>Here is some of my code:</p>
  
  <p>The xaml:</p>
  
  <pre><code>&lt;ScrollViewer Margin="5" Name="scrvImagePanel" VerticalAlignment="Stretch" 
                    CanContentScroll="True"
                    DockPanel.Dock="Left" 
                    HorizontalAlignment="Stretch" 
                    HorizontalContentAlignment="Stretch"
                    HorizontalScrollBarVisibility="Auto" 
                    VerticalContentAlignment="Stretch" 
                    VerticalScrollBarVisibility="Auto"
                    Background="{StaticResource {x:Static SystemColors.ControlDarkBrushKey}}"
                    ScrollChanged="OnScrollChanged"&gt;
          &lt;Image Name="imgPicture"
                 MouseUp="imgMouseUp" 
                 Stretch="None"
                 HorizontalAlignment="Left" 
                 VerticalAlignment="Top" 
                 &gt;
              &lt;Image.LayoutTransform&gt;
                  &lt;TransformGroup&gt;
                  &lt;ScaleTransform x:Name="imgZoomTransform" ScaleX="1" ScaleY="1"&gt;&lt;/ScaleTransform&gt;
                  &lt;/TransformGroup&gt;
              &lt;/Image.LayoutTransform&gt;                
          &lt;/Image&gt;
      &lt;/ScrollViewer&gt;
  </code></pre>
  
  <p>and the code:</p>
  
  <pre><code>private void imgMouseUp(object sender, MouseButtonEventArgs e)
  {
     Point absScreenPos = e.GetPosition(imgPicture);
  
      //calculate the new zoom factor
      this.ZoomFactor = imgZoomTransform.ScaleX;
      if (e.ChangedButton == MouseButton.Right)
      {
        this.ZoomFactor /= 2.0;
      }
      else if (e.ChangedButton == MouseButton.Left)
      {
        this.ZoomFactor *= 2.0;
      }
  
      //perform the zooming
      this.DoZoom(this.ZoomFactor, absScreenPos.X, absScreenPos.Y);
  
  }
  
  private void DoZoom(double zoom, double posX, double posY)
  {
    // update the scale transform
    imgZoomTransform.ScaleX = zoom;
    imgZoomTransform.ScaleY = zoom;
  
    this.AdjustScroll(new Point(posX, posY));
  }
  
  
  private void AdjustScroll(Point? centerPoint)
  {
    if(centerPoint != null)
    {
      var sv = this.scrvImagePanel;
  
      double offsetX = (centerPoint.Value.X / this.imgPicture.ActualWidth) * sv.ActualWidth;
      double offsetY = (centerPoint.Value.Y / this.imgPicture.ActualHeight) * sv.ActualHeight;
  
      sv.ScrollToHorizontalOffset(offsetX);
      sv.ScrollToVerticalOffset(offsetY);
    }
  }
  </code></pre>