WPF - Zooming in on an image inside a scroll viewer, and having the scrollbars adjust accordingly
You should be using LayoutTransform
instead of RenderTransform
on your Image.
RenderTransform
happens after layout completes and is visual only. LayoutTransform
is done before the layout pass and so can notify the ScrollViewer
of the new size.
See here for more info: http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.layouttransform.aspx
For pure scrolling I'd rather use a ScaleTransform, it should adjust the scrollbars accordingly.You can try below code if it fixes your issue.
private double _zoomValue = 1.0;private void UIElement_OnMouseWheel(object sender, MouseWheelEventArgs e){ if (e.Delta > 0) { _zoomValue += 0.1; } else { _zoomValue -= 0.1; } ScaleTransform scale = new ScaleTransform(_zoomValue, _zoomValue); MyImage.LayoutTransform = scale; e.Handled = true;}
Let's assume you have a Canvas_Main inside a ViewBox_CanvasMain, which in turn inside a ScrollViewer_CanvasMain. You want to zoom in by turning the mouse wheel, and the ScrollViewer will adjust the offset automatically so the feature (pointed by the mouse in the Canvas_Main) stays during the zoom in/out. It is complex but here is the code called by the mouse wheel eventhandler:
private void MouseWheelZoom(MouseWheelEventArgs e) { if(Canvas_Main.IsMouseOver) { Point mouseAtImage = e.GetPosition(Canvas_Main); // ScrollViewer_CanvasMain.TranslatePoint(middleOfScrollViewer, Canvas_Main); Point mouseAtScrollViewer = e.GetPosition(ScrollViewer_CanvasMain); ScaleTransform st = ViewBox_CanvasMain.LayoutTransform as ScaleTransform; if (st == null) { st = new ScaleTransform(); ViewBox_CanvasMain.LayoutTransform = st; } if (e.Delta > 0) { st.ScaleX = st.ScaleY = st.ScaleX * 1.25; if (st.ScaleX > 64) st.ScaleX = st.ScaleY = 64; } else { st.ScaleX = st.ScaleY = st.ScaleX / 1.25; if (st.ScaleX < 1) st.ScaleX = st.ScaleY = 1; } #region [this step is critical for offset] ScrollViewer_CanvasMain.ScrollToHorizontalOffset(0); ScrollViewer_CanvasMain.ScrollToVerticalOffset(0); this.UpdateLayout(); #endregion Vector offset = Canvas_Main.TranslatePoint(mouseAtImage, ScrollViewer_CanvasMain) - mouseAtScrollViewer; // (Vector)middleOfScrollViewer; ScrollViewer_CanvasMain.ScrollToHorizontalOffset(offset.X); ScrollViewer_CanvasMain.ScrollToVerticalOffset(offset.Y); this.UpdateLayout(); e.Handled = true; } }