
Notes for building/running the sample project
- 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.
- You need the June CTP version of the .NET 3.0 Runtime as well the SDK.
- You need to change the path to the image in the XAML to point to a valid image file.
- 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.

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.
<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

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.
<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.

Here's the XAML code that achieves the above transformation.
<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 :
- A
ScaleTransform to mirror-invert the ListBox
- A
TranslateTransform to move the object back to the visible window
Here's what the final effect looks like.

And here's the code that achieves the above effect.
<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.

The XAML for the above effect is shown below.
<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.
<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:
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 :
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:
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:
<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:
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
| You must Sign In to use this message board. |
|
|
 |
|
 |
Hi, I have installed Visual Studio 2005 in WindowsXP. but when i tried to load the project, it's failed. Saying that, it is not possible to load the project in the current installation. what may be the reason?
SaRath.
"Where I am from, there is no plan B. So, take advantage of today becuase tomorrow is not promised. - 50 Cent"
My Blog | Understanding State Pattern
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Sarath. wrote: what may be the reason
You also need to install WPF, it's not part of VS 2005. There's a runtime, an add in for VS2005 and an SDK.
You could just download Expression instead.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Nish and Christian,
I'm glad to know that you guys are writing the CP WPF series. Keep up the great work!
On a side note, I find this use of transforms[^](by Charles Petzold) to be deviously brilliant. I just thought that the message board of your article seemed like a good place to point out this oddity.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
After sleeping on it, I came up with an idea for your next article in the series, something I feel would be a bit more practical. Take a look at the calculator using VG.net[^]. Besides the eye candy, what I'd like to see in a WPF/XAML app is:
1. re-use of a styles (for example, the 0-9 buttons are all the same style except for the text) 2. overriding a specific style attribute (for example, the operator buttons are different shade than the number buttons) 3. changing a style attribute for a mouse hover and mouse down events 4. connecting the event in XAML to imperative code 5. since it's all VG, the calculator should be fully scalable. I really like the idea of making a window smaller but so that everything is scaled, rather than minimizing/maximizing as the only to options. You shouldn't have to write a line of code for scaling to work, right? 6. extensibility--if I want to add more buttons to your calculator, how can that be done? Does XAML directly support XML include/import syntax, or does it have to be done imperatively? 7. Can the calculator be set up as a widget that could, for example, easily be added to my own application? If so, how do you write WPF components/widgets? 8. Rather than hand-coding the XAML directly, what tools did you use? (Really, handcoding XAML is simply out of the question for "real" applications). 9. Overriding the style so I can have my own custom look without recoding the whole XAML. For example, at the bottom of Frank's article, he talks about customizing the XAML the calculator with automatic style switching.
Note, I'm not intending for this to be a competition between VG.net and XAML, I'm just looking at what VG.net does, and some the things I know I'd like to do, and putting together a requirements list to see how WPF works.
At some point, when I get into WPF/XAML, those are the first questions I'm going to be looking at, and I think it would make a great article. Forget all the rotation/transformation stuff--that's a dime-a-dozen out there on the web already. 
Marc
XPressTierSome people believe what the bible says. Literally. At least [with Wikipedia] you have the chance to correct the wiki -- Jörgen Sigvardsson
People are just notoriously impossible. --DavidCrow
-- modified at 7:36 Saturday 22nd July, 2006
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hi Marc. I see that you're really going to be keeping us honest in here :P
Marc Clifton wrote: Forget all the rotation/transformation stuff--that's a dime-a-dozen out there on the web already.
Nish and I talked about this, our feeling is that we want to fairly quickly move through the absolute basics, so that we end up with a complete series here on CP. That's why the articles are numbered as well, for those who want to work through them.
Marc Clifton wrote: re-use of a styles
Using WPF to style an application is almost certainly article #3, because I think it's a real selling point. I'm happy to use your calculator example, it saves me from thinking of something else. I can't promise to touch on all that you've mentioned ( for example, I have no idea about XML import syntax, but I doubt it ).
Marc Clifton wrote: Rather than hand-coding the XAML directly, what tools did you use?
To be honest, the XAML editing tools are a bit hideous still. I use Visual Studio mostly, because it allows me to hand edit and preview my work. Expression does allow WYSIWYG editing, but the text editor is less functional than Notepad ( it doesn't have search ), and I am the sort of person who inevitably ends up wanting to hand edit stuff, especially as Expression has the annoying habit of specifying margins like 24.9934723473572375234.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Christian Graus wrote: I see that you're really going to be keeping us honest in here
Yeah, sorry about that. Actually, I just realized the title was "Part I". Well, from my perspective, I've seen a lot of what amounts to me as useless drivel about XAML and WPF with regards to VG and UI's coming from various bloggers out there, and I'm prodding you guys simply because I want to see something useful besides fancy chess pieces and skewed transluscent windows. The fact that two of the top experts here at CP are writing these articles makes me very hopeful. 
Marc
XPressTierSome people believe what the bible says. Literally. At least [with Wikipedia] you have the chance to correct the wiki -- Jörgen Sigvardsson
People are just notoriously impossible. --DavidCrow
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Marc Clifton wrote: I'm prodding you guys simply because I want to see something useful besides fancy chess pieces and skewed transluscent windows.
*grin* I would agree, we're under no illusions as to the world needing this specific article, it's here to make the series complete.
And given your expertise, I appreciate your ideas, we certainly don't have a complete road map at this stage, just an intention of writing a comprehensive series that rises above the 'look how funny my window looks' type articles.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Marc Clifton wrote: Forget all the rotation/transformation stuff--that's a dime-a-dozen out there on the web already.
When I looked at the article I had exactly the same feeling. I am bored by seeing all the rotation/transform/scale tutorials. The MSDN documents and samples have been pretty good. Your suggestions are excellent. Sadly I must say that I have been disappointed with this article especially because it is by two seasoned CP vets. The article got only 4 not 5 from me.
My suggestion would be to have something in the lines of Mike Dunn's WTL for MFC programmers.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Rama Krishna Vavilala wrote: Sadly I must say that I have been disappointed with this article especially because it is by two seasoned CP vets.
I apologise for disappointing you. As I said elsewhere, we want to do a comprehensive series on WPF, so we're starting with stuff we know is covered elsewhere, just so anyone on CP who wants to learn WPF could concievably do it from scratch using our articles in sequence order. I suggest you jump in around article 4 or 5, I hope things will be more interesting for you by then.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I realize that it makes for a cool demo, but can you think of an application where you'd actually do transformations on a listbox? This is not a criticism, but a suggestion--I'd like to see something a bit more useful from all the WPF/XAML articles I've been noticing.
Marc
XPressTierSome people believe what the bible says. Literally. At least [with Wikipedia] you have the chance to correct the wiki -- Jörgen Sigvardsson
People are just notoriously impossible. --DavidCrow
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
The second part of the article shows transforming an image, which seems more likely to happen. The transformations on a listbox serve to show that you can transform pretty much anything. I'd agree, it's going to be rare that you'd want to do this, with the exception that I expect to do this to controls often, within an animation, to animate the changing of views in a form, etc. IMO one of the things that's really cool about WPF is the ability to write little, 1/4 second animations that make the UI look super slick.
This article was also very limited, by definition. Nish and I hope to write a pretty decent sized series on WPF, and the intention is that as the scope widens, the examples will become more and more 'real world'.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Well, what they have basically done is to get rid of the basis of windows apps as we know them ( everything is a window/has a HWND ), and use DirectX to draw the UI. This is a pretty open approach, and it's open to a lot of abuse. However, it's also very powerful. I also like the idea that my buttons do not have a HWND that can be found and interacted with, for example 
I would concur ( as I said above ) that rotating controls are not a great idea, with the caveat that I like the idea of controls animating when they come into view, etc. But I'm always in favour of the system giving me abilities that I can abuse, rather than trying to make sure I can walk the 'right line'. That's why I like C++. Sure, WPF has facilities that will result in some hideous UIs. I bet it also results in some pretty special ones.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|