Silverlight Tip: Reflecting Objects Horizontally or Vertically using ScaleTransform

While working on a Silverlight application, I wanted to have two instances of a class which faced each other.  After exploring the available transforms, I eventually remembered how to do it simply by scaling the object in a negative direction.

First, we need an object to reflect.  You can reflect any control this way, be it a pre-built control or a custom control in your project.  To perform the reflection, we can use a ScaleTransform object. In the following, I've applied it to an Image:

 <Image x:Name="Reflectee"  Source="up.jpg" Height="50" Width="50" >
     <Image.RenderTransform>
         <ScaleTransform x:Name="AxisReflector" ScaleX="1" ScaleY="1"></ScaleTransform>
     </Image.RenderTransform>
 </Image>

Now, to reflect the image across either the X or Y axis, all we have to do is toggle the sign of the scale we're interested in (ScaleX or ScaleY).  By setting ScaleX to -1, we reflect horizontally; similarly, by setting ScaleY to -1, we reflect vertically.  To revert either to the original, simply set the scale back to 1.  Using any value other than 1 will scale the object accordingly.

It's important to note the effect of changing the center of the ScaleTransform.  The ScaleTransform by default sets its center at (0,0) relative to the object it applies to, which corresponds to the top-left corner of that object.  You can customize it by changing the CenterX and CenterY properties of the ScaleTransform object.  Because the scale operation occurs relative to that point, if you simply reflect an object, it won't necessarily reflect in place.  To offset that, you can set the center of the ScaleTransform to the middle of the image.  Note that the change will take place immediately, and any previous reflections with this ScaleTransform will be updated relative to the new coordinates.  That means that if you've reflected around one point, and then change the center to another point, the object will be updated to have the reflection around the second point.  For this demo, I've simply created a button to set the reflection point to the middle:

 private void SetReflectCenter_Click(object sender, RoutedEventArgs e)
 {
     AxisReflector.CenterX = Reflectee.ActualWidth / 2;
     AxisReflector.CenterY = Reflectee.ActualHeight / 2;
 }

You can also set the values outside of the dimensions of the object (either using negative values or values larger than the corresponding dimension) to reflect the object around a point outside of the object.

Sample app:

The code for this sample is available here

Comments