WPF/Silverlight: Zoom image using databinding

Databinding is a major and powerful aspect of WPF/Silverlight. I use it often together with datatemplates to represent data on a form but in this post I’ll show you how to use it when binding to the property of another control.

Binding to a property can be very cool as you don’t need to do any code-behind work like formatting and events, everything is done in XAML.

The general syntax to bind a property of one control to the value of a property of another control is the following:

{binding <property>, ElementName=<name of control>}

Say you want to bind the text property of a textblock to the text in a textbox named txtText, you’d write:

<TextBlock [other properties] Text="{Binding Text, ElementName txtText}" />

When you’d run the application you’ll see the text in the textblock changed when you type in the textbox. Much as many other WPF/Silverlight concepts, you can use this in any way you can imagine. In traditional WinForms, you had to use the TextChanged event of the textbox to manually update the textblock’s text, but now no C# code in involved!

The goal of this post was to show you how to use the above concepts to create a zoom slider for an image using databinding.

When you create a new WPF/Silverlight project, you’ll see the image object doesn’t expose any direct functionality to zoom in/out. There’s a way to do this by using a RenderTransform on the image, more specifically a ScaleTransform. Here’s the XAMl code how to do this:

<Image HorizontalAlignment="Left" Margin="0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Source="/ZoomBinding;component/lake.jpg">
<Image.RenderTransform> 
<ScaleTransform ScaleX="2" ScaleY="2" /> 
</Image.RenderTransform> 
</Image>

Now you’ll see the scale of your image has been doubled. There’s an annoying problem though, with the size being doubled, the image takes up lots of more space on the form. We need a way to show only a part of the zoomed image, with the rest of the image hidden. As a webdesigner, I immediately thought of wrapping it in some div (panel) and setting it’s overflow property to hidden, only showing as much of the image as the width and heigth of the div. In WPF, there are no divs, and unfortunately there isn’t an overflow property, luckily for us, there are numerous other containers, and there’s the ClipToBounds property. I’ve wrapped a wrappanel around my image and set its ClipToBounds property to true giving us the desired result.

Add an source image and slider to your form, and make sure your image resides in a container (WrapPanel, StackPanel,…) with its ClipToBounds property set to true. You should have something similar to this:

You might see where we’re going, we’re going to bind the above ScaleX and ScaleY properties to the value of a slider! Before we do that, we should set the minimum and maximum values of the scrollbar. The Minimum and Maximum values will do that for you. Your Minimum always needs to be 1, because if you’d use 0 as a scale, you’d end up with nothing. Even though it sounds small, I’ve found 3 to be a good Maximum, though experiment as you wish. Below is the complete XAML code, including binding the scrollbar value to the ScaleX and ScaleY values. You could use two scrollbars, but that would stretch your image making this beautiful lake ugly.

<Grid> 
<Slider Height="23" HorizontalAlignment="Left" Margin="10,220,0,0" Name="slider1" Minimum="1" Maximum="3" VerticalAlignment="Top" Width="305" /> 
<WrapPanel HorizontalAlignment="Left" Name="container" VerticalAlignment="Top" Margin="15,10,0,0" Background="Red" Width="300" ClipToBounds="True" Height="200"> 
<Image HorizontalAlignment="Left" Margin="0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Source="/AnotherBinding;component/lake.jpg"> 
<Image.RenderTransform> 
<ScaleTransform CenterX="150" CenterY="100" ScaleX="{Binding Value, ElementName=slider1}" ScaleY="{Binding Value, ElementName=slider1}" /> 
</Image.RenderTransform> 
</Image> 
</WrapPanel> 
</Grid>

Hit F5 and you’ll see it works, without using any C# code, there’s still one small problem: when zooming, the image will be aligned (zoomed in/out) to the upper-left corner. Could you think of some way to make it zoom in the direction of the center of the image as you can see below. Hint: check some of the other properties of the ScaleTransform 😉

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s