On a recent project, I was tasked with adding pinch-to-zoom for images that would be displayed in a WinRT app. Since this feature doesn’t come for free I started thinking of ways to handle the gesture input and apply the appropriate amount of scaling while still playing by the rules of MVVM. Much to my delight, I soon discovered that the ScrollViewer can handle this sort of thing be default. For the purpose of scaling an image, you’ll want to disable the Vertical and Horizontal scroll bars, and use an Image control as the content of the Scroll Viewer. The key properties on the ScrollViewer you’ll want to use to control the zoom level are MinZoomFactor and MaxZoomFactor. The defaults are 0.1 and 10, respectively, but in my case I needed to set the MaxZoom based on the resolution of the image itself. There are a number of ways to do this, and my solution uses a custom control for it. Here’s what the logic for that looks like in my control…….
This is the handler for the Opened event of the Image control. The Source property you see on the first line is a Dependency Property I exposed on this custom control to expose the Image Source property. The first if statement checks to see if the image is smaller than the screen in both directions, in which case I display the image at native size with no scaling. The next block handles images that are larger than the screen in either or both directions. In that case, I divide the bitmap pixel width and pixel height by the actual rendered width and height of the ScrollViewer and use the larger value as the MaxZoomFactor. The end result is that the image is scalable up to it’s native size. Here’s what the xaml of my default control template looks like…..
And that’s all there is to it! If you don’t want / need to go down the custom control path, you can very easily just use the ScrollViewer and Image controls and set the zoom values directly in Xaml or data bind them. Either way is much easier than handling the gestures and scaling manually.