WPF Intro Part 1
WPF Intro Part 1
Goals:
Introduce the XAML syntax.
Creating applications with XAML.
Using XAML with custom types.
Overview:
This lab will introduce you to building applications with WPF. The application here is very
simple and is used to show how different source files (XAML and C#) come together to create a
single application. You are encouraged to experiment with the code and XAML and deviate
from the lab instructions to customize your resulting application.
In this first part you will write a simple XAML application and view it inside Internet Explorer.
Steps:
1. Create a new file with a .XAML extension. Open it with your favorite XML editor.
a. Most people tend to prefer Visual Studio, but you can use any text-based editor.
Another common tool is XamlPad which is available in the Windows SDK.
2. In this XML file, add a Canvas element. The namespace for Canvas is
“http://schemas.microsoft.com/winfx/2006/xaml/presentation”
3. In the Canvas element, add a Rectangle element. For the rectangle to be visible,
you'll need to set its Width, Height and Fill properties.
a. Set the Width to “300”.
b. Set the Height to “200”.
c. Set the Fill property to “Orange”.
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Width="300" Height="200" Fill="Orange" />
</Canvas>
In this part, you'll set complex and attached properties using XAML.
Steps:
1. Create a new file with a .XAML extension and copy the content of the previous part.
2. Having a solid color background is pretty boring. Your job is to change the background
brush to a gradient brush.
3. In the previous example, the color “Orange” was automatically transformed into a brush.
However, if the background is a gradient, it is not possible to express its value through a
simple string.
4. Replace the Fill property value with a LinearGradientBrush object. In XAML, a
property may be set to a complex object using an inner XML element where the name is
specified in the form Type.Property. In this case, the element name should be
<Rectangle.Fill>.
5. Set the Fill property to a gradient from Orange to Blue.
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Width="300" Height="200">
<Rectangle.Fill>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Orange" />
<GradientStop Offset="1" Color="Blue" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Canvas>
8. Save the file and open it using Internet Explorer. As expected, the rectangle has moved
away from the corner of the window.
In the previous parts, the application did not contain any code. In this part, you'll create a
Windows application that calls C# code in response to UI events.
Steps:
1. Create a new WPF Windows application project and name it MyWindowsApplication.
If you are on an older version of VS.NET, the project templates are installed with the WPF/WCF
“Cider” add-in for Visual Studio 2005. If you do not have a “.NET Framework 3.0” section under
the Visual C# project types, then it is likely the add-in has not been installed.
16. Compile and test. Verify that the color changes each time you click on the rectangle. If
you have time, add other controls such as buttons and list boxes.
In most cases, XAML will be used for defining UI elements. However, XAML can be to create
any kind of type. In this part, you will define your type and use it directly from XAML.
Steps:
1. Create a new class named Person in the same namespace -
MyWindowsApplication.
2. Add a few interesting properties such as Age and Name.
3. Override ToString to return the name and age.
public class Person
{
string name;
int age;
4. In order to use this type from XAML, you need to map an XML namespace to the CLR
namespace.
5. In the Window1.xaml file, locate the existing XML namespace definitions and add a
new XML namespace definition next to them.
xmlns:my="clr-namespace:MyWindowsApplication"
6. Locate the Rectangle element, directly below it, add a new Button and set its content to
a new Person.
7. In order to set the button content, add a child element using the my XML prefix you just
defined.
8. Set the Age and Name properties to meaningful values.
Note that as soon as you add a custom type into the XAML, the Visual Studio Designer
will complain and give warnings about the definition. This is because VS.NET is using a
static XML schema definition (.XSD) file to validate the XML and your custom tags aren’t
defined in that schema. These warnings are safe to ignore – you will see more of these
as the class progresses because of the beta state of the designer.
<Button>
<my:Person Name=”Mark” Age=”42” />
</Button>
9. Compile and run the application. Notice that the person is now inside the button.
Solution
In this section you will use some of the advanced visual effects of WPF to create a reflecting
image. We didn’t talk explicitly about some of these features so you will need to read the lab
instructions carefully. This part is here to show you how powerful WPF can really be! When
you are finished, the application will look something like:
Steps:
1. Create a new WPF application in Visual Studio.
a. In the root Window tag set the Background property to “Black”.
b. Change the root panel from a Grid to a StackPanel and set the Margin to
“20”.
2. Add a new Border control to the StackPanel.
a. Give it a name – the lab will use “picture”.
b. Set the BorderBrush to “White”. This will simulate a picture border.
c. Set the BorderThickness to “10”.
d. Set the Width to “300”.
e. Set the Height to “300”.
f. Using the complex property syntax of Border.Background, set the
background to a new ImageBrush. The ImageSource of the brush should be
any image you like. The lab will use “c:\windows\web\wallpaper\img5.jpg”.
<StackPanel Margin="20">
<Border Name="picture" BorderBrush="White"
BorderThickness="10" Width="300" Height="300">
<Border.Background>
<ImageBrush ImageSource="c:\windows\web\wallpaper\img5.jpg" />
</Border.Background>
</Border>
</StackPanel>
</Window>
3. Under the Border, add a second border with the same Width and Height.
a. Set the Margin property to “0, 10, 0, 0” to put a little space between the bottom
of the first border and this one.
4. Using the complex property syntax, set the Border.Background to be a new
VisualBrush instance.
a. Set the Visual to be a data binding to the 1st border.
<VisualBrush Visual="{Binding ElementName=picture}" />
5. Notice that we now have a complete copy of the image. The next step is to flip the image
by adding a transform.
a. Add a RenderTransform to the second border and add in a
ScaleTransform that flips on the Y axis (hint: think negative ScaleY).
b. You will also need to adjust the origin of the transform so it stays below the
original border image.
6. The image should now be flipped on the Y axis – the next step is to angle it slightly so it
looks like it is sitting on a flat surface.
a. Add a SkewTransform which adjusts the X angle to 10 degrees.
<StackPanel Margin="20">
<Border Name="picture" BorderBrush="White" BorderThickness="10"
Width="300" Height="300">
<Border.Background>
<ImageBrush ImageSource="c:\windows\web\wallpaper\img5.jpg" />
</Border.Background>
</Border>
<Border Width="300" Height="300" Margin="0,10,0,0">
<Border.Background>
<VisualBrush Visual="{Binding ElementName=picture}" />
</Border.Background>
7. Add a complex property to the second border which sets the Border.OpacityMask.
This takes a Brush to determine what the opacity is.
8. Set the OpacityMask property to be a new LinearGradientBrush object.
a. Set the StartPoint to (0,1) and the EndPoint to (0,0).
b. Add a gradient stop with an Offset of “0” and a Color of “Black”.
c. Add a second gradient stop with an Offset of “.35” and a Color of
“#30000000”.
d. Add a final gradient stop with an Offset of “.65” and a Color of
“Transparent” (#00000000).
9. The image should now fade as it moves further away, simulating a real reflection.
<StackPanel Margin="20">
<Border Name="picture" BorderBrush="White" BorderThickness="10"
Width="300" Height="300">
<Border.Background>
<ImageBrush ImageSource="c:\windows\web\wallpaper\img5.jpg" />
</Border.Background>
</Border>
<Border Width="300" Height="300" Margin="0,10,0,0">
<Border.Background>
<VisualBrush Visual="{Binding ElementName=picture}" />
</Border.Background>
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterY="150" />
<SkewTransform AngleX="10" />
</TransformGroup>
</Border.RenderTransform>
<Border.OpacityMask>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset=".35" Color="#30000000" />
<GradientStop Offset=".65" Color="Transparent" />
</LinearGradientBrush>
Think about this: How much procedural code was actually written for this program? All of the
effects you have done here could be added by the visual designer – instead of the programmer.