Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / WPF

WPF Tutorial - Part 1 : Transformations

,
Rate me:
Please Sign up or sign in to vote.
4.40/5 (56 votes)
28 Jun 2010CPOL6 min read 352.3K   7.9K   127   26
A brief introduction to using transformations with the WPF

Image 1

Notes for building/running the sample project

  1. You need to have Visual Studio 2005 as well as the Orcas tools for VS 2005. Alternatively you can also use Expression to run the sample.
  2. You need the June CTP version of the .NET 3.0 Runtime as well the SDK.
  3. You need to change the path to the image in the XAML to point to a valid image file.
  4. If you have an earlier or later CTP, most of the code should still compile the same - though you may have to make some namespace changes.

Introduction

Welcome to this, our first joint article on WPF, which is part of WinFX ( now called .NET 3.0, for reasons that are totally unclear to anyone with half a brain ). In this article we will cover transformations, both in XAML and in code. While this is a logical 'starting' topic, even here WPF shows its power over traditional windows programming, as these transformations can be applied to any element in your UI, creating effects that would have been close to impossible in traditional forms programming. The first part of the article will run you thgrough some transforms in XAML, and the second part will demonstrate a sample app that shows an image and allows you to set transform values with sliders, with the idea that being able to interact in this way will give you a stronger idea of what the transforms can do, both together and individually.

Rotation Transforms

The RotateTransform class is used to rotate a WPF object in an X-Y plane. It can be applied via XAML or directly via imperative code. For our examples, we'll use a WPF ListBox control and we'll apply a Rotation Transform to it. Here's what the ListBox would look like when a Rotation Transform of -20 degrees (20 degrees anti-clockwise) is applied to it.

Image 2

Compare the ListBox on the left which is rotated, with the one on the right (identical except that it's not rotated). And here's the XAML that achieves this.

XML
<ListBox Name="listBox1" FontSize="15" 
   Canvas.Bottom="140" Canvas.Left="30" 
    Canvas.Right="150" Canvas.Top="40">         
    <ListBoxItem IsSelected="True">Canada</ListBoxItem>
    . . .
    <ListBoxItem>Spain</ListBoxItem>    

    <ListBox.RenderTransform> *(1)*
            <RotateTransform Angle="-20" 
              CenterX="50" CenterY="50" /> *(2)*
    </ListBox.RenderTransform>
</ListBox>
  • (1) - We specify a RenderTransform on the object, which modifies how the object is rendered by the UI system. (This is in contrast to the LayoutTransform which doesn't affect rendering, but affects how the object is processed by the layout system)
  • (2) - We use a RotateTransform which lets us specify the angle of rotation in clock wise degrees. We can also optionally specify the X,Y point about which the object is rotated. Setting X and Y points equal to Width/2 and Height/2 will cause an object to 'spin' as opposed to rotate around an imaginary curve.

Later, we'll write a more flexible demo that demonstrates various transforms and how various properties can be applied to each of those transforms. Next let's look at a Scale Transform.

Scale Transforms

Image 3

In the above screenshot, you can see a Scale Transform that has stretched the ListBox on the left by 1.5 times in the X axis, and compressed it by 0.75 times in the Y axis. Here's the XAML that achieves this.

XML
<ListBox.RenderTransform>
    <ScaleTransform ScaleX="1.5" ScaleY="0.75"/>
</ListBox.RenderTransform>

We just replaced the Rotation Transform with a Scale Transform. Note that it's possible to apply multiple transforms on a single object, and we'll see that later. But before that, let's take a look at using the SkewTransform class.

Skew Transforms

Skew Transforms skew an object by specified X and Y angles, and can be used to create some fancy transformation effects (and are also used for animations). The following screenshot shows a skew transformation of 20 degrees in the X axis and 30 degrees in the Y axis.

Image 4

Here's the XAML code that achieves the above transformation.

XML
<ListBox.RenderTransform>
    <SkewTransform AngleX="20" AngleY="30"/>
</ListBox.RenderTransform>

Thus far we've only looked at single transformations on an object, next we'll look at how to achieve multiple transformations on an object.

Applying multiple transformations on an object

In the below example, we are going to apply two transforms on an object :

  1. A ScaleTransform to mirror-invert the ListBox
  2. A TranslateTransform to move the object back to the visible window

Here's what the final effect looks like.

Image 5

And here's the code that achieves the above effect.

XML
<ListBox.RenderTransform>
    <TransformGroup>
        <ScaleTransform ScaleX="-1" ScaleY="1" />
        <TranslateTransform X="100" />
    </TransformGroup>
</ListBox.RenderTransform>

Notice the use of the TransformGroup object that allows us to group multiple transforms and then apply them on a single object. Here's another example of multiple transforms on the list box, which tries to achieve a 3d effect.

Image 6

The XAML for the above effect is shown below.

XML
<ListBox.RenderTransform>
    <TransformGroup>
        <RotateTransform Angle="15" CenterY="30" />
        <SkewTransform AngleY="-45" />
    </TransformGroup>
</ListBox.RenderTransform>

A sample app to play around with transformations

Ok, now that we know how to do transforms, let's write a little app that we can use to interact with them, and see how they work. The sample app has an image in it, and here's how it is defined using XAML. You will need to modify the ImageSource property of the ImageBrush element to point to an image on your local hard disk. In the zip download, we have included the JPG image that we used, so you could use that if you want to.

XML
<Rectangle Stroke="#FF000000" HorizontalAlignment="Stretch" 
    VerticalAlignment="Stretch"
    Margin="198,80,260,230" Width="Auto" Height="Auto" x:Name="rect"> 
	<Rectangle.Fill>
    		<ImageBrush ImageSource="d:\toofast.jpg" /> 
	</Rectangle.Fill> 
</Rectangle>

You probably realize that we can define our transforms inside the XAML, but we're trying to show some operations within the code. So, we define the transforms like this:

C#
    private TransformGroup trGrp;
    private SkewTransform trSkw;
    private RotateTransform trRot;
    private TranslateTransform trTns;
    private ScaleTransform trScl;

public Scene1()
{
   this.InitializeComponent();

        trSkw = new SkewTransform(0, 0);
        trRot = new RotateTransform(0);
        trTns = new TranslateTransform(0, 0);
        trScl = new ScaleTransform(1, 1);

        trGrp = new TransformGroup();
        trGrp.Children.Add(trSkw);
        trGrp.Children.Add(trRot);
        trGrp.Children.Add(trTns);
        trGrp.Children.Add(trScl);
    }

This code creates the four possible transform objects and adds them to a TransformGroup. This group is now a member variable, it's initialized, but it's not associated with our object. To do this, we need to add the following to the opening tag for our XAML document :

XML
Loaded="OnSceneLoaded"

This has the effect of defining a method that will be called when the scene loads, and that method is defined as follows:

C#
private void OnSceneLoaded(object sender, System.Windows.RoutedEventArgs e) 
{ 
    rect.RenderTransform = trGrp; 
    slSclX.Value = slSclY.Value = 1; 
}

As you can see, this method assigns the transform group to the rectangle object, and sets initial slider values to the scaling sliders. The rest of the program logic is pretty simple : we just define a single method which sets all the transform values based on the various sliders, and hook all the value changed events on the sliders to the one method. An example XAML snippet goes like this:

XML
<Slider LargeChange="0.1" Maximum="50" Minimum="-50" SmallChange="0.1" 
   Name="slSkwX" ValueChanged="OnValueChanged" />

Some attributes have been removed to make the example clearer. Now we just need that central method:

C#
protected void OnValueChanged(object sender,
                         System.Windows.RoutedEventArgs e)
{
    trRot.Angle = slRot.Value;
    trRot.CenterX = slRotX.Value;
    trRot.CenterY = slRotY.Value;
    trScl.ScaleX = slSclX.Value;
    trScl.ScaleY = slSclY.Value;
    trScl.CenterX = slSclOX.Value;
    trScl.CenterY = slSclOY.Value;

    trSkw.AngleX = slSkwX.Value;
    trSkw.AngleY = slSkwY.Value;
    trSkw.CenterX = slSkwOX.Value;
    trSkw.CenterY = slSkwOY.Value;

    trTns.X = slTrnX.Value;
    trTns.Y = slTrnY.Value;
}

Now all our transform values will be set whenever you move any slider. This is arguably inefficient, but it does simplify the code for this example.

Conclusion

As was stated in the introduction, the real power of WPF becomes apparent pretty quickly, even this simple example shows off things that under 'traditional' development would be a lot of work. However, we've really only just begun, our next article on animation will really start to show what's possible with this new framework.

History

  • Jul 21, 2006 - Article first published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
Programming computers ( self taught ) since about 1984 when I bought my first Apple ][. Was working on a GUI library to interface Win32 to Python, and writing graphics filters in my spare time, and then building n-tiered apps using asp, atl and asp.net in my job at Dytech. After 4 years there, I've started working from home, at first for Code Project and now for a vet telemedicine company. I owned part of a company that sells client education software in the vet market, but we sold that and I worked for the owners for five years before leaving to get away from the travel, and spend more time with my family. I now work for a company here in Hobart, doing all sorts of Microsoft based stuff in C++ and C#, with a lot of T-SQL in the mix.

Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions

 
QuestionHow to rotate Line around its first point? Pin
aruyc2-Jun-16 23:58
aruyc2-Jun-16 23:58 
GeneralMy vote of 2 Pin
smton20-Aug-13 12:54
smton20-Aug-13 12:54 
GeneralRe: My vote of 2 Pin
Christian Graus20-Aug-13 12:55
protectorChristian Graus20-Aug-13 12:55 
GeneralRe: My vote of 2 Pin
Nish Nishant21-Aug-13 4:18
sitebuilderNish Nishant21-Aug-13 4:18 
GeneralMy vote of 5 Pin
Christian Amado20-Aug-12 10:02
professionalChristian Amado20-Aug-12 10:02 
QuestionWhy the line is not smooth after rotation? Pin
Naresh Goradara22-Apr-12 19:42
Naresh Goradara22-Apr-12 19:42 
AnswerRe: Why the line is not smooth after rotation? Pin
Christian Graus22-Apr-12 19:44
protectorChristian Graus22-Apr-12 19:44 
GeneralRe: Why the line is not smooth after rotation? Pin
Naresh Goradara22-Apr-12 19:52
Naresh Goradara22-Apr-12 19:52 
GeneralRe: Why the line is not smooth after rotation? Pin
Naresh Goradara23-Apr-12 0:25
Naresh Goradara23-Apr-12 0:25 
GeneralMy vote of 5 Pin
Raj Pratap16-Jun-11 8:45
Raj Pratap16-Jun-11 8:45 
GeneralProblems in Opening project Pin
Sarath C4-Aug-06 2:02
Sarath C4-Aug-06 2:02 
GeneralRe: Problems in Opening project Pin
Christian Graus4-Aug-06 3:20
protectorChristian Graus4-Aug-06 3:20 
GeneralRe: Problems in Opening project Pin
dakeefer28-Jun-10 7:37
dakeefer28-Jun-10 7:37 
AnswerRe: Problems in Opening project Pin
Nish Nishant28-Jun-10 7:45
sitebuilderNish Nishant28-Jun-10 7:45 
GeneralA mind-bending use of transforms Pin
Josh Smith30-Jul-06 14:22
Josh Smith30-Jul-06 14:22 
GeneralSuggestion for next article [modified] Pin
Marc Clifton22-Jul-06 1:31
mvaMarc Clifton22-Jul-06 1:31 
GeneralRe: Suggestion for next article Pin
Christian Graus22-Jul-06 1:44
protectorChristian Graus22-Jul-06 1:44 
GeneralRe: Suggestion for next article Pin
Marc Clifton22-Jul-06 6:31
mvaMarc Clifton22-Jul-06 6:31 
GeneralRe: Suggestion for next article Pin
Christian Graus22-Jul-06 12:17
protectorChristian Graus22-Jul-06 12:17 
GeneralRe: Suggestion for next article Pin
Rama Krishna Vavilala22-Jul-06 6:32
Rama Krishna Vavilala22-Jul-06 6:32 
GeneralRe: Suggestion for next article Pin
Christian Graus22-Jul-06 12:19
protectorChristian Graus22-Jul-06 12:19 
QuestionWhy would you transform a ListBox? Pin
Marc Clifton21-Jul-06 13:06
mvaMarc Clifton21-Jul-06 13:06 
AnswerRe: Why would you transform a ListBox? Pin
Christian Graus21-Jul-06 13:26
protectorChristian Graus21-Jul-06 13:26 
GeneralRe: Why would you transform a ListBox? Pin
Jamie Nordmeyer21-Jul-06 19:52
Jamie Nordmeyer21-Jul-06 19:52 
I'm amazed that Microsoft put so much time and effor (and money) in to allow controls to be rotated in the first place. Don't get me wrong. The demo was great. It just seems that Microsoft's decision to do this in the first place was ill-placed. I'd rather they created a built in skinning framework where a user can literally tell the OS that they'd like all borders to use this bitmap, all buttons to use this gradient, but THIS gradient when you hover, or maybe scratch the rectangle, and allow the user to specify a round button.

Kyosa Jamie Nordmeyer - Taekwondo Yi (2nd) Dan
Portland, Oregon, USA

GeneralRe: Why would you transform a ListBox? Pin
Christian Graus21-Jul-06 23:36
protectorChristian Graus21-Jul-06 23:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.