private void set(ScrollChangedEventArgs e, ScrollViewer sv, Canvas canvas) { if (e.ExtentHeightChange != 0 || e.ExtentWidthChange != 0) { Point? targetBefore = null; Point? targetNow = null; if (!lastMousePositionOnTarget.HasValue) { if (lastCenterPositionOnTarget.HasValue) { var centerOfViewport = new Point(sv.ViewportWidth / 2, sv.ViewportHeight / 2); Point centerOfTargetNow = sv.TranslatePoint(centerOfViewport, canvas); targetBefore = lastCenterPositionOnTarget; targetNow = centerOfTargetNow; } } else { targetBefore = lastMousePositionOnTarget; targetNow = Mouse.GetPosition(canvas); lastMousePositionOnTarget = null; } if (targetBefore.HasValue) { double dXInTargetPixels = targetNow.Value.X - targetBefore.Value.X; double dYInTargetPixels = targetNow.Value.Y - targetBefore.Value.Y; double multiplicatorX = e.ExtentWidth / canvas.Width; double multiplicatorY = e.ExtentHeight / canvas.Height; double newOffsetX = sv.HorizontalOffset - dXInTargetPixels * multiplicatorX; double newOffsetY = sv.VerticalOffset - dYInTargetPixels * multiplicatorY; if (double.IsNaN(newOffsetX) || double.IsNaN(newOffsetY)) { return; } sv.ScrollToHorizontalOffset(newOffsetX); sv.ScrollToVerticalOffset(newOffsetY); } } }