Sei sulla pagina 1di 10

Working with Windows Presentation Foundation

Estimated time for completion: 60 minutes

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.

Part 1 – Writing a very simple XAML 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>

© 2007 Education Experiences, Inc. All rights reserved Page 1 of 10


4. Save the file and open it using Internet Explorer. You should see new page with an
orange rectangle in it. (Just double click on the file in Explorer – IE will be used to open
it).
5. The rectangle displayed by the page is a "live" object. To verify this, set the Cursor
property to “Cross”. Save and open the file again. Notice that the cursor changes when
the mouse is on top of the rectangle.

Part 2 – Apply complex and attached properties

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>

6. Save the file and open it using Internet Explorer.


a. The background should now be a gradient going from Orange to Blue.
7. In the current XAML file, the rectangle is on the top left corner of the canvas. Your job is
now to set the Top and Left properties of the rectangle. Top and Left and example of
attached properties. They are defined by the Canvas type but applied to its children.
a. Set the Left of the rectangle to “100” by setting the Canvas.Left attribute.

© 2007 Education Experiences, Inc. All rights reserved Page 2 of 10


b. Set the Top of the rectangle to “80” using a full XAML property element syntax
where it is placed in a child element.
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Width="300" Height="200" Canvas.Left="100">
<Canvas.Top>80</Canvas.Top>
<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.

Part 3 – Add C# event handlers

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.

© 2007 Education Experiences, Inc. All rights reserved Page 3 of 10


2. Examine the created project and notice that that it contains two XAML files: app.xaml
and Window1.xaml.
a. app.xaml contains the markup for the application.
b. window1.xaml contains the code for the main window.
3. Open app.xaml and notice that the StartupUri attribute is set to Window1.xaml -
the main window.
4. Examine the content of Window1.xaml. Notice it contains a Window element with a
Grid inside. Notice it also specifies the corresponding class
x:Class="MyWindowsApplication.Window1.
5. Verify that there is a file below Window1.xaml called Window1.xaml.cs. This is
where you'll put your code.
6. Compile the project. In Window1.xaml.cs, notice that the constructor calls a method
named InitializeComponent. Navigate to the definition of this method by right-
clicking on it and selecting “Definition”.
7. This should open a file named Window1.g.cs. As the “g” suggests, this method has
been automatically generated during compilation. This is what the XAML compiler
produced from the .XAML file. Notice that it is a partial class which adds to your code
behind file. This is where:
a. The .BAML is loaded and parsed, creating the actual objects based on the
markup.
b. Any named elements are backed with private fields accessible in your code
behind.
c. Event handlers are wired up to events.
8. Run the project. You should see the window with no content.
9. Go back to the XAML file for the main window. Inside the Grid element, add an
orange rectangle like you did in the previous part. Compile and run. You should get a
window with an orange rectangle.
10. So far, the application does not do more than a markup application. Your job is now to
change the fill of the rectangle to a random each time you click on it.
11. Locate the Rectangle element and set its MouseDown event to the name of a method
you'll create shortly: OnRectangleMouseDown.
12. Try compiling. This should fail because the C# method has not been declared yet.
13. Open the Window1.xaml.cs file and add a new method named
OnRectangleMouseDown with the following signature:
void OnRectangleMouseDown(object sender, MouseEventArgs args)

14. Compile. It should work now.

© 2007 Education Experiences, Inc. All rights reserved Page 4 of 10


15. In order to change its fill color, you need a reference to the rectangle in
OnRectangleMouseDown. There are several ways to accomplish this. The easiest
way is to set the Name attribute in XAML to the desired C# field name.
a. Set the Name attribute to “myRectangle”.
b. Compile. Notice that the code Window1.g.cs now contains a definition for a
field named “myRectangle”.
c. Implement OnRectangleMouseDown to set the fill of the rectangle to a
random color.
Random r = new Random();
void OnRectangleMouseDown(object sender, MouseEventArgs args)
{
Color c = new Color();
c.A = (byte)r.Next(256);
c.R = (byte)r.Next(256);
c.G = (byte)r.Next(256);
c.B = (byte)r.Next(256);
myRectangle.Fill = new SolidColorBrush(c);
}

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.

Part 4 – Use XAML for custom types

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;

public string Name


{
get { return name; }
set { name = value; }
}
public int Age

© 2007 Education Experiences, Inc. All rights reserved Page 5 of 10


{
get { return age; }
set { age = value; }
}

public override string ToString()


{
return name + “is “ + age + “ years old.”;
}
}

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

The after\MyWindowsApplication.sln solution contains a project which implements the two


final Visual Studio based parts.

© 2007 Education Experiences, Inc. All rights reserved Page 6 of 10


Part 5 – Getting more visual (Advanced/Optional)

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

© 2007 Education Experiences, Inc. All rights reserved Page 7 of 10


<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">

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

© 2007 Education Experiences, Inc. All rights reserved Page 8 of 10


<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterY="150" />
<SkewTransform AngleX="10" />
</TransformGroup>
</Border.RenderTransform>
</Border>
</StackPanel>

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>

© 2007 Education Experiences, Inc. All rights reserved Page 9 of 10


</Border.OpacityMask>
</Border>
</StackPanel>

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.

© 2007 Education Experiences, Inc. All rights reserved Page 10 of 10