You are on page 1of 98

1

Using Graphics, Animation, and Multimedia in WPF


If you need an information on:
Graphics, Animation, and Multimedia in WPF 3.5

See page:
2

Chapter 1

Graphics, in literal sense, means a visual presentation of designs, shapes, drawings, and text, which is often used to view particular information. Graphics combine text, illustration, color, and so on. Animation is the process of sequentially arranging these graphics to create an illusion of movement. Multimedia includes a combination of text, audio, video, animation, and graphic contents. Windows Presentation Foundation (WPF) includes support for high quality 2-D and 3-D graphics, animation, and media features, which enable you to add graphics, transition effects, sound, and video to your applications. WPF provides advanced drawing and animation features that were previously available only for specialized libraries such as Graphics Device Interface (GDI) and GDI+. In this chapter, you learn about the graphics, animation and multimedia features of WPF. This chapter covers a detailed overview of the use of graphics, animation, and multimedia in WPF 3.5. In the later sections of this chapter, you learn about creating graphics, animation, and multimedia in WPF.

Graphics, Animation, and Multimedia in WPF 3.5


This part of the chapter introduces you to the different aspects of graphics, animation, and multimedia in WPF. The drawing and animation features were previously available only in GDI and GDI+. With WPF 3.5, Microsoft has introduced advanced drawing and animation features such as the use of graphics in WPF application. WPF offers integrated support for multimedia, vector graphics, and animation, and makes it easier for you to build interesting user interfaces and content. Lets take an overview of what are the highlights of graphics, animation, and multimedia in WPF 3.5. First and foremost, WPF graphics system uses device-independent units to enable resolution and device independence. The traditional Windows applications are bound by the screen resolution for display. The basic problem with the traditional Windows application is that they are not scalable. However, WPF does not suffer from this problem because it renders all user interface elements itself, whether it a simple shape or a common control such as Button. WPF also uses improved precision, which increases the performance of the WPF application. The coordinate system of WPF is measured with double-precision floating point numbers rather than single-precision. WPF also supports a wider color scope and provides integrated support for managing inputs from different color spaces. One of the most important highlight of WPF 3.5, which is the subject matter of this chapter, is the support for advanced graphics and animations. WPF simplifies graphics programming by managing the scene graph. The Windows applications were limited when dealing with multimedia. Multimedia and animation are an intrinsic part of the WPF Framework. Another important highlight of WPF 3.5 is hardware acceleration. The WPF graphic system is designed in a way to take advantage of the graphics hardware to minimize the CPU usage. This was all about the features of graphics in WPF 3.5. Lets now learn about 2-D graphics, 3-D graphics, animation, and multimedia.

2-D Graphics
The 2-D graphics are the primitives that are specified by a set of points on a coordinate system, such as lines, curves, and figures. In this section, you will learn about: Shapes in WPF Geometries in WPF Brushes in WPF The Drawing Class Lets discuss these now in detail.

Shapes in WPF
The most important and the simplest way to draw 2-D graphics in WPF user interface are to use Shapes. Shapes in WPF represent Line, Ellipse, Path, Polygon, Polyline, and Rectangle. You can combine these shapes to create a complex graphic. Shapes in WPF are derived from the FrameworkElement class and can be drawn

Using Graphics, Animation, and Multimedia in WPF

simply using XAML (Extensible Application Markup Language). The description of different types of Shape in WPF or the Shape class in WPF are listed in Table 1.1: Table 1.1: Shape Class

Class
Line Ellipse Path Polygon Polyline Rectangle

Description
Draws a line between two points Draws a ellipse Draws curve and complex shapes Draws a connected series of lines that form a closed shape Draws a series of connected straight line Draws a rectangle

The common properties of all the Shape class in WPF are listed in Table 1.2: Table 1.2: Common Properties of Shape Class

Property
Stroke StrokeThickness Fill

Description
Paints the shape outline Specifies the thickness of the shape outline Paints the interior the shape

The Shape objects derive themselves from UIElement class. You can use the Shape objects inside the Container controls, as discussed earlier in Chapter 17, Working with WPF 3.5 Controls, Resources, Styles, Templates, and Commands. The Canvas container control is a good choice for the Shape objects because it supports absolute positing of its child elements. The Shape class is an abstract class and it provides a base class for the Shape elements in WPF. The inheritance hierarchy of the Shape class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Shapes.Shape

The noteworthy properties of the Shape class are listed in Table 1.3: Table 1.3: Properties of Shape class

Property
DefiningGeometry GeometryTransform RenderedGeometry Stroke StrokeEndLineCap StrokeLineJoin StrokeMiterLimit StrokeStartLineCap StrokeThickness

Description
Retrieves a value that represents the Geometry of the Shape Retrieves a value that represents a Transform that is applied to the geometry of a Shape prior to when it is drawn Retrieves a value that represents the final rendered Geometry of a Shape Gets or sets the Brush that specifies how the Shape outline is painted Gets or sets a PenLineCap enumeration value that describes the Shape at the end of a line Gets or sets a PenLineJoin enumeration value that specifies the type of join that is used at the vertices of a Shape Gets or sets a limit on the ratio of the miter length to half the StrokeThickness of a Shape element Gets or sets a PenLineCap enumeration value that describes the Shape at the start of a Stroke Gets or sets the width of the Shape outline

Chapter 1

Geometries in WPF
The geometries in WPF are derived from the abstract base class Geometry class. The classes that derive from the Geometry class define geometric shapes in WPF. The Geometry objects are used for clipping and rendering 2-D graphics in WPF. In Table 1.1, you learned about the different Shape elements available in WPF. One of them was the Path object. The Path class has the ability the draw any simple shape, group of shapes, or more complex curves. These shapes and curves are described using the Geometry object. To use the Path class, you first need to create Geometry and then use it to set the Data property of the Path class. The basic difference between Path and Geometry is that Geometry defines a Shape and Path allows you to draw that Shape. The Path class actually uses Geometry to describe its content. The inheritance hierarchy of the Geometry class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Geometry

The noteworthy properties of the Geometry class are listed in Table 1.4: Table 1.4: Properties of Geometry Class

Property
Bounds CanFreeze DependencyObjectType Dispatcher Empty HasAnimatedProperties IsFrozen IsSealed StandardFlatteningTolerance Transform

Description
Retrieves a Rect that specifies the axis-aligned bounding box of the Geometry Retrieves a value that indicates whether the object can be made unmodifiable Retrieves the DependencyObjectType that wraps the CLR (Common Langauge Runtime) type of Geometry class Retrieves the Dispatcher this DispatcherObject is associated with Retrieves an empty object Retrieves a value that indicates whether one or more AnimationClock objects is associated with any of the Geometry class dependency properties Retrieves a value that indicates whether the object is currently modifiable Retrieves a value that declares whether this instance is currently read-only Retrieves the standard tolerance used for smoothing of the geometry. Gets or sets the Transform object applied to a Geometry

The Geometry and Shape class might look similar to you as they both describe 2-D shapes, but there are certain important differences between them. The first difference being that the Geometry class inherits from the Freezable class while the Shape class inherits from the FrameworkElement class. The Shape objects are more readily usable but the Geometry objects are more versatile. Therefore, you can say that, the Geometry class simply defines the geometry of a shape and cannot render itself. There are different types of Geometry available in WPF. The base class for all geometries is the abstract class Geometry. The classes that derive from the Geometry class can be grouped into three categories, as follows: Simple geometry Path geometry Composite geometry These categories are discussed in the upcoming section.

Simple Geometry
The simple geometry classes are used to create basic geometric shapes such as lines, rectangle, and ellipse. Basically a simple geometry class includes three classes, as given here: The LineGeometry classRepresents the geometry of a line. You can draw a line by specifying the StartPoint and EndPoint of the line. The StartPoint property gets or sets the start point of the line and the EndPoint property gets or sets the end point of the line. You can also create multiple connected

Using Graphics, Animation, and Multimedia in WPF

lines by using the LineSegment or Polyline segment with the PathFigure and PathGeometry classes. The LineSegment class creates a line between two points in a PathFigure and the Polyline class draws a series of connected straight lines. The RectangleGeometry classRepresents a two-dimensional rectangle. The RectangleGeoemetry is defined with the Rect structure which specifies the relative position of the rectangle and also its height and width. You can also create a rectangle with rounded edges by setting the RadiusX and RadiusY properties of the rectangle. The RectangleGeometry and the Rectangle shape are not the same. The difference lies in the values that each takes. The Rectangle shape takes only the Height and Width properties while the RectangleGeometry takes four numbers that describe the size and location of the rectangle along with the height and width. The EllipseGeometry classRepresents the geometry of a circle or ellipse. The EllipseGeometry class and the Ellipse class are not the same. The Ellipse class has a Fill, Stroke and other rendering properties which the EllipseGeometry lacks. The EllipseGeometry class defines the geometry of an ellipse.

Path Geometry
The path geometry classes include PathGeometry and StreamGeometry. The path geometry classes are used to create multiple complex figures composed of arcs, curves and lines. The path geometry classes and their functioning are listed in Table 1.5: Table 1.5: Path Geometry Classes

Class
PathGeometry StreamGeometry

Description
Draws a complex shape that is composed of arcs and curves Draws a geometric shape and is a light-weight alternative to PathGeometry

The PathGeometry class is used to define complex shapes that may be composed of arcs, curves, ellipses, lines and rectangles. The PathGeometry class defines a collection of PathFigure objects and each of PathFigure objects is composed of one or more PathSegment objects. The different types of PathSegment objects are listed in Table 1.6: Table 1.6: Type of PathSegment Object

Segment
ArcSegment BezierSegment LineSegment PolyBezierSegment PolyLineSegment PolyQuadraticBezierSegment QuadraticBezierSegment

Description
Creates an elliptical arc between two points Creates a cubic Bezier curve between two points Creates a line between two points Creates a series of cubic Bezier curve Creates a series of lines Creates a series of quadratic Bezier curve Creates a quadratic Bezier curve

The segments within the PathFigure are combined into a single geometric shape as the end point of each segment is the start point of the next segment. You can specify the point from which the first segment is drawn by setting the StartPoint property. The filled area of the PathGeometry is defined by taking all the PathFigure objects that have their IsFilled property set to True. The FillRule property is applied to determine the enclosed area. The StreamGeometry class also defines geometric shapes like the PathGeometry class. The only difference is that the StreamGeometry class is a light-weight alternative to PathGeometry. The StreamGeometry class does not support data binding, animation, or modification like the PathGeometry class.

Chapter 1

Composite Geometry
The composite geometry classes include GeometryGroup and CombinedGeometry classes. You can also create composite geometry by calling the static method Combine of the Geometry class. The composite geometry classes and their functioning are listed in Table 1.7: Table 1.7: Composite Geometry Classes

Class
GeometryGroup CombinedGeometry

Description
Creates an amalgamation of Geometry objects without combining their area Combines the area defined by two geometries

The GeometryGroup class represents a composite geometry, inclusive of other Geometry objects. The GeometryGroup class creates a composite geometry from any number of geometry objects. You can use the FillRule property of GeometryGroup to specify how the geometries are combined. The CombinedGeometry class on the other hand, represents a 2-D geometric shape defined by the combination of two Geometry objects. You can use the GeometryCombineMode property of CombinedGeometry to specify how the two geometries will be combined. The values of GeometryCombineMode can be set to: Union, Intersect, Exclude or Xor. The geometries that do not have an area disappear when the two geometries are combined.

Brushes in WPF
In WPF, you can use brushes to applying background and foreground to elements. The brushes in WPF are used to paint various shapes. The brushes in WPF derive from the Freezable base class and so supports change notification. For example, if you change a brush, the element that uses that brush repaints itself. The brushes in WPF are defined in the Brush class defined in the System.Windows.Media.Brush. The different types of brushes available in WPF are listed in Table 1.8: Table 1.8: Brush Class

Class
SolidColorBrush LinearGradientBrush RadialGradientBrush DrawingBrush ImageBrush VisualBrush

Description
Paints an area with a solid color Paints an area with linear gradient Paints an area with radial gradient Paints an area with a drawing Paints an area with an image Paints an area with a visual object

The inheritance hierarchy of the Brush class is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush

The noteworthy properties of the Brush class are listed in Table 1.9: Table 1.9: Properties of Brush class

Property
CanFreeze DependencyObjectType Dispatcher HasAnimatedProperties IsFrozen

Description
Retrieves a value that indicates whether the object can be made unmodifiable Retrieves the DependencyObjectType that wraps the CLR type of this instance Retrieves the Dispatcher, this DispatcherObject is associated with Retrieves a value that indicates whether one or more AnimationClock objects is associated with any of this objects dependency properties Retrieves a value that indicates whether the object is currently modifiable

Using Graphics, Animation, and Multimedia in WPF

Table 1.9: Properties of Brush class

Property
IsSealed Opacity RelativeTransform Transform

Description
Retrieves a value that declares whether this instance is currently read-only Retrieves or sets the degree of opacity of a Brush Retrieves or sets the transformation that is applied to the brush using relative coordinates Gets or sets the transformation that is applied to the brush

Different types of brushes that help you to make a WPF application are given here: SolidColorBrush LinearGradientBrush RadialGradientBrush DrawingBrush ImageBrush VisualBrush These types of brushes are discussed in the next sections.

SolidColorBrush
The SolidColorBrush defines the brush of a single color. The SolidColorBrush is used to fill graphics shapes, such as rectangle, ellipse, polygons, and paths with a single color. You can define solid color by setting the Background attribute to a string that defines a solid color. You can paint an area with a solid color by using the predefined system brush such as Red, Blue, or Yellow. You can add a SolidColorBrush to your application by adding the following code:
<SolidColorBrush .../>

The inheritance hierarchy of the SolidColorBrush is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.SolidColorBrush

The noteworthy property of SolidColorBrush is listed in Table 1.10: Table 1.10: Property of SolidColorBrush

Property
Color

Description
Gets or sets the color of this SolidColorBrush

LinearGradientBrush
The LinearGradientBrush paints an area with linear gradient, a gradually shaded fill that changes from one color to another. The LinearGradientBrush applies a smooth color change to the elements. The LinearGradientBrush creates a blended fill. This brush defines the StartPoint and EndPoint properties. They assign the two-dimensional coordinates for applying the linear gradient. The default value of the StartPoint property is 0, and EndPoint property is 1, 1 which creates a diagonal gradient. These properties allow you to choose the point where the first color begins to change and the point where the color change ends with the final color. To create a gradient, you need to add one GradientStop for each color and place each color in your gradient using the Offset value from 0 to 1. You can add a LinearGradientBrush to your application by adding the following code:
<LinearGradientBrush> <!-- GradientStops --> </LinearGradientBrush>

The inheritance hierarchy of the LinearGradientBrush is as follows:

Chapter 1
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.GradientBrush System.Windows.Media.LinearGradientBrush

The noteworthy properties of the LinearGradientBrush are listed in Table 1.11: Table 1.11: Properties of LinearGradientBrush

Property
ColorInterpolationMode EndPoint GradientStops MappingMode SpreadMethod StartPoint

Description
Gets or sets a ColorInterpolationMode enumeration that specifies how the gradients colors are interpolated Gets or sets the ending two-dimensional coordinates of the linear gradient Gets or sets the brushs gradient stops Gets or sets a BrushMappingMode enumeration that specifies whether the gradient brushs positioning coordinates are absolute or relative to the output area Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted Gets or sets the starting two-dimensional coordinates of the linear gradient

RadialGradientBrush
The RadialGradientBrush is similar to the LinearGradientBrush. The RadialGradientBrush also fills an area with a gradient fill. The difference lies on the way, the gradient is applied. The RadialGradientBrush fill the gradient which radiates out in a circular pattern starting from the center point. You can use the GradientOrigin property to identify the point where the first color in the gradient starts. The default value of the GradientOrigin is 0.5, which represents the middle of the fill region. The gradient radiates out from the point in the GradientOrigin which is the starting point in a circular manner. The RadialGradientBrush is a good choice for filling rounded shapes and creates lightening effect. You can add a RadialGradientBrush to your application by adding the following code:
<RadialGradientBrush> <!-- GradientStops --> </RadialGradientBrush>

The inheritance hierarchy of the RadialGradientBrush is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.GradientBrush System.Windows.Media.RadialGradientBrush

The noteworthy properties of the RadialGradientBrush are listed in Table 1.12: Table 1.12: Property of RadialGradientBrush

Property
Center ColorInterpolationMode GradientOrigin GradientStops MappingMode

Description
Gets or sets the center of the outermost circle of the radial gradient Gets or sets a ColorInterpolationMode enumeration that specifies how the gradients colors are interpolated Gets or sets the location of the two-dimensional focal point that defines the beginning of the gradient Gets or sets the brushs gradient stops Gets or sets a BrushMappingMode enumeration that specifies whether the gradient brushs positioning coordinates are absolute or related to the output area

Using Graphics, Animation, and Multimedia in WPF

Table 1.12: Property of RadialGradientBrush

Property
RadiusX RadiusY SpreadMethod

Description
Gets or sets the horizontal radius of the outermost circle of the radial gradient Gets or sets the vertical radius of the outermost circle of a radial gradient Gets or sets the type of spread method that specifies how to draw a gradient that starts or ends inside the bounds of the object to be painted

DrawingBrush
The DrawingBrush paints an area with drawing object, which can include shapes, text, video, images, or other drawings. The DrawingBrush paints an area with a Drawing object. The Drawing object describes the visible content of the DrawingBrush. The DrawingBrush stretches the drawing to fill the output area. The drawing that is shown with the brush is defined using the GeometryDrawing element. You can also create a repeating pattern of the drawing by setting the Viewport and TileMode property of the DrawingBrush. You can apply the DrawingBrush to your application by adding the following code:
<DrawingBrush .../>

The inheritance hierarchy of the DrawingBrush is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.TileBrush System.Windows.Media.DrawingBrush

The noteworthy properties of the DrawingBrush class are listed in Table 1.13: Table 1.13: Property of DrawingBrush

Property
AlignmentX AlignmentY Drawing Stretch TileMode Viewbox ViewboxUnits Viewport ViewportUnits

Description
Gets or sets the horizontal alignment of content in the TileBrush base tile Gets or sets the vertical alignment of content in the TileBrush base tile Gets or sets the Drawing that describes the contents of the DrawingBrush Gets or sets a value that specifies how the content of the TileBrush stretches to fit its tiles Gets or sets a value that specifies how a TileBrush fills the area that you are painting if the base tile is smaller than the output area Gets or sets the position and dimensions of the content in a TileBrush tile Gets or sets a value that specifies whether the Viewbox value is related to the bounding box of the TileBrush contents or whether the value is absolute Gets or sets the position and dimensions of the base tile for a TileBrush Gets or sets a BrushMappingMode enumeration that specifies whether the value of the Viewport, which indicates the size and position of the TileBrush base tile, is relative to the size of the output area

ImageBrush
You can use the ImageBrush to load an image into a brush. You can load the most common image file types, including bmp, png, gif, and jpeg file. The ImageSource property is used to display the image used in the ImageBrush. The image used in the ImageSource property is stretched to fill the area. This is the default behavior. You can control this behavior by setting the Stretch property of TileBrush to Uniform or UniformToFill. This causes the image to preserve the aspect ratio of the image. You can create a repeating pattern of the image by setting the Viewport and TileMode property. You can add the ImageBrush to your application by adding the following code:
<ImageBrush .../>

The inheritance hierarchy of the ImageBrush is as follows:

Chapter 1
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.TileBrush System.Windows.Media.ImageBrush

The noteworthy properties of the ImageBrush class are listed in Table 1.14: Table 1.14: Properties of ImageBrush

Property
AlignmentX AlignmentY ImageSource Stretch TileMode Viewbox ViewboxUnits Viewport ViewportUnits

Description
Gets or sets the horizontal alignment of content in the TileBrush base tile Gets or sets the vertical alignment of content in the TileBrush base tile Gets or sets the image displayed by the ImageBrush Gets or sets a value that specifies how the content of the TileBrush stretches to fit its tiles Gets or sets a value that specifies how a TileBrush fills the area that you are painting if the base tile is smaller than the output area Gets or sets the position and dimensions of the content in a TileBrush tile Gets or sets a value that specifies whether the Viewbox value is relative to the bounding box of the TileBrush contents or the value is absolute Gets or sets the position and dimensions of the base tile for a TileBrush Gets or sets a BrushMappingMode enumeration that specifies whether the value of the Viewport, which indicates the size and position of the TileBrush base tile, is relative to the size of the output area

VisualBrush
The VisualBrush paints an area with a visual. The VisualBrush allows you to take the visual content of an element and use it to fill the area. For example, you can copy the appearance of a button in the window to a region somewhere else in that window. By this way, you are using an existing image to create the duplicate image. Another way to specify the Visual content of the VisualBrush is to create a new Visual and use it to set the Visual property of the VisualBrush. With VisualBrush, you can also create effects such as reflection. You can also use the VisualBrush to display a video by setting the Visual property to MediaElement. You can add the VisualBrush to your application by adding the following code:
<VisualBrush .../>

The inheritance hierarchy of VisualBrush is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Brush System.Windows.Media.TileBrush System.Windows.Media.VisualBrush

The noteworthy properties of the VisualBrush are listed in Table 1.15: Table 1.15: Property of VisualBrush

Property
AlignmentX AlignmentY AutoLayoutContent Stretch TileMode Viewbox

Description
Gets or sets the horizontal alignment of content in the TileBrush base tile Gets or sets the vertical alignment of content in the TileBrush base tile Gets or sets a value that specifies whether the VisualBrush will place the content Gets or sets a value that specifies how the content of the TileBrush stretches to fit its tiles Gets or sets a value that specifies how a TileBrush fills the area that you are painting if the base tile is smaller than the output area Gets or sets the position and dimensions of the content in a TileBrush tile

10

Using Graphics, Animation, and Multimedia in WPF

Table 1.15: Property of VisualBrush

Property
ViewboxUnits Viewport ViewportUnits

Description
Gets or sets a value that specifies whether the Viewbox value is relative to the bounding box of the TileBrush contents or whether the value is absolute Gets or sets the position and dimensions of the base tile for a TileBrush Gets or sets a BrushMappingMode enumeration that specifies whether the value of the Viewport, which indicates the size and position of the TileBrush base tile, is relative to the size of the output area Gets or sets the brushs content

Visual

The Drawing Class


The Drawing class is an abstract class. The Drawing class represents a 2-D drawing. The Drawing class uses Drawing objects to draw different types of content. The Drawing objects are light-weight objects that enable you to add geometric shapes, images, text and media to an application. The inheritance hierarchy of the Drawing class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Drawing

The noteworthy properties of the Drawing class are listed in Table 1.16: Table 1.16: Properties of Drawing Class

Property
Bounds CanFreeze DependencyObjectType Dispatcher HasAnimatedProperties IsFrozen IsSealed

Description
Retrieves the axis-aligned bounds of the drawings contents Retrieves a value that indicates whether the object can be made unmodifiable Retrieves the DependencyObjectType that wraps the CLR type of Drawing class Retrieves the Dispatcher the Drawing class DispatcherObject is associated with Retrieves a value that indicates whether one or more AnimationClock objects is associated with any of the Drawing class dependency properties Retrieves a value that indicates whether the object is currently modifiable Retrieves a value that declares whether this instance is currently read-only

You can find the methods of Drawing class listed in Table 1.17: Table 1.17: Methods of Drawing Class

Method
Clone CloneCurrentValue

Description
Creates a modifiable clone of the Drawing class. Creates a modifiable clone of the current value of the Drawing class

The Drawing class helps you make a WPF application with the help of different types of drawing object and the DrawingContext class, which we describe next.

Types of Drawing Objects


In the previous section, you have learned that the Drawing object in the Drawing class enable you to add geometric shapes, images, text, and media to an application. The Drawing objects are used to efficiently draw shapes, bitmaps, text and media. You can use the Drawing objects when you create clip art or paint with the DrawingBrush. The different types of Drawing object are described as follows:

11

Chapter 1

The GeometryDrawing classEnables you to create shape with a fill and an outline by using the Pen and Brush property with the Geometry. The Geometry describes the structure of the shape, the Brush describes the fill color of the shape, and the Pen describes the outline. The ImageDrawing classEnables you to display an ImageSource with a DrawingBrush, DrawingImage, or Visual. The ImageSource property specifies the image to be drawn and the Rect property specifies the position and size of each image. The GlyphRunDrawing classRepresents the Drawing object that renders a GlyphRun. The GlyphRun contains font details such as glyph indices and the individual glyph positions. In simple words, to draw text, you use a GlyphRunDrawing and a GlyphRun. The VideoDrawing classEnables you to play a media file. You can use the VideoDrawing and the MediaPlayer to play an audio or a video file. You can load and play media in two ways. The first way is to use a MediaPlayer and the VideoDrawing by themselves. The second way is to create your own MediaTimeline to use with the MediaPlayer and VideoDrawing. The DrawingGroup classEnables you to combine a collection of drawings that can be operated as a single drawing. The flexibility of this class enables you to create complex scenes. The DrawingGroup also enables you to apply opacity masks, transforms, bitmap effects, and other operations to its content. The operations of DrawingGroup are applied in the following order: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet, and then Transform.

The DrawingContext Class


The DrawingContext class describes the visual content using draw, push, and pop commands. The DrawingContext is obtained from a DrawingGroup and is displayed using an Image control. You can use the DrawingContext class to populate a Visual class or a Drawing class with visual content. The DrawingContext class is not used for drawing to the screen in real time. When you are using the DrawingContext object draw commands, you are actually storing a set of rendering instructions that will be later used by the graphics system. You can never directly instantiate a DrawingContext class. However, you can acquire a DrawingContext from certain methods, such as DrawingGroup.Open and DrawingVisual.RenderOpen. The DrawingContext class is made up of methods that add some graphical detail to your visual. You can call these methods to draw various shapes, apply transforms, change opacity, and many more. You can find the methods of DrawingContext class listed in Table 1.18: Table 1.18: Methods of DrawingContext Class

Method
CheckAccess Close DrawDrawing DrawEllipse DrawGeometry DrawGlyphRun DrawImage DrawLine DrawRectangle DrawRoundedRectangle DrawText DrawVideo Equals GetHashCode GetType

Description
Determines whether the calling thread has access to this DispatcherObject Closes the DrawingContext and flushes the content Draws the specified Drawing object Draws an ellipse Draws the specified Geometry using the specified Brush and Pen Draws the specified text Draws an image into the region defined by the specified Rect Draws a line with the specified Pen Draws a rectangle Draws a rounded rectangle Draws formatted text at the specified location Draw a video into the specified region Determines whether the specified Object is equal to the current Object Serves as a hash function for a particular type Retrieves the Type of the current instance

12

Using Graphics, Animation, and Multimedia in WPF

Table 1.18: Methods of DrawingContext Class

Method
Pop PushClip PushEffect PushGuidelineSet PushOpacity PushOpacityMask PushTransform ToString VerifyAccess

Description
Pops the last opacity mask, opacity, clip, effect, or transform operation that was pushed onto the drawing context Pushes the specified clip region onto the drawing context Pushes the specified BitmapEffect onto the drawing context Pushes the specified GuidelineSet onto the drawing context Pushes the specified opacity setting onto the drawing context Pushes the specified opacity mask onto the drawing context Pushes the specified Transform onto the drawing context Returns a String that represents the current Object Enforces that the calling thread has access to this DispatcherObject

The DrawingContext class has one noteworthy property, the Dispatcher property, which retrieves the Dispatcher the DrawingContext class is associated with.

Using 2-D Graphics in WPF 3.5


The 2-D graphics in WPF includes shapes, geometries, and brushes. You can create a rich looking application by combining these. In this section, you will learn to create the practical application of the shapes, geometries, and brushes available in WPF. In this section you will learn about: Using 2-D Shapes Creating Stretchable Shapes Drawing Geometry Combining Multiple Geometries Transforming Shapes Using the Path Shape and PathGeometry Geometry Using Brushes Changing the Tile Size and the Pattern of Brushes Creating Reflections using VisualBrush Preserving the AspectRatio of Image Lets discuss these one by one in detail.

Using 2-D Shapes


The shapes available in WPF are Line, Polyline, Rectangle, Polygon, Ellipse, and Path. These shapes are contained in the Shape class. You can use shapes to create a visual appealing figure. Lets use all the shapes in one application and create a human figure. For this, create a WPF application named Using2DShape (available in the CD-ROM) and add the following code given in Listing 1.1 to Window1.xaml: Listing 1.1: Creating 2-D Shape in WPF
<Window x:Class="Using2DShape.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Canvas Background=" LightBlue"> <Ellipse Canvas.Left="86" Canvas.Top="41" Height="90" Name="ellipse1" Stroke="Black" Width="96" Fill="AntiqueWhite" /> <Ellipse Canvas.Left="105" Canvas.Top="62" Height="13" Name="ellipse2" Stroke="Black" Width="14" Fill="Cornsilk" /> <Ellipse Canvas.Left="144" Canvas.Top="62" Height="13" Name="ellipse3" Stroke="Black" Width="14" Fill="Cornsilk" /> <Ellipse Canvas.Left="112" Canvas.Top="68" Height="5" Name="ellipse4" Stroke="Black" Width="5" Fill="Black" />

13

Chapter 1
<Ellipse Canvas.Left="151" Canvas.Top="67" Height="5" Name="ellipse5" Stroke="Black" Width="5" Fill="Black" /> <Rectangle Canvas.Left="105" Canvas.Top="129" Height="111" Name="rectangle1" Stroke="Black" Width="59" Fill="HotPink" /> <Ellipse Canvas.Left="127" Canvas.Top="128" Height="10" Name="ellipse6" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="148" Height="10" Name="ellipse7" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="168" Height="10" Name="ellipse8" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="188" Height="10" Name="ellipse9" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="208" Height="10" Name="ellipse10" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="228" Height="10" Name="ellipse11" Stroke="Black" Width="9" Fill="Blue" /> <Line X1="12" X2="400" Y1="145" Y2="115" Stroke="Black" StrokeThickness="5" Height="158" Canvas.Left="131" Canvas.Top="114" Width="42" /> <Path Name="path1" Stroke="Black" Data="M 60,113 Q 90,146 111,111" StrokeThickness="5" Height="134" Canvas.Left="48" Canvas.Top="-14" Width="145" /> <Line X1="124" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="40" Canvas.Top="-7" Width="147" /> <Line X1="145" X2="600" Y1="149" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="37" Canvas.Top="8" Width="178" /> <Line X1="124" X2="170" Y1="145" Y2="16" Stroke="Black" StrokeThickness="5" Height="115" Canvas.Left="-42" Canvas.Top="65" Width="147" /> <Line X1="115" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-50" Canvas.Top="11" Width="147" /> <Polygon Points="10,110 60,10 110,110" Fill="Blue" Height="55" Canvas.Left="72" Canvas.Top="-7" Width="132" /> <Line X1="11" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="163" Canvas.Left="83" Canvas.Top="110" Width="41" /> <Line X1="145" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-23" Canvas.Top="94" Width="151" /> <Line X1="145" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-1" Canvas.Top="94" Width="147" /> <Line X1="11" X2="10" Y1="145" Y2="115" Stroke="Black" StrokeThickness="5" Height="158" Canvas.Left="121" Canvas.Top="-52" Width="42" /> <Polyline Points="10,110 6,10 110,110" Stroke="Black" StrokeThickness="4" Height="52" Canvas.Left="209" Canvas.Top="210" Width="50"/> <Ellipse Canvas.Left="172" Canvas.Top="118" Height="100" Name="ellipse12" Stroke="Black" Width="87"> <Ellipse.BitmapEffect> <OuterGlowBitmapEffect GlowColor="DarkViolet" /> </Ellipse.BitmapEffect> </Ellipse> </Canvas> </Window>

Adding the code to the application will create a human figure. You will notice that all the shapes are used in the application to create the figure. When you run the code, by pressing F5, you will get an output as shown in Figure 1.1:

Figure 1.1: Using 2-D Shape

14

Using Graphics, Animation, and Multimedia in WPF

Creating Stretchable Shapes


All shapes in WPF have a Stretch property. The Stretch property determines how the Shape object content is stretched to fill the Shape object in layout space. The layout space is the space where Shape is allocated by using the Height and Width property. The Stretch property can take the following values: None Fill Uniform UniformToFill Lets create the shape with their Stretch property. For this, create a WPF application named StretchableShape (available on the CD-ROM) and add the following code given in Listing 1.2 to Window1.xaml: Listing 1.2: Applying Stretch property
<Window x:Class="StretchableShape.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <StackPanel> <Polyline Fill="Pink" Points="100,100 100,200 200,200 200,100" Stroke="Red" StrokeThickness="5" Stretch="Fill"/> <Polyline Fill="LightBlue" Points="100,100 100,200 200,200 200,100" Stroke="Red" StrokeThickness="2" Stretch="Uniform" /> </StackPanel> </Grid> </Window>

In this code, two shapes are added and different Stretch properties are applied to both of them. The first shape has the Stretch property to Fill and the second shape has the Stretch property to Uniform. When you run the code, by pressing F5, you will get an output as shown in Figure 1.2:

Figure 1.2: Creating Stretchable Shape

Drawing Geometry
The Geometry class enables you to describe the geometry of a 2-D shape. The classes that derive from the Geometry class are EllipseGeometry, PathGeometry, and CombinedGeomtry. You can create simple shape using geometry or complex shape by combining two geometries. Lets create an application using Geometry. For this, create a WPF application named DrawingGeometry (available on the CD-ROM) and add the following code given in Listing 1.3 to Window1.xaml: Listing 1.3:Using the Geometry Class
<Window x:Class="DrawingGeometry.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300">

15

Chapter 1
<Grid> <Path Stroke="Black" StrokeThickness="1" Fill="LightPink"> <Path.Data> <GeometryGroup> <EllipseGeometry Center="75,70" RadiusX="60" RadiusY="40" /> <RectangleGeometry Rect="25,55 100 25" /> </GeometryGroup> </Path.Data> </Path> </Grid> </Window>

In this code, EllipseGeometry is used to create a circle and RectangleGeometry is used to create the rectangle. When you run the code by pressing F5, you will get an output as shown in Figure 1.3:

Figure 1.3: Drawing Geometry

Combining Multiple Geometries


You can use the CombinedGeometry class to combine multiple geometries in WPF. The values of the CombinedGeometry are Exclude Intersect, Union, and Xor. You can combine any two geometries that we discussed earlier by using the CombinedGeometry class. Lets combine geometries using the CombinedGeometry class. For this, create a WPF application named CombiningGeometry (available on the CDROM) and add the following code given in Listing 1.4 to Window1.xaml: Listing 1.4: CombinedGeometry Class
<Window x:Class="CombiningGeometry.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Path Stroke="DarkRed" StrokeThickness="1" Fill="NavajoWhite" Margin="-52,19,52,19"> <Path.Data> <!-- Combines two geometries using the intersect combine mode. --> <CombinedGeometry GeometryCombineMode="Intersect"> <CombinedGeometry.Geometry1> <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" /> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" /> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> <Path Stroke="RosyBrown" StrokeThickness="1" Fill="AliceBlue" Margin="77,-19,77,19"> <Path.Data> <!-- Combines two geometries using the union combine mode. -->

16

Using Graphics, Animation, and Multimedia in WPF


<CombinedGeometry GeometryCombineMode="Union"> <CombinedGeometry.Geometry1> <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" /> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" /> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> <Path Stroke="Turquoise" StrokeThickness="1" Fill="SandyBrown" Margin="21,100,21,-100"> <Path.Data> <!-- Combines two geometries using the XOR combine mode. --> <CombinedGeometry GeometryCombineMode="Xor"> <CombinedGeometry.Geometry1> <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" /> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" /> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> <Path Stroke="LawnGreen" StrokeThickness="1" Fill="MediumTurquoise" HorizontalAlignment="Right" Margin="0,108,-152,-108" Width="278"> <Path.Data> <!-- Combines two geometries using the exclude combine mode. --> <CombinedGeometry GeometryCombineMode="Exclude"> <CombinedGeometry.Geometry1> <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" /> </CombinedGeometry.Geometry1> <CombinedGeometry.Geometry2> <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" /> </CombinedGeometry.Geometry2> </CombinedGeometry> </Path.Data> </Path> </Grid> </Window>

In this code, there are four types of CombinedGeometry applied on the EllipseGeometry. The CombinedGeometry works best on EllipseGeometry, therefore, it is used. When you run the code, by pressing F5, you will get an output as shown in Figure 1.4:

Figure 1.4: Combining Multiple Geometry

17

Chapter 1

Transforming Shapes
In WPF, you can transform the shapes using the RenderTransform, RotateTransform, and ScaleTransform properties. You have learned about these properties in Chapter 18, Working with Typography and Documents in WPF, where we applied transformation on text. Here, the transformation is applied to the shapes. The RenderTransform property affects the rendering position of the element. The RotateTransform property rotates the shape in the specified angle. The ScaleTransform property flips the shape either horizontally or vertically. Lets transform shapes by using these properties. For this, create a WPF application named TransformmingShapes (available in the CD) and add the following code given in Listing 1.5 to Window1.xaml: Listing 1.5: Applying Transformation
<Window x:Class="TransformmingShapes.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Canvas Opacity="1"> <Rectangle Canvas.Left="22" Canvas.Top="22" Height="91" Name="rectangle1" Stroke="Black" Width="73" Fill="BlueViolet" Opacity="1" > <Rectangle.RenderTransform> <RotateTransform Angle="50" CenterX="45" CenterY="45"/> </Rectangle.RenderTransform> </Rectangle> <Ellipse Canvas.Left="119" Canvas.Top="104" Height="91" Name="ellipse2" Stroke="Black" Width="90" Fill="CadetBlue"> <Ellipse.RenderTransform> <RotateTransform Angle="45" CenterX="100" CenterY="100"/> </Ellipse.RenderTransform> </Ellipse> <Rectangle Canvas.Left="96" Canvas.Top="203" Height="23" Name="button1" Width="75" Fill="Pink"> <Rectangle.RenderTransform> <ScaleTransform ScaleX="-1" /> </Rectangle.RenderTransform> </Rectangle> </Canvas> </Window>

In this code, we have added an ellipse and two rectangles on which we have applied the properties. When you run the code, by pressing F5, you get the output as shown in Figure 1.5:

Figure 1.5: Transforming Shapes

Using the Path Shape and PathGeometry Geometry


In WPF, the Path class enables you to draw complex curves and shapes. To use Path, you first create Geometry and use it to set the Path object Data property. The FillRule property specifies how the intersecting areas are combined. The FillRule property works with either the PathGeometry or

18

Using Graphics, Animation, and Multimedia in WPF

GeometryGroup. There are two values of the FillRule property, EvenOdd and NonZero. If you specify the EvenOdd value, the alternate area will be filled. The NonZero value fills the whole area specified in the GeometryGroup or the PathGeometry with the specified color. The PathGeometry is made up of one or more figures which is represented by the PathFigure class. Each figure is made up of one or more segments which is defined by the PathSegment class. Lets use the Path shape and the PathGeometry to see the application of the FillRule property. For this, create a WPF application named UsingPath (available on the CD-ROM) and add the following code given in Listing 1.6 to Window1.xaml: Listing 1.6: Using Path Class
<Window x:Class="UsingPath.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Path Stroke="Black" StrokeThickness="2" Fill="LightBlue"> <Path.Data> <GeometryGroup FillRule="EvenOdd"> <PathGeometry> <PathGeometry.Figures> <PathFigure StartPoint="150,150"> <PathFigure.Segments> <PathSegmentCollection> <ArcSegment Size="50,50" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,120" /> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> <PathFigure StartPoint="150,150"> <PathFigure.Segments> <PathSegmentCollection> <ArcSegment Size="70,70" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,100" /> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> </PathGeometry> </GeometryGroup> </Path.Data> </Path> </Grid> </Window>

In this code, the FillRule property of EvenOdd is applied on the PathGeometry and the GeometryGroup. There are two arcs added to the application which are filled with color using the FillRule property. The PathFigure class is used to represent a section of the geometry. When you run the code, by pressing F5, you get the output as shown in Figure 1.6:

Figure 1.6: Using PathGeometry

19

Chapter 1

Using Brushes
In this section, you will learn about how to use the different brushes to give your WPF application a rich look. As you know, there are five types of brushes available in WPF such as LinearGradientBrush, RadialGradeintBrush, ImageBrush, DrawingBrush, and VisualBrush. You will see further the usage of the all the brushes in detail.

LinearGradientBrush and RadialGradientBrush


The LinearGradientBrush paints an area with linear gradient. The RadialGradientBrush paints an area with radial gradient. You use the GradientStop object to specify the colors in the gradient and their position. Lets add the LinearGradientBrush and RadialGradientBrush to the application. For this, create a WPF application named Linear_RadialBrush (available on the CD-ROM) and add the following code given in Listing 1.7 to Window1.xaml: Listing 1.7: LinearGradientBrush and RadialGradientBrush
<Window x:Class="Linear_RadialBrush.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Ellipse Name="ellipse1" Stroke="OrangeRed" HorizontalAlignment="Right" Width="96" Height="96" VerticalAlignment="Top" Margin="0,8,19,0"> <Ellipse.Fill> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Color="OrangeRed" Offset="0.0"/> <GradientStop Color="Orange" Offset="0.25"/> <GradientStop Color="Yellow" Offset="0.75"/> <GradientStop Color="MediumVioletRed" Offset="1"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> <Rectangle Margin="9,103,0,17" Name="rectangle2" Stroke="Thistle" HorizontalAlignment="Left" Width="103" StrokeThickness="4"> <Rectangle.Fill> <RadialGradientBrush GradientOrigin="1,1" Center="1,1" RadiusX="1" RadiusY="1"> <RadialGradientBrush.GradientStops> <GradientStop Offset="0.09" Color="Yellow"/> <GradientStop Offset="0.25" Color="Green"/> <GradientStop Offset="0.5" Color="Red"/> <GradientStop Offset="1.25" Color="Blue"/> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </Rectangle.Fill> </Rectangle> <Polygon Points="10,110 60,11,110,110" Stroke="IndianRed" StrokeThickness="4" Canvas.Left="150" Canvas.Top="150" Margin="0,-9,0,9" Fill="IndianRed"></Polygon> </Grid> </Window>

In this code, the shapes are colored using the LinearGradientBrush and the RadialGradientBrush. As you can see in the code, the colors in both the brushes are described using the GardientStop class. The difference is shown in the output of the brushes. When you run the code, by pressing F5, you get the output as shown in Figure 1.7:

20

Using Graphics, Animation, and Multimedia in WPF

Figure 1.7: LinearGradientBrush and RadialGradientBrush

ImageBrush
The ImageBrush paints an area with an image. The ImageSource property of the ImageBrush is used to paint the area. Lets add the ImageBrush to the application. For this, create a WPF application named ImageBrush (available on the CD-ROM) and add the following code given in Listing 1.8 to Window1.xaml: Listing 1.8: ImageBrush
<Window x:Class="ImageBrush.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions"> <Grid> <StackPanel> <Rectangle Width="100" Height="100" Stroke="Red" StrokeThickness="4"> <Rectangle.Fill> <ImageBrush Stretch="UniformToFill" ImageSource="C:\Users\avantika\Documents\Visual Studio 2008\Projects\ImageBrush\Image.jpg" PresentationOptions:Freeze="True" /> </Rectangle.Fill> </Rectangle> <Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="2" Margin="50,50,20,20"> <Rectangle.Fill> <ImageBrush Stretch="Fill" ImageSource="C:\Users\avantika\Documents\Visual Studio 2008\Projects\ImageBrush\Image.jpg" PresentationOptions:Freeze="True" TileMode="Tile"/> </Rectangle.Fill> </Rectangle> </StackPanel> </Grid> </Window>

You need to change the path of the image file specified in this application as well as all the applications in this chapter that are using the image file according to the image location in your system.

In this code, images are added to the application in different views and mode. When you run the code, by pressing F5, you get the output as shown in Figure 1.8:

21

Chapter 1

Figure 1.8: ImageBrush

DrawingBrush and VisualBrush


The DrawingBrush paints an area with a Drawing which can contain shapes, images, and text. The VisualBrush paints an area with a visual which can include a Button, Page, or MediaElement. Lets add DrawingBrush and VisualBrush to the application. For this, create a WPF application named Drawing_VisualBrush (available on the CD-ROM) and add the following code given in Listing 1.9 to Window1.xaml: Listing 1.9: DrawingBrush and VisualBrush
<Window x:Class="Drawing_VisualBrush.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Name="button1"> <Button.Background> <DrawingBrush> <DrawingBrush.Drawing> <GeometryDrawing Brush="Firebrick"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="50" RadiusY="12"/> <EllipseGeometry RadiusX="45" RadiusY="10"/> <EllipseGeometry RadiusX="30" RadiusY="7"/> <EllipseGeometry RadiusX="20" RadiusY="5"/> </GeometryGroup> </GeometryDrawing.Geometry> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Button.Background> </Button> <Rectangle Margin="79,83,76,83" Name="rectangle1" Stroke="Gold"> <Rectangle.Fill> <VisualBrush> <VisualBrush.Visual> <StackPanel Background="AntiqueWhite"> <TextBlock FontSize="10pt" Margin="3"> Hello!!!! </TextBlock> </StackPanel> </VisualBrush.Visual> </VisualBrush> </Rectangle.Fill> </Rectangle> </Grid> </Window>

22

Using Graphics, Animation, and Multimedia in WPF

In this code, DrawingBrush and VisualBrush are applied to the application. When you run the code by pressing F5, you get the output as shown in Figure 1.9:

Figure 1.9: Using DrawingBrush and VisualBrush

Changing the Tile Size and the Pattern of Brushes


You can use the TileMode property of the Brush in WPF to create a pattern. The TileMode property enables you to specify how the content of the Brush is repeated to fill the output area. You can set the TileMode property to Tile, FlipX, FlipY, or FlipXY. The TileMode property works identically for ImageBrush, VisualBrush, and DrawingBrush. You should also set the Viewport property of the Brush to create the tiles. Lets create an application and change the tile size and pattern of brush. For this, create a WPF application named TileSize_Pattern_Brush (available on the CD-ROM) and add the following code given in Listing 1.10 to Window1.xaml: Listing 1.10: Applying TileMode property
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <Page.Resources> <GeometryDrawing x:Key="TileSize" Geometry="M0,0 L50,0 0,50Z" Brush="Aquamarine" PresentationOptions:Freeze="True" > <GeometryDrawing.Pen> <Pen Thickness="2" Brush="PaleVioletRed" MiterLimit="0" /> </GeometryDrawing.Pen> </GeometryDrawing> </Page.Resources> <StackPanel HorizontalAlignment="Center"> <Rectangle Height="96" Name="rectangle1" Stroke="Black" Width="222"> <Rectangle.Fill> <DrawingBrush TileMode="None" Drawing="{StaticResource TileSize}" /> </Rectangle.Fill> </Rectangle> <Rectangle Height="114" Name="rectangle2" Stroke="Black" Width="221"> <Rectangle.Fill> <DrawingBrush TileMode="Tile" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TileSize}"/> </Rectangle.Fill> </Rectangle> <Rectangle Height="112" Name="rectangle3" Stroke="Black" Width="219"> <Rectangle.Fill> <DrawingBrush TileMode="FlipY" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TileSize}" /> </Rectangle.Fill> </Rectangle> <Rectangle Height="102" Name="rectangle4" Stroke="Black" Width="218">

23

Chapter 1
<Rectangle.Fill> <DrawingBrush TileMode="FlipXY" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TileSize}" /> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>

You can change the root element of the application to Page in a WPF application.

In this code, the DrawingBrush is used to create four rectangles and each is given a different TileMode setting. When you run code by pressing F5, you get the output as shown in Figure 1.10:

Figure 1.10: Changing Tile Size and Pattern of Brush

Creating Reflections using VisualBrush


In WPF, you can use the VisualBrush to create the reflection of the image used to paint the area. VisualBrush has the capability to display an existing visual, so you can use the VisualBrush to create interesting visual effects, such as reflection. Lets create reflections of images using VisualBrush. For this, create a WPF application named CreatingReflection (available on the CD-ROM) and add the following code given in Listing 1.11 to Window1.xaml: Listing 1.11: Creating Reflection
<Window x:Class="CreatingReflection.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="700" Width="700"> <Window.Background> <LinearGradientBrush StartPoint="0,0.3" EndPoint="1,0"> <LinearGradientBrush.GradientStops> <GradientStop Color="Pink" Offset="0.1" /> <GradientStop Color="Plum" Offset="0.3" /> <GradientStop Color="PeachPuff" Offset="0.5" /> <GradientStop Color="AliceBlue" Offset="0.7" /> <GradientStop Color="Beige" Offset="0.9" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Window.Background> <Grid> <StackPanel Margin="10"> <Border BorderBrush="Pink" BorderThickness="4" Width="450" Height="400"> <Image Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\CreatingReflection\Flower.jpg" Width="400" Height="300" Name="Flower" /> </Border>

24

Using Graphics, Animation, and Multimedia in WPF


<Border Width="450" Height="400" Opacity="0.7" BorderBrush="White" BorderThickness="4"> <Border.OpacityMask> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0" Color="White"/> <GradientStop Offset="0.6" Color="Transparent"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.OpacityMask> <Border.Background> <VisualBrush Visual="{Binding ElementName=Flower}"> <VisualBrush.Transform> <ScaleTransform ScaleX="1" ScaleY="-1" CenterX="200" CenterY="150" /> </VisualBrush.Transform> </VisualBrush> </Border.Background> </Border> </StackPanel> </Grid> </Window>

In the following code, the reflection of the image is created by using VisualBrush. When you run code by pressing F5, you get the output as shown in Figure 1.11:

Figure 1.11: Creating Reflection

Preserving the Aspect Ratio of Image


The word aspect ratio means the ratio of the height and width of an image. By preserving the aspect ratio, we mean to maintain the height and width of the image to the original size, when used in a larger output area. The aspect ratio of an image is preserved using the Stretch property of the ImageBrush. By default, when you use an ImageBrush to paint an area, the content stretches itself completely to fill the output area. When the output area and the image have different aspect ratio, the image gets distorted by stretching. Therefore, to preserve the aspect ratio of the image, set the Stretch property of ImageBrush to Uniform or UniformToFill. Lets create an application to preserve the aspect ratio of the image. For this, create a WPF application named PreservingAspectRatio (available on the CD-ROM) and add the following code given in Listing 1.12 to Window1.xaml:

25

Chapter 1

Listing 1.12: Preserving Aspect Ratio


<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <StackPanel Height="450" Width="400"> <Rectangle Width="300" Height="150" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <ImageBrush Stretch="Uniform" ImageSource="C:\Users\avantika\Documents\Visual Studio 2008\Projects\PreservingAspectRatio\pattern.jpg" /> </Rectangle.Fill> </Rectangle> <Rectangle Width="300" Height="150" Stroke="Black" StrokeThickness="1" Margin="0,10,0,0"> <Rectangle.Fill> <ImageBrush Stretch="UniformToFill" ImageSource="C:\Users\avantika\Documents\Visual Studio 2008\Projects\PreservingAspectRatio\pattern.jpg" /> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>

In this code, the same image is displayed in two different ways. In the first image, the Stretch property of the image is set to Uniform and thus preserving the aspect ratio of the image. In the second image, the Stretch property of the image is set to UniformToFill. When you run code by pressing F5, you get the output as shown in Figure 1.12:

Figure 1.12: Preserving the AspectRatio of the Image

3-D Graphics
WPF provides a set of 3-D graphics that integrate with 2-D graphics in order to create visually appealing layout, user interface, and data visualization. The 3-D implementation in WPF allows developers to draw, transform, and animate the 3-D graphics in both XAML and code. You can combine the 2-D and 3-D graphics to create rich controls and enhance the user experience of an application interface. The most important objects used in the creation of 3-D graphics in WPF are Viewport3D, Camera, Materials and Lights, which we will discuss next.

26

Using Graphics, Animation, and Multimedia in WPF

The Viewport3D Class


In WPF, if you want to work with 3-D content, you need a container that can host it. The container is the Viewport3D class, which is found in the System.Windows.Controls namespace. The Viewport3D class derives itself from the FrameworkElement class, and so you can place it anywhere you would place a normal element. The Viewport3D control displays 3-D content while providing properties consistent with the 2-D layout, such as clipping, height, width, and mouse event. There are two important properties of the Viewport3D class Camera and Children. The Camera property of the Viewport3D class defines the lookout of the content on the 3-D scene and the Children property holds all the 3-D objects that you want to place in the scene. The light source that lights the 3-D scene is an object of the Viewport3D class. You can add a Viewport3D to your application by adding the following code:
<Viewport3D> <!-- Children --> </Viewport3D>

The inheritance hierarchy of the Viewport3D class is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Viewport3D

The noteworthy properties of the Viewport3D class are listed in Table 1.19: Table 1.19: Property of Viewport3D Class

Property
Camera Children

Description
Gets or sets a camera object that projects the 3-D contents of the Viewport3D to the 2-D surface of the Viewport3D Retrieves a collection of the Visual3D children of the Viewport3D

Cameras
The camera in WPF is an essential element for rendering 3-D Graphics. You need to place the camera at the correct position and adjust it in the correct direction before actually rendering a 3-D scene. You can do this by setting the Camera property of the Viewport3D class. The camera in WPF is represented by the System.Windows.Media.Media3D namespace. The Camera class represents an imaginary viewing position and direction in a 3-D coordinate space that describes how a 3-D model is projected on a 2-D visual. The inheritance hierarchy of the Camera class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Media3D.Camera

The noteworthy methods of the Camera class are listed in Table 1.20: Table 1.20: Methods of ProjectionCamera Class

Method
Clone CloneCurrentValue ToSring

Description
Creates a modifiable clone of this Camera class Creates a modifiable clone of this Camera object, making deep copies of this objects current values Creates a string representation of the Camera class

27

Chapter 1

The noteworthy property of the ProjectionCamera class is listed in Table 1.21: Table 1.21: Property of ProjectionCamera Class

Property
Transform

Description
Retrieves or sets the Transform3D applied to the camera

WPF includes three Camera classes as follows: PerspectiveCameraRenders the scene so that the object that are farther, appear smaller OrthographicCameraFlattens the 3-D objects so that the exact scale is preserved MatrixCameraSpecify a matrix that is used to transform the 3-D scene to a 2-D view Here, we are discussing the two important camera classes, i.e. PerspectiveCamera OrthographicCamera, in detail.

and

PerspectiveCamera Class
The PerspectiveCamera class represents a perspective projection camera. The PerspectiveCamera renders the scene so that the objects that are farther away appear smaller. The PerspectiveCamera class is derived from the ProjectionCamera base class. The PerspectiveCamera is the most versatile and the most commonly used camera in WPF. The PerspectiveCamera specifies the projection of a 3-D model object to a 2D visual surface. The object described using the PerspectiveCamera have their sides converge toward a point on the horizon. The objects that are closer to the Camera appear larger, and the objects farther from the Camera appear smaller. You can limit the range of camera projection by setting the NearPlaneDistance and FarPlaneDistance properties. The NearPlaneDistance property allows you to specify a minimum distance from the camera of the near clip plane. On the other hand, the FarPlaneDistance property allows you to specify a distance from the camera of the far clip plane, which ensures that objects too far away are not included in the scene. You can add a PerspectiveCamera to your application by adding the following code:
<PerspectiveCamera .../>

The inheritance hierarchy of the PerspectiveCamera class is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Media3D.Camera System.Windows.Media.Media3D.ProjectionCamera System.Windows.Media.Media3D.PerspectiveCamera

The noteworthy property of the PerscpectiveCamera class is listed in Table 1.22. Table 1.22: Property of PerspectiveCamera class

Property
FieldOfView

Description
Gets or sets a value that represents the cameras horizontal field of view

OrthographicCamera
The OrthographicCamera class represents an orthographic projection camera. The OrthographicCamera class specifies an orthogonal projection of a 3-D model to a 2-D visual surface. The OrthographicCamera specifies a position, viewing direction, and upward direction. The OrthographicCamera class describes a viewing box whose sides are parallel, instead of one whose sides meet in a point at the horizon like the PerspectiveCamera. The OrthographicCamera flattens the 3-D objects so that the exact scale is preserved, not matter where a shape is positioned. You can add an OrthographicCamera to your application by adding the following code:
<OrthographicCamera .../>

The inheritance hierarchy of the OrthographicCamera class is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject

28

Using Graphics, Animation, and Multimedia in WPF


System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Media3D.Camera System.Windows.Media.Media3D.ProjectionCamera System.Windows.Media.Media3D.OrthographicCamera

The noteworthy property of the OrthographicCamera class is listed in Table 1.23. Table 1.23: Property of OrthographicCamera class

Property
Width

Description
Gets or sets the width of the cameras viewing box, in world units

3-D Models and Materials


When you are working with complex 3-D scenes, you will always need to arrange multiple objects to get the perfect result. Till now, you have seen the bare bones of the WPF 3-D support. You should now learn to create more complex shapes and figures. 3-D Models in WPF are used to create complex shapes. Material is used to apply texture, or the skin to the complex shape. In this section, you will learn about creating complex models and applying materials to them.

3-D Models
All 3-D modeling programs in WPF include basic primitives or mesh. A basic 3-D primitive is a collection of vertices that form a single 3-D entity. For example, a triangle defined by three vertices. The three points in a triangle is coplanar. You can build a more complex shape by using mesh. When you build a model in WPF, you begin by building a primitive or a mesh. After building the complex shape, you can use these primitives or mesh to create the required scene. You can take the example of the sphere in WPF, which is built out of smaller triangles. You can also take the example of the simple closed figure, triangle which is defined by three vertices. The ModelVisual3D class represents the visual that contains the 3-D models. This class provides services and properties that are common to all the visual objects. The entire scene of the visual is defined in a single ModelVisual3D class and contains the Model3DGroup. The Model3DGroup class allows the developer to apply transformations or animations to group the 3-D models as if they were a single model. The Model3D is the abstract base class that represents a generic 3-D object and provides functionality for the 3-D models. To build a typical 3-D scene, you need some objects to view and some objects that make up the scene graph that derive themselves from the Model3D class. The classes that derive themselves from the Model3D class and help in building the 3-D scene are GeometryModel3D class, and MeshGeometry3D class. The MeshGeometry3D class provides triangle primitive for building a 3-D shape or any geometry. The MeshGeometry3D allows the developer to specify the position and texture coordinate information by specifying the Positions property. Once you have properly configured MeshGeometry3D, you need to wrap it in a GeometryModel3D class. The modeling geometries in WPF are supported with the GeometryModel3D class. The GeometryModel3D objects are responsible for defining the objects and their materials. The GeometryModel3D has only three important properties, Geometry, Material, and BackMaterial. The Geometry property takes the MeshGeometry3D that defined the shape of your object. The Material property gets or sets the material of the GeometryModel3D. Similarly, the BackMaterial property also gets or sets the material to be applied to the back of the object. The Material and BackMaterial property defines the surface of the shape. The surface is important for two reasons; first, it defines the color of the object, and second, it defines how the material responds to light.

Materials for 3-D Models


When you create a Geometry3D object, you should specify not only the vertex of the shape, but also the material out of which it is composed. In 2-D, you use the Brush to apply colors and patterns to make the object visible. In 3-D, however, you need to apply texture to cover the surface for a mesh to look like a 3D object. For applying texture, WPF uses the Material abstract class. WPF includes following three material classes, all of which derive from the abstract Material class in the System.Windows.Media.Media3D namespace:

29

Chapter 1

The DiffuseMaterial classSpecifies that the brush will be applied to the model evenly. The DiffuseMaterial allows the application of a 2-D brush, like a SolidColorBrush to diffusely light a 3-D model. The DiffuseMaterial diffuses light evenly in all the directions. The SpecularMaterial classCreates a glossy and highlighted look. It reflects the light back directly like a mirror. The SpecularMaterial specifies that the brush will be applied to the models as if the model surface is hard which is capable of reflecting lights. You can set the degree to which the texture will reflect the light by specifying the SpecularPower property. The EmmissiveMaterial classCreates a glowing look by generating its own light. This light does not reflect off other objects in the scene. It allows you to specify the texture that will be applied as though the model is emitting light equal to the color of the brush. You can apply multiple Materials to the scene by using the MaterialGroup class. For example, you may choose to apply a complex texture to a mesh using the DiffuseMaterial, and also add a highlighting effect with the SpecularMaterial on the same mesh. MaterialGroup allows you to treat these Materials as a single texture.

Lights
After adding model and material to the scene, you need to add a light source to the scene to make it visible. The light effects in WPF are calculated for objects individually. The light that reflects from one object will not reflect off another object. In the same way, an object will not cast its shadow on another object, no matter where it is placed. Light class is the abstract base class for using light in WPF. WPF provides following four light classes for the implementation of light in WPF: The DirectionalLight classIlluminates light like a distant light source. The DirectionalLight lights the object that projects its effect along a direction specified by the Vector3D. The light specified by the DirectionalLight comes from one side and you can see the edges and shadow. You can take the example of Sunlight in context of DirectionalLight. The AmbientLight classProvides an unnatural light that lights the scene with scattered light. The AmbientLight lights the object uniformly regardless of the shape, location or orientation. The PointLight classRadiates light in all directions, beginning at a single point. The PointLight have a position and they point the light from that position. The objects in the scene are illuminated depending on their position and distance with respect to the light. The Range property of the PointLight determines the distance beyond which the models will not be illuminated by light. The SpotLight classRadiates light outward in a cone style starting from a single point. The SpotLight inherits from PointLight. The InnerConeAngle and OuterConeAngle property specify the area of the projection of the light in the cone shaped area.

Using 3-D Graphics in WPF 3.5


The 3-D graphics in WPF includes the Viewporst3D class, the Cameras, Model, Material, and Lights. You can create a rich looking application in 3-D graphics by combining the shapes of WPF. In this section, you will learn about the practical application of the 3-D graphics concepts that we discussed earlier.

Creating 3-D Models


When you create 3-D model in WPF, you keep few things in mind. Firstly, you need a Viewport3D, so that you can create a three dimensional scene. The Viewport3D acts like a container control for the 3-D model. Secondly, you need a Camera added to the application so that you can view the 3-D model. Thirdly, you need to apply Material to the 3-D model. Keeping all these in mind, lets create a 3d model. For this, create a WPF application named 3DModel (available on the CD-ROM) and add the following code given in Listing 1.13 to Window1.xaml: Listing 1.13: Creating 3-D Model
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Viewport3D> <Viewport3D.Camera>

30

Using Graphics, Animation, and Multimedia in WPF


<PerspectiveCamera Position="-2,2,3" LookDirection="2,-2,-3" UpDirection="2,-4,-9" /> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="Pink" Direction="0,-1,-1" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="-1,0,0 0,1,0 0,0,1" TriangleIndices="0,2,1" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.9"> <LinearGradientBrush.GradientStops> <GradientStop Color="Wheat" Offset="0.1" /> <GradientStop Color="Pink" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D> </Page>

In this code, we are actually creating a 3-D model by adding Viewport3D, Camera, Model, and Material. The output of the code is shown in Figure 1.13.

Using Materials on 3-D Models


Materials are the texture of the 3-D model. You cannot view a 3-D model until, you add Material to the model. For adding Material to the 3-D model, you can take a reference of the code given in Listing 1.11. In the Listing 1.14, we have added Material to the 3-D model, so that you can view the model. The code given in this Listing 1.14 is a part of Listing 1.13, which deals with adding Material to the 3-D model: Listing 1.14: Adding Material
<GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.9"> <LinearGradientBrush.GradientStops> <GradientStop Color="Wheat" Offset="0.1" /> <GradientStop Color="Pink" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material>

In this code, you are adding Material to the 3-D model which you have created in Listing 1.11. When you run the full code by pressing F5, you get the output as shown in Figure 1.13:

31

Chapter 1

Figure 1.13: Creating 3-D Model

Using DrawingBrush to Apply Material on 3-D Models


You have learned about applying Material to the 3-D model in the previous section. In the code given in Listing 1.13, to apply Material to a 3-D model, we have used the LinearGradientBrush. You can also use the DrawingBrush to apply Material on 3-D model. The use of DrawingBrush helps you in creating different patterns in 3-D model. Lets use the DrawingBrush to apply Material on a 3-D model. For this, create a WPF application named MaterialusingDrawingBrush (available on the CD-ROM) and add the following code given in Listing 1.15 to Window1.xaml: Listing 1.15: Using DrawingBrush to Add Material
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Canvas Width="300" Height="200"> <Viewport3D ClipToBounds="True" Width="275" Height="200" Canvas.Left="0" Canvas.Top="10"> <Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-2" FieldOfView="55" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-0.6,-0.5,-0.5" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,3 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial> <DiffuseMaterial.Brush> <DrawingBrush Viewport="0,0.3,0.1,0.1" TileMode="FlipXY"> <DrawingBrush.Drawing> <DrawingGroup> <DrawingGroup.Children>

32

Using Graphics, Animation, and Multimedia in WPF


<GeometryDrawing Geometry="M0,0.1 L0.1,0 1,0.9, 0.9,1z" Brush="Pink" /> <GeometryDrawing Geometry="M0.25,0.25 L0.5,0.125 0.75,0.25 0.5,0.5z" Brush="Aqua" /> <GeometryDrawing Geometry="M0.25,0.75 L0.5,0.875 0.75,0.75 0.5,0.5z" Brush="Salmon" /> <GeometryDrawing Geometry="M0.25,0.75 L0.125,0.5 0.25,0.25 0.5,0.5z" Brush="Red" /> </DrawingGroup.Children> </DrawingGroup> </DrawingBrush.Drawing> </DrawingBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,2,1" Angle="30" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Canvas> </Page>

In this code, a 3-D pattern is created. The Material on the 3-D model is added using the DrawingBrush. When you run the code by pressing F5, you get the output as shown in Figure 1.14:

Figure 1.14: Adding Material using DrawingBrush

Adding Cameras
The 3-D scene that you are creating is actually a 2-D representation of a 3-D object. The 3-D scene looks different depending upon the viewer angle of view. So, you must specify the angle of view. For this purpose, Camera is used in WPF to specify the point of view of the 3-D scene. There are three types of Camera available in WPF,

33

Chapter 1

MatrixCamera, OrthographicCamera and PerspectiveCamera. In this section, we will discuss about the two most important and most used camera in WPF: OrthographicCamera PerspectiveCamera

OrthographicCamera
The OrthographicCamera describes the points that are parallel to the angle of view, instead of the one whose sides meet in the point of Camera. Lets learn the usage of the OrthographicCamera. For this, create a WPF application named OrthographicCamera (available on the CD-ROM) and add the following code given in Listing 1.16 to Window1.xaml: Listing 1.16: Using OrthographicCamera
<Window x:Class="OrthographicCamera.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Viewport3D> <Viewport3D.Camera> <OrthographicCamera LookDirection="7,-3,-4" UpDirection="1,1,100" Position="-5.5,2.5,3" /> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0" Normals="0 0 1 0 0 1 0 0 1 0 0 1" TextureCoordinates="1 0 1 1 0 0 1 0" TriangleIndices="0 1 2 1 3 2" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.9"> <LinearGradientBrush.GradientStops> <GradientStop Color="Wheat" Offset="0.1" /> <GradientStop Color="Pink" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </GeometryModel3D.Material> </GeometryModel3D> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D> </Grid> </Window>

In this code, a solid figure is created which is viewed on the surface using the OrthographicCamera. When you run the code by pressing F5, you get the output as shown in Figure 1.15:

34

Using Graphics, Animation, and Multimedia in WPF

Figure 1.15: OrthographicCamera

PerspectiveCamera
PerspectiveCamera specifies a projection that makes the scene short. The PerspectiveCamera describes the area whose sides converge toward a point on the horizon. Lets learn the usage of PerscpectiveCamera. For this, create a WPF application named PerspectiveCamera (available in the CD) and add the following code given in Listing 1.17 to Window1.xaml: Listing 1.17: Using PerspectiveCamera
<Window x:Class="PerspectiveCamera.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Viewport3D> <Viewport3D.Camera> <PerspectiveCamera LookDirection="6,-3,-4" UpDirection="0,0,1" Position="-5,2.5,3" FieldOfView="30" /> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0" Normals="0 0 1 0 0 1 0 0 1 0 0 1" TextureCoordinates="1 0 1 1 0 0 1 0" TriangleIndices="0 1 2 1 3 2" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" Opacity="0.9"> <LinearGradientBrush.GradientStops> <GradientStop Color="Wheat" Offset="0.1" /> <GradientStop Color="Pink" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </GeometryModel3D.Material> </GeometryModel3D> </Model3DGroup> </ModelVisual3D.Content>

35

Chapter 1
</ModelVisual3D> </Viewport3D> </Grid> </Window>

In this code, a solid figure is created which is viewed on the surface using the PerspectiveCamera. When you run the code by pressing F5, you get the output as shown in Figure 1.16:

Figure 1.16: Adding PerspectiveCamera

At this point, you can see the difference between the OrthographicCamera and PerspectiveCamera. The same figure is created for both Camera; the only difference is the way of angle in which they are viewed.

Adding Lights
Lights in WPF make the graphic visible on the Window. As discussed earlier, there are four kinds of light available in WPF, such as AmbeintLight, DirectionalLight, PointLight, and SpotLight. All the four types of light create a variety of light and shadow effect in WPF. Lets add the different types of light to the WPF application. For this create a WPF application named AddingLight (available on the CD) and add the following code given in Listing 1.18 to Window1.xaml: Listing 1.18: Adding Light to the WPF application
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Canvas Width="421" Height="301"> <Viewport3D ClipToBounds="True" Width="100" Height="100" Canvas.Left="0" Canvas.Top="1"> <Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="20" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-0.4,-0.7,-0.9" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material>

36

Using Graphics, Animation, and Multimedia in WPF


<MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <LinearGradientBrush.GradientStops> <GradientStop Color="Blue" Offset="0" /> <GradientStop Color="White" Offset="0.25" /> <GradientStop Color="Red" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,2,1" Angle="40" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> <Viewport3D ClipToBounds="True" Width="100" Height="100" Canvas.Right="100" Canvas.Top="1"> <Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="40" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <AmbientLight Color="Pink" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <LinearGradientBrush.GradientStops> <GradientStop Color="White" Offset="0" /> <GradientStop Color="Purple" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" />

37

Chapter 1
<GradientStop Color="Green" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,3,0" Angle="20" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> <Viewport3D ClipToBounds="True" Width="100" Height="100" Canvas.Right="100" Canvas.Bottom="1"> <Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="20" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <PointLight Color="Wheat" Position="0,1,1.5"/> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <SolidColorBrush Color="Bisque"/> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,3,0" Angle="40" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> <Viewport3D ClipToBounds="True" Width="100" Height="100" Canvas.Left="0" Canvas.Bottom="1">

38

Using Graphics, Animation, and Multimedia in WPF


<Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="40" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <SpotLight Color="Yellow" InnerConeAngle="50" OuterConeAngle="25" Direction="0,0,-1" Position="1,1,6" Range="10"/> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <LinearGradientBrush.GradientStops> <GradientStop Color="Green" Offset="0" /> <GradientStop Color="SpringGreen" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,3,0" Angle="30" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Canvas> </Page>

In this code, the usage of the four types of light is shown. When you run the code by pressing F5, you get the output as shown in Figure 1.17:

39

Chapter 1

Figure 1.17: Adding Light

Transforming 3-D Models


You can apply transformation on the 3-D models in the same way as you have applied on the 2-D model. The different types of transformation that you can apply to the 3-D model are TranslateTransform3D, ScaleTransform3D, and RotateTransform3D. Transfomation allows you to resize and re-orient the 3-D models without changing the base clause that defines them. The 3-D transformation that you apply in a WPF application inherits from the Transfom3D base class.

TranslateTransform3D
The TranslateTransfom3D moves all the points of the 3-D model in the direction of the offset vector which you specify with OffsetX, OffsetY, and OffsetZ. Lets create a 3-D model on which you can apply the TranslateTransform3D. For this, create a WPF application named TranslateTransform3D (available on the CD-ROM) and add the following code given in Listing 1.19 to Window1.xaml: Listing 1.19: Applying TranslateTransform3D
<Window x:Class="TranslateTransform3D.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <DockPanel> <Canvas Width="300" Height="300"> <Viewport3D ClipToBounds="True" Width="200" Height="200"> <Viewport3D.Camera> <PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="Pink" Direction="-0.612372,-0.5,0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material>

40

Using Graphics, Animation, and Multimedia in WPF


<MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <SolidColorBrush Color="LightYellow" Opacity="0.9"/> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <TranslateTransform3D OffsetX="1" OffsetY="0" OffsetZ="0" /> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Canvas> </DockPanel> </Window>

In this code, the 3-D model is moved according to the OffsetX, OffsetY, and OffsetZ properties of the TranslateTransform. When you run the code by pressing F5, you get the output as shown in Figure 1.18:

Figure 1.18: TranslateTransform3D

ScaleTransform3D
The ScaleTransform3D scales the 3-D model by a specified vector with reference to the center point. You can specify the same value in ScaleX, ScaleY, and ScaleZ properties, so that the 3-D model scales by the same value in the X, Y, and Z axis. Lets create a 3-D model on which you can apply ScaleTransfom3D. For this, create a WPF application named ScaleTransform3D (available on the CD-ROM) and add the following code given in Listing 1.20 to Window1.xaml: Listing 1.20: Applying ScaleTransform3D
<Window x:Class="ScaleTransform3D.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <DockPanel> <Canvas Width="321" Height="201"> <Viewport3D Width="150" Height="150" Canvas.Left="0" Canvas.Top="10"> <Viewport3D.Camera> <PerspectiveCamera Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D>

41

Chapter 1
<ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-0.612372,0.5,-0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <LinearGradientBrush.GradientStops> <GradientStop Color="Yellow" Offset="0.25" /> <GradientStop Color="Red" Offset="0.75" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <ScaleTransform3D ScaleX="1" ScaleY="1.5" ScaleZ="1.5" CenterX="1" CenterY="1" CenterZ="1" /> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Canvas> </DockPanel> </Window>

In this code, the 3-D model is sized according to the ScaleX, ScaleY, and ScaleZ property of the ScaleTransform3D. When you run the code by pressing F5, you get the output as shown in Figure 1.19:

Figure 1.19: ScaleTransform3D

42

Using Graphics, Animation, and Multimedia in WPF

RotateTransform3D
You can rotate a 3-D model in different ways using RotateTransfom3D. A typical rotation is the one in which you specify an axis and an angle of rotation around the axis. The rotation is defined using the Rotation property. The axis angle of the rotation is defined using the Axis and Angle property. Lets create a 3-D model on which you can apply the RotateTransfom3D. For this, create a WPF application named RotateTransform3D (available on the CD-ROM) and add the following code given in Listing 1.21 to Window1.xaml: Listing 1.21: Applying RotateTransfom3D
<Window x:Class="RotateTransform3D.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <DockPanel> <Canvas Width="321" Height="201"> <Viewport3D Width="150" Height="150" Canvas.Left="0" Canvas.Top="10"> <Viewport3D.Camera> <PerspectiveCamera x:Name="myPerspectiveCamera" Position="0,0,2" LookDirection="0,0,-1" FieldOfView="60" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-0.612372,0.5,-0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="0.612372,-0.5,0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Color="Yellow" Offset="0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,2,1" Angle="45" />

43

Chapter 1
</RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </Canvas> </DockPanel> </Window>

In this code, the 3-D model is rotated by specifying the Axis and Angle properties of the RotateTransform3D. When you run the code by pressing F5, you get the output as shown in Figure 1.20:

Figure 1.20: RotateTransform3D

Animation in WPF 3.5


Animation in WPF allows you to create dynamic user interface. You can apply different effects using animation, such as growing icons or scrolling text. Animations in WPF can be used in many ways to enhance applications. In WPF, you can create animations and also put them into action without writing a single line of code, that is, you can create animations declaratively. You firstly create a timer that fires periodically. When the timer fires, you need to use an event handler to calculate the animation related details. WPF notices the change you have made to the elements in your window. It then repaints the new window content. WPF includes an efficient timing system through the managed code and XAML. In WPF, you animate objects by applying animations to their individual properties. For example, to make an element grow, you animate its Height and Width property. For a property to have the animation capabilities, you must keep three requirements in mind. The firstly, it must be a dependency property. Secondly, the property must belong to a class that inherits from DependencyObject and implements the IAnimatable interface. Thirdly, a compatible animation type should be available. The System.Windows.Media.Animation namespace is the base for all the following animations in WPF: Types of Animation Essentials of Animation Event Triggers and animation KeyFrames Lets discuss these in detail.

44

Using Graphics, Animation, and Multimedia in WPF

Types of Animation
As stated earlier, animations generate property values, different animation types exist for different property types. For example, to animate a property that takes a Double, such as the Width property of the element, you use an animation that produces Double value. Since there are number of different property types, there are several animation classes in the System.Windows.Media.Animation namespace. All of them follow a strict naming convention and thus can be categorized in three parts, as follows: Basic Animation KeyFrame Animation Path Animation Lets discuss these in detail.

Basic Animation
The Basic animation in WPF creates a transition between two target values. The Basic animation animates between a starting and destination value or by adding an offset value to its starting value. The From property of the animation defines the starting point of the animation. The ending value is defined by setting the To property of the animation. The By property of the animation specifies an offset value. You can use the From, To, and By properties which can be used together or separately to determine an animation target value. The resulting behavior of the From, To, and By properties are listed in Table 1.24: Table 1.24: Resulting Behavior of the properties

Property
From From and To From and By To By

Resulting Behavior
The animation progresses from the value specified by the From property to the base value of the property being animated or to a previous animations output value These two properties are used together for the animation to progress from the value specified by the From property to the value specified by the To property These two properties are used together for the animation to progress from the value specified by the From property to the value specified by the sum of the From and By properties The animation progresses from the animated propertys base value or a previous animations output value to the value specified by the To property The animation progresses from the base value of the property being animated or a previous animations output value to the sum of that value and the value specified by the By property

You should not set the To and By property in the same animation.

KeyFrame Animation
The KeyFrame animations are a better choice in animations in comparison to the Basic animation. In the KeyFrame animation, you can specify any number of target values. The KeyFrame animation animates the value of the target property. A KeyFrame animation target value is described using KeyFrame objects. To specify the animation target value, you need to create KeyFrame objects and add them to the animation KeyFrame collection. For specifying animation with KeyFrame animation, you need to follow a particular sequence: You declare an animation and specify its Duration. For each target value, you need to create a KeyFrame of the appropriate type, set its value and KeyTime, and add it to the KeyFrame collection. To complete the animation process, associate the animation with a property like the Basic animation. There are different KeyFrame animation classes for different property type which are listed in Table 1.25:

45

Chapter 1

Table 1.25: KeyFrame animation classes

Property Type
Boolean Byte Color Decimal Double Int16 Int32 Int64 Matrix Object Point Quaternion Rect Rotation3D Single String Size Thickness Vector3D Vector

Animation Classes
BooleanAnimationUsingKeyFrames ByteAnimationUsingKeyFrames ColorAnimationUsingKeyFrames DecimalAnimationUsingKeyFrames DoubleAnimationUsingKeyFrames Int16AnimationUsingKeyFrames Int32AnimationUsingKeyFrames Int64AnimationUsingKeyFrames MatrixAnimationUsingKeyFrames ObjectAnimationUsingKeyFrames PointAnimationUsingKeyFrames QuaternionAnimationUsingKeyFrames RectAnimationUsingKeyFrames Rotation3DAnimationUsingKeyFrames SingleAnimationUsingKeyFrames StringAnimationUsingKeyFrames SizeAnimationUsingKeyFrames ThicknessAnimationUsingKeyFrames Vector3DAnimationUsingKeyFrames VectorAnimationUsingKeyFrames

The basic purpose of KeyFrame animation is to specify the KeyTime and Value property. The Value property specifies the target value for the KeyFrame. The KeyTime property specifies when the KeyFrame Value property is achieved. When the KeyFrame animation begins, it iterates through its key frames in the order defined by their KeyTime properties. If there is no KeyFrame at time 0, the animation creates a transition between the current value of target property and the Value of the first KeyFrame.
If you set the animation Duration to Automatic or equal to the time of the last KeyFrame, the animation ends.

Path Animation
A Path base animation modifies a value to correspond with the shape that is described by a PathGeometry object. It is primarily useful for moving an element along a Path. Path animation can be used to modify any property that has the right data type. Path animation is most useful when animating position related properties. When you create a Path based animation, you do not supply the starting and ending values, but the PathGeometry. The collection of lines and curves that constitute the Path determines the value that will be used for the animated property.
A Path based animation, always runs at a continuous speed. The total length of the Path and the duration that you have specified, determines the speed.

Animation Classes
You have learned about the different types of animation in WPF, such as Basic animation, KeyFrame animation, and Path animation. Although, WPF uses these three types of animations currently, you can create more animation classes that modify values using a completely different approach. These different types of animation

46

Using Graphics, Animation, and Multimedia in WPF

are contained in the System.Windows.Media.Animation namespace. Speaking in the broader sense, there are actually two kinds of animation: Those that vary a property incrementally between the staring and finishing values. Those that abruptly change a property from one value to another. The different types of animation classes available in the System.Windows.Media.Animation namespace are listed in Table 1.26: Table 1.26: Classes of System.Windows.Media.Animation namespace

Class
Animatable AnimationClock AnimationException AnimationTimeline BeginStoryboard BooleanAnimationUsingKeyFrames BooleanKeyFrame BooleanKeyFrameCollection ByteAnimation ByteAnimationUsingKeyFrames ByteKeyFrame ByteKeyFrameCollection CharAnimationUsingKeyFrames CharKeyFrame CharKeyFrameCollection Clock ClockCollection ClockController ColorAnimation ColorAnimationBase ColorAnimationUsingKeyFrames ColorKeyFrame ColorKeyFrameCollection ControllableStoryboardAction DecimalAnimation DecimalAnimationBase DecimalAnimationUsingKeyFrames

Description
Provides animation support Maintains the run-time state of an AnimationTimeline and processes its output values Thrown when an error occurs while animating a property Defines a segment of time over which output values are produced Begins a Storyboard and distributes its animations to their targeted objects and properties Animates the value of a property that takes a Boolean along a set of KeyFrames over a specified Duration Defines a segment with its own target value and interpolation method for a BooleanAnimationUsingKeyFrames Represents a collection of BooleanKeyFrame objects Animates the value of a Byte property between two target values using linear interpolation over a specified Duration Animates the value of a Byte property along a set of KeyFrames Defines an animation segment with its own target value and interpolation method for a ByteAnimationUsingKeyFrames Represents a collection of ByteKeyFrame objects Animates the value of a Char property along a set of KeyFrames over a specified Duration Defines an animation segment with its own target value and interpolation method for a CharAnimationUsingKeyFrames Represents a collection of CharKeyFrame objects Maintains run-time timing state for a Timeline Represents an ordered collection of Clock objects Interactively controls a Clock Animates the value of a Color property between two target values using linear interpolation over a specified Duration Animates a Color value Animates the value of a Color property along a set of KeyFrames over a specified Duration Defines an animation segment with its own target value and interpolation method for a ColorAnimationUsingKeyFrames Represents a collection of ColorKeyFrame objects Manipulates a Storyboard that has been applied by a BeginStoryboard action Animates the value of a Decimal property between two target values using linear interpolation over a specified Duration Animates a Decimal value Animates the value of a Decimal property along a set of KeyFrames

47

Chapter 1

Table 1.26: Classes of System.Windows.Media.Animation namespace

Class
DecimalKeyFrame DecimalKeyFrameCollection DiscreteBooleanKeyFrame DiscreteByteKeyFrame DiscreteCharKeyFrame DiscreteColorKeyFrame DiscreteDecimalKeyFrame DiscreteDoubleKeyFrame DiscreteInt16KeyFrame DiscreteInt32KeyFrame DiscreteInt64KeyFrame DiscreteMatrixKeyFrame DiscreteObjectKeyFrame DiscretePoint3DKeyFrame DiscretePointKeyFrame DiscreteQuaternionKeyFrame DiscreteRectKeyFrame DiscreteRotation3DKeyFrame DiscreteSingleKeyFrame DiscreteSizeKeyFrame DiscreteStringKeyFrame DiscreteThicknessKeyFrame DiscreteVector3DKeyFrame DiscreteVectorKeyFrame

Description
Defines an animation segment with its own target value and interpolation method for a DecimalAnimationUsingKeyFrames Represents a collection of DecimalKeyFrame objects Animates from the Boolean value of the previous key frame to its own Value using discrete interpolation Animates from the Byte value of the previous key frame to its own Value using discrete interpolation Animates from the Char value of the previous key frame to its own Value using discrete interpolation Animates from the Color value of the previous key frame to its own Value using discrete interpolation Animates from the Decimal value of the previous key frame to its own Value using discrete interpolation Animates from the Decimal value of the previous key frame to its own Value using discrete interpolation Animates from the Int16 value of the previous key frame to its own Value using discrete interpolation Animates from the Int32 value of the previous key frame to its own Value using discrete interpolation Animates from the Int64 value of the previous key frame to its own Value using discrete interpolation Animates from the Matrix value of the previous key frame to its own Value using discrete interpolation Animates from the Object value of the previous key frame to its own Value using discrete interpolation Animates from the Point3D value of the previous key frame to its own Value using discrete interpolation Animates from the Point value of the previous key frame to its own Value using discrete interpolation Animates from the Quaternion value of the previous key frame to its own Value using discrete interpolation Animates from the Rect value of the previous key frame to its own Value using discrete interpolation Animates from the Rotation3D value of the previous key frame to its own Value using discrete interpolation Animates from the Single value of the previous key frame to its own Value using discrete interpolation Animates from the Size value of the previous key frame to its own Value using discrete interpolation Animates from the String value of the previous key frame to its own Value using discrete interpolation Animates from the Thickness value of the previous key frame to its own Value using discrete interpolation Animates from the Vector3D value of the previous key frame to its own Value using discrete interpolation Animates from the Vector value of the previous key frame to its own Value using discrete interpolation

48

Using Graphics, Animation, and Multimedia in WPF

Table 1.26: Classes of System.Windows.Media.Animation namespace

Class
DoubleAnimation DoubleAnimationBase DoubleAnimationUsingKeyFrames DoubleAnimationUsingPath DoubleKeyFrame DoubleKeyFrameCollection KeySpline ParallelTimeline PauseStoryboard PointAnimation RectAnimation RemoveStoryboard RepeatBehaviorConverter ResumeStoryboard SeekStoryboard SetStoryboardSpeedRatio SingleAnimation SizeAnimation SkipStoryboardToFill StopStoryboard Storyboard ThicknessAnimation Timeline TimelineCollection TimelineGroup

Description
Animates the value of a Double property between two target values using linear interpolation over a specified Duration Animates a Double value Animates the value of a Double property along a set of KeyFrames Animates the value of a Double property between two or more target values using a PathGeometry to specify those values Defines an animation segment with its own target value and interpolation method for a DoubleAnimationUsingKeyFrames Represents a collection of DoubleKeyFrame objects Used by a spline key frame to define animation progress Defines a segment of time that may contain child Timeline objects Pauses a Storyboard Animates the value of a Point property between two target values using linear interpolation over a specified Duration Animates the value of a Rect property between two target values using linear interpolation Removes a Storyboard Converts instances of RepeatBehavior to and from other data types Resumes a paused Storyboard Provides functionality for seeking a specified time within the active period of a Storyboard Changes the speed of a Storyboard Animates the value of a Single property between two target values using linear interpolation over a specified Duration Animates the value of a Size property between two target values using linear interpolation over a specified Duration Advances a Storyboard to the end of its fill period Stops a Storyboard Provides object and property targeting information for its child animations Animates the value of a Thickness property between two target values using linear interpolation over a specified Duration Defines a segment of time Represents a collection of Timeline objects Represents a Timeline that may contain a collection of child Timeline objects

Essentials of Animation
In the preceding section, you learned about the different types of animation available in WPF and the different animation classes. In order to create the animation in WPF application, there are some essentials of animation that you should keep in mind. These essential include the Timeline class, the Storyboard class, the EventTrigger, and the KeyFrames. We will discuss these essentials next.

Animation Timeline
A timeline represents a stretch of time. It usually describes one or more events that happen during that stretch of time. Timelines of all kinds have a start time and duration. It provides the properties that enable you to specify the length of the segment, when it should start, how many times it should repeat, and how fast the time

49

Chapter 1

progresses in the segment. The timeline in animation is represented by the Timeline class. There are different types of specialized timelines are: AnimationTimeline classGenerates output values based on the timimg progress. It defines a segment of time over which the output value are produced. The values are used to animate the target property. MediaTimeline classA Timeline object which provides control over media timing in the same way that animation timeline objects control animations. For example, you can specify the Duration and BeginTime properties to specify when the media begins and how long it plays. ParallelTimeline classRepresents a segment of time that contains other child Timeline objects. These child elements are active according to their respective BeginTime properties. You can also make the child elements run in parallel with each other. The ParallelTimeline has its own BeginTime property, and so all child timeline BeginTime values are relative to the parent ParallelTimeline value for BeginTime. StoryboardA special type of ParallelTimeline that provides object and property targeting information for the timelines it contains. A Storyboard can contain any type of Timeline, including other container Timelines and animation. The noteworthy properties of the Timeline class are listed in Table 1.27: Table 1.27: Properties of Timeline class

Property
AccelerationRatio AutoReverse BeginTime CanFreeze DecelerationRatio DependencyObjectType Dispatcher Duration FillBehavior HasAnimatedProperties IsFrozen IsSealed Name RepeatBehavior SpeedRatio DesiredFrameRate

Description
Gets or sets a value specifying the percentage of the timelines Duration spent accelerating the passage of time from zero to its maximum rate Gets or sets a value that indicates whether the timeline plays in reverse after it completes a forward iteration Gets or sets the time at which the Timeline should begin Retrieves a value that indicates whether the object can be made unmodifiable Gets or sets a value specifying the percentage of the timelines Duration spent decelerating the passage of time from its maximum rate to zero Retrieves the DependencyObjectType that wraps the CLR type of Timeline class Retrieves the Dispatcher the Timeline class DispatcherObject is associated with Gets or sets the length of time for which the timeline plays, not counting repetitions Gets or sets a value that specifies how the Timeline behaves after it reaches at the end of its active period Retrieves a value that indicates whether one or more AnimationClock objects is associated with any of this objects dependency properties Retrieves a value that indicates whether the object is currently modifiable Retrieves a value that declares whether the Timeline class is currently read-only Gets or sets the name of the Timeline Gets or sets the repeating behavior of the timeline Gets or sets the rate, relative to its parent, at which time progresses for the Timeline Gets or sets the desired frame rate for the timeline and its child timelines

The noteworthy methods of the Timeline class are listed in Table 1.28: Table 1.28: Methods of Timeline class

Method
Clone CloneCurrentValue CreateClock

Description
Creates a modifiable clone of the Timeline, making copies of the object values Creates a modifiable clone of the Timeline object, making copies of the object current values Creates a Clock from the Timeline

50

Using Graphics, Animation, and Multimedia in WPF

Table 1.28: Methods of Timeline class

Method
GetDesiredFrameRate SetDesiredFrameRate

Description
Retrieves the desired frame rate of the specified Timeline Sets the desired frame rate of the specified Timeline

Animation Storyboard
A Storyboard is an enhanced Timeline. You can use a Storyboard to group multiple animations, and it has the capabilities to control the playback of the animation, such as pausing it, stopping it, and also changing its position. The most basic feature provided by the Storyboard class is its ability to point to a specific property and a specific element using the TargetName and TargetProperty property. Thus, you can say that the Storyboard bridges the gap between your animation and the property you want to animate. A controllable Storyboard can pause, resume, stop, seek, and also be removed in the animation. To make a Storyboard controllable in XAML code, you specify the Name property of the BeginStoryboard object that creates it. You can also make a Storyboard controllable in code, by using the appropriate overload of the Storyboard Begin method and specify True to make it controllable. You can add a Storyboard, by adding the following code in your application:
<Storyboard> <!-- Children --> </Storyboard>

The inheritance hierarchy of the Storyboard is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.Animation.Timeline System.Windows.Media.Animation.TimelineGroup System.Windows.Media.Animation.ParallelTimeline System.Windows.Media.Animation.Storyboard

The properties of the Storyboard class is same as the Timeline class. The noteworthy property of the Storyboard class which is different from the Timeline class is listed in Table 1.29: Table 1.29: Property of Storyboard Class

Property
SlipBehavior

Description
Gets or sets a value that specifies how this timeline will behave when one or more of its Timeline children slips

The noteworthy methods of the Storyboard class are listed in Table 1.30: Table 1.30: Methods of Storyboard Class

Method
Begin Clone GetCurrentGlobalSpeed GetCurrentIteration GetCurrentProgress GetCurrentState GetCurrentTime GetIsPaused Pause Resume

Description
Initiates the set of animations associated with the Storyboard Creates a modifiable clone of the Storyboard Retrieves the CurrentGlobalSpeed of the clock that was created for the Storyboard Retrieves the CurrentIteration of the Clock that was created for the Storyboard Retrieves the CurrentProgress of the Clock that was created for the Storyboard Retrieves the CurrentState of the Clock that was created for the Storyboard Retrieves the CurrentTime of the Clock that was created for the Storyboard Retrieves a value that indicates whether the Clock that was created for the Storyboard is paused Pauses the clock that was created for the Storyboard Resumes the animation clock, or runtime-state, associated with the Storyboard instance

51

Chapter 1

Table 1.30: Methods of Storyboard Class

Method
Seek SeekAlignedToLastTick SetSpeedRatio Stop

Description
Seeks the Storyboard to a new position when the next clock tick occurs Seeks the Storyboard to a new position immediately Sets the interactive speed ratio for the Clock that was created for the Storyboard Halts the Clock that was created for the Storyboard

If you are using code to add a Storyboard to the application, you must create a NameScope for the FrameworkElement and register the names of the objects to animate with that FrameworkElement. To enable the targeting of the FrameworkElement in XAML, you set its Name property. In the code-behind file of your application, you need to use the RegisterName method to register the element name with the element for which you have created a NameScope. You can interactively control a Storyboard after it has started. Table 1.31 lists a list of Storyboard actions that you use with event triggers to control a Storyboard: Table 1.31: Controllable Storyboard Actions

Action
BeginStoryboard PauseStoryboard ResumeStoryboard SetStoryboardSpeedRatio SkipStoryboardToFill StopStoryboard RemoveStotyboard

Effect
Starts the Storyboard Pauses the Storyboard Resumes a paused Storyboard Changes the Storyboard speed Advances the Storyboard to the end of its fill period Stops the Storyboard Removes the Storyboard

Event Triggers and Animation


Using an EventTrigger is the most common way to attach an animation. When you are creating an EventTrigger, you need to indicate the routed event that starts the trigger and the action that are performed by the trigger. To start an animation in XAML, you need to use a Storyboard. To start a Storyboard in XAML, you use the BeginStoryboard action and an EventTrigger. The EventTrigger begins the BeginStoryboard action when the event that is specified by its RoutedEvent property occurs. The Storyboard.TargetProperty property identifies the property you want to change. For example, you can change the Width of the Button control with EventTrigger. The basic purpose of the EventTrigger is to launch an action. All the actions are represented by the classes that derive from the System.Windows.TriggerAction namespace. The EventTrigger has no concept of termination of state, so the action will not be undone once the condition that raised the event is no longer true.

Key Frames
You can attach different KeyFrame with each animation and the subsequent interpolation method. The interpolation method describes the transition of animation between values over the duration of the animation. You can define the interpolation method for each KeyFrame segment by selecting the KeyFrame type with your animation. There are three different types of interpolation method, such as linear, discrete, and splined, described as follows: You can choose linear interpolation when you want your animation to progress at a constant rate of the segment duration. You can choose discrete interpolation when you want your animation to jump from one value to the next without interpolation.

52

Using Graphics, Animation, and Multimedia in WPF

You can use splined interpolation when you want your animation to achieve more realistic timing effect. You can use splined interpolation with spline KeyFrame. You need to specify KeySpline with the spline KeyFrame to implement splined interpolation. You can also use KeyFrame with different interpolation types in a single KeyFrame animation. When you apply two KeyFrame animations with different interpolations, the interpolation method of the second KeyFrame is used to create the transition from the first value to the second. The KeyFrame animation also uses the Duration property. You also need to specify what portion of the duration is given to each KeyFrame by specifying the KeyTime for each KeyFrame. You can set the value of KeyTime to any of the following values: UniformDivides the allotted time of the animation evenly between KeyFrame. PacedCreates a timing behavior resulting in an animation that interpolates at a constant rate. This means that the available time is allocated according to the length of each KeyFrame to determine the duration of each frame. TimeSpanSpecifies the value of KeyTime. The value of the TimeSpan should be greater than or equal to zero and less than or equal to the duration of animation. PercentagevEnds the KeyFrame at some percentage of the animation Duration. The value of Percentage must be greater than or equal to zero and less than or equal to 100 percent.

Using Animation in WPF 3.5


Animation in WPF includes the different types of animation, which are represented by the Timeline class, the Storyboard class, Trigger, and KeyFrame. Animation can make an attractive, impressive and useful user interface. You can attach animations to the 2-D graphics and the 3-D graphics in WPF. You can create normal shapes and add animations to it. Lets now learn how to implement an animation in a WPF application.

Creating Animations Using Storyboards


Storyboards are a useful tool to create animation in WPF. They are basic ingredient in WPF. The Storyboard object enables you to combine timelines that affect a variety of objects into a single timeline tree, and makes it easy for you to combine and control complex timing behavior. You can use Storyboard with triggers to create animation in WPF. Normally, Storyboard is used with EventTriggers. However, you can use them with other types of triggers to create animations in WPF.

Using Event Triggers


EventTrigger starts a set of actions based on the occurrence of an event. For example, the action can be the click of the Button and the event can be starting point of an animation on the click of the Button. Lets create an animation using EventTrigger. For this, create a WPF application named EventTrigger (available on the CD-ROM) and add the following code given in Listing 1.22 to Window1.xaml. This listing shows how to control the Storyboard after it starts: Listing 1.22: Creating Event Trigger
<Window x:Class="EventTrigger.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="400"> <DockPanel> <Grid DockPanel.Dock="Top"> <Canvas Background="CadetBlue"> <Ellipse Canvas.Left="86" Canvas.Top="41" Height="90" Name="ellipse1" Stroke="Black" Width="96" Fill="AntiqueWhite" /> <Ellipse Canvas.Left="105" Canvas.Top="62" Height="13" Name="ellipse2" Stroke="Black" Width="14" Fill="Cornsilk" /> <Ellipse Canvas.Left="144" Canvas.Top="62" Height="13" Name="ellipse3" Stroke="Black" Width="14" Fill="Cornsilk" /> <Ellipse Canvas.Left="112" Canvas.Top="68" Height="5" Name="ellipse4" Stroke="Black" Width="5" Fill="Black" /> <Ellipse Canvas.Left="151" Canvas.Top="67" Height="5" Name="ellipse5" Stroke="Black" Width="5" Fill="Black" />

53

Chapter 1
<Rectangle Canvas.Left="105" Canvas.Top="129" Height="111" Name="rectangle1" Stroke="Black" Width="59" Fill="HotPink" /> <Ellipse Canvas.Left="127" Canvas.Top="128" Height="10" Name="ellipse6" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="148" Height="10" Name="ellipse7" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="168" Height="10" Name="ellipse8" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="188" Height="10" Name="ellipse9" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="208" Height="10" Name="ellipse10" Stroke="Black" Width="9" Fill="Blue" /> <Ellipse Canvas.Left="127" Canvas.Top="228" Height="10" Name="ellipse11" Stroke="Black" Width="9" Fill="Blue" /> <Line X1="12" X2="400" Y1="145" Y2="115" Stroke="Black" StrokeThickness="5" Height="158" Canvas.Left="131" Canvas.Top="114" Width="42" /> <Path Name="path1" Stroke="Black" Data="M 60,113 Q 90,146 111,111" StrokeThickness="5" Height="134" Canvas.Left="48" Canvas.Top="-14" Width="145" /> <Line X1="124" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="40" Canvas.Top="-7" Width="147" /> <Line X1="145" X2="600" Y1="149" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="37" Canvas.Top="8" Width="178" /> <Line X1="124" X2="170" Y1="145" Y2="16" Stroke="Black" StrokeThickness="5" Height="115" Canvas.Left="-42" Canvas.Top="65" Width="147" /> <Line X1="115" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-50" Canvas.Top="11" Width="147" /> <Polygon Points="10,110 60,10 110,110" Fill="Blue" Height="55" Canvas.Left="72" Canvas.Top="-7" Width="132" /> <Line X1="11" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="163" Canvas.Left="83" Canvas.Top="110" Width="41" /> <Line X1="145" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-23" Canvas.Top="94" Width="151" /> <Line X1="145" X2="145" Y1="145" Y2="166" Stroke="Black" StrokeThickness="5" Height="168" Canvas.Left="-1" Canvas.Top="94" Width="147" /> <Line X1="11" X2="10" Y1="145" Y2="115" Stroke="Black" StrokeThickness="5" Height="158" Canvas.Left="121" Canvas.Top="-52" Width="42" /> <Polyline Name="Base" Points="10,110 6,10 110,110" Stroke="Black" StrokeThickness="4" Height="52" Canvas.Left="209" Canvas.Top="210" Width="50"/> <Ellipse Canvas.Left="172" Canvas.Top="118" Height="100" Name="Ball" Stroke="Black" Width="87"> <Ellipse.BitmapEffect> <OuterGlowBitmapEffect GlowColor="DarkViolet" /> </Ellipse.BitmapEffect> </Ellipse> <Button Canvas.Left="235" Canvas.Top="12" Height="23" Name="StartAnimation" Width="75">Start</Button> <Button Canvas.Left="235" Canvas.Top="45" Height="23" Name="StopAnimation" Width="75">Stop</Button> </Canvas> </Grid> <DockPanel.Triggers> <EventTrigger RoutedEvent="Button.Click" SourceName="StartAnimation"> <BeginStoryboard Name="StartMoveBall"> <Storyboard Name="MoveBall"> <DoubleAnimation RepeatBehavior="Forever" AccelerationRatio="0.4" DecelerationRatio="0.4" AutoReverse="True" By="100" Duration="0:0:3" Storyboard.TargetName="Ball" Storyboard.TargetProperty="(Canvas.Left)"/> </Storyboard> </BeginStoryboard>

54

Using Graphics, Animation, and Multimedia in WPF


</EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="StartAnimation"> <BeginStoryboard Name="StartTable"> <Storyboard Name="Table"> <DoubleAnimation RepeatBehavior="Forever" AccelerationRatio="0.4" DecelerationRatio="0.4" AutoReverse="True" By="100" Duration="0:0:3" Storyboard.TargetName="Base" Storyboard.TargetProperty="(Canvas.Left)"/> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimation"> <StopStoryboard BeginStoryboardName="StartMoveBall"/> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="StopAnimation"> <StopStoryboard BeginStoryboardName="StartTable"/> </EventTrigger> </DockPanel.Triggers> </DockPanel> </Window>

In this code, we have used the figure created in Listing 1.1. We have added two buttons to the application and added Event Trigger to the Button. On the click of the Start Button the animation starts and the circle along with the figure starts moving. The AutoReverse property is set to True in the application. So, when the circle reaches at the end of the Window, it moves back again. The animation continues until you click the Stop Button. Once you click the Stop Button, the figure stops moving and comes back to its original place. When you run the code by pressing F5, you get the output as shown in Figure 1.21:

Figure 1.21: Using Event Trigger

Using Triggers
The most common way to start an animation in WPF is to use EventTrigger. However, you can use the different types of trigger available in WPF to create an animation. For example, you can use PropertyTrigger to create animations in WPF. Lets create animations in WPF using trigger. For this, create a WPF application named UsingTrigger (available on the CD-ROM) and add the following code given in Listing 1.23 to Window1.xaml: Listing 1.23: Creating Trigger
<Window x:Class="UsingTrigger.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Window.Resources> <Style x:Key="PropertyTrigger" TargetType="{x:Type Button}"> <Setter Property="Opacity" Value="0.5"> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard>

55

Chapter 1
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:1"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:1"/> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> </Style.Triggers> </Style> </Window.Resources> <StackPanel> <Button Style="{StaticResource PropertyTrigger}"> Move the Mouse over me to Start Animation </Button> </StackPanel> </Window>

In this code, a Button is added to Window on which the animation is applied with the help of trigger. The Button is initially blurred with the help of the Opacity property. When you run the application, by pressing F5, a blurred Button on the Window is visible to you. When you move the mouse over the Button, it becomes visible, and when you remove the mouse, the Button again becomes blurred. You can see the output when the mouse is over the Button in Figure 1.22:

Figure 1.22: Using Trigger

Changing the Speed of Animations


In WPF, you can change the speed of animation by using the AccelerationRatio and DecelerationRatio property of the Timeline class. The AccelerationRatio property specifies the percentage of the timeline Duration accelerating the passage of time from zero to its maximum. Similarly, the DecelerationRatio property specifies the percentage of timeline Duration decelerating the passage of time from its maximum rate to zero. Lets create an application in which we are changing the speed of animation. For this, create a WPF application named ChangingSpeed (available on the CD-ROM) and add the following code given in Listing 1.24 to Window1.xaml: Listing 1.24: Using the AccelerationRatio and DecelerationRatio property
<Window x:Class="ChangingSpeed.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="400"> <Grid>

56

Using Graphics, Animation, and Multimedia in WPF


<Ellipse Height="30" Margin="9,29,0,0" Name="ellipse1" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="105" Fill="Red"/> <Ellipse Height="30" Margin="9,60,0,0" Name="ellipse2" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="105" Fill="Yellow"/> <Ellipse Height="30" Margin="9,92,0,0" Name="ellipse3" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="105" Fill="Green"/> <Ellipse Margin="9,121,0,111" Name="ellipse4" Stroke="Black" HorizontalAlignment="Left" Width="105" Fill="Red"/> <Button HorizontalAlignment="Left" Margin="9,0,0,15" Name="button1" Width="95" Height="23" VerticalAlignment="Bottom"> StartAnimation <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="(Ellipse.Width)" Duration="0:0:10" From="105" To="250"/> <DoubleAnimation Storyboard.TargetName="ellipse2" Storyboard.TargetProperty="(Ellipse.Width)" Duration="0:0:10" AccelerationRatio="0.4" From="105" To="250"/> <DoubleAnimation Storyboard.TargetName="ellipse3" Storyboard.TargetProperty="(Ellipse.Width)" Duration="0:0:10" DecelerationRatio="0.6" From="105" To="250"/> <DoubleAnimation Storyboard.TargetName="ellipse4" Storyboard.TargetProperty="(Ellipse.Width)" Duration="0:0:10" AccelerationRatio="0.4" DecelerationRatio="0.6" From="105" To="250"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid> </Window>

In this code, there are four ellipse added to the Window. The animation is applied to all of them. The EventTrigger is added on the click of the Button. When you click the Button, the ellipse starts increasing. The speed of increasing the width of the ellipse is different. The first ellipse increases with the speed specified in the Duration property. In the second ellipse along with the Duration property, AccelerationRatio is also specified, which specifies the increasing speed of the ellipse. In the third ellipse, the Duration and the DecelerationRatio property are specified. In the third ellipse, along with the Duration property, the AccelerationRatio and the DecelerationRatio properties are also specified. When you run the application, by pressing F5, the four ellipses along with the Button, on the Window is visible to you. When you click the StartAnimation button, the ellipse starts growing according to the speed attached to the ellipse. You can see the output after clicking the Button in Figure 1.23:

Figure 1.23: Changing the Speed of Animation

57

Chapter 1

Reversing the Animation


In WPF, you can reverse an animation by specifying the AutoReverse property of timeline. The animation can reverse itself after completing a forward iteration. You can reverse the animation by setting the AutoReverse property of the animation to True. Lets create an application in which you can reverse the animation. For this, create a WPF application named ReversingAnimation (available on the CD-ROM) and add the following code given in Listing 1.25 to Window1.xaml: Listing 1.25: Using the AutoReverse property
<Window x:Class="ReversingAnimation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <StackPanel> <Rectangle Height="43" Name="rectangle1" Stroke="Black" Width="88" Fill="Red"/> <Rectangle Height="43" Name="rectangle2" Stroke="Black" Width="88" Fill="Yellow"/> <Button Height="23" Name="button1" Width="166"> StartAnimation <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Width" Duration="0:0:2" From="88" To="250" AutoReverse="False"/> <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="Width" Duration="0:0:2" From="88" To="250" AutoReverse="True"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </StackPanel> </Window>

In this code, two rectangles and a button is added to the Window. The animation is attached on the click event of the Button. When you click the Button, the rectangle starts increasing in Width. The first rectangle stops after increasing as the AutoReverse property is set to False. The second rectangle first increases and then moves back to its original size as the AutoReverse property is set to True. You can see the output after the animation ends in Figure 1.24:

Figure 1.24: Reversing Animation

Controlling the Behavior of Animation


You can control the behavior of the animation in WPF by specifying the RepeatBehavior property of the Timeline class. The RepeatBehavior property controls the number of times an animation repeats itself. The default value of the RepeatBehavior property is set to 1.0, which implies that the animation plays one time and does not repeat itself. You can specify the number of times for repeating the animation or you can even set

58

Using Graphics, Animation, and Multimedia in WPF

the RepeatBehavior property to Forever to repeat the animation indefinitely. Lets create an application to control the behavior of the animation. For this, create a WPF application named ControllingAnimation (available on the CD-ROM) and add the following code given in Listing 1.26 to Window1.xaml: Listing 1.26: Using the RepeatBehavior property
<Window x:Class="ControllingAnimation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <StackPanel> <Rectangle Height="32" Name="rectangle1" Stroke="Black" Width="90" Fill="Pink"/> <Rectangle Height="32" Name="rectangle2" Stroke="Black" Width="90" Fill="Pink"/> <Rectangle Height="32" Name="rectangle3" Stroke="Black" Width="90" Fill="Pink"/> <Rectangle Height="32" Name="rectangle4" Stroke="Black" Width="90" Fill="Pink"/> <Button Height="23" Name="button1" Width="155">Start</Button> <StackPanel.Triggers> <EventTrigger SourceName="button1" RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Width" From="90" To="200" RepeatBehavior="Forever" Duration="0:0:2"/> <DoubleAnimation Storyboard.TargetName="rectangle2" Storyboard.TargetProperty="Width" From="90" To="200" RepeatBehavior="0:0:2" Duration="0:0:2"/> <DoubleAnimation Storyboard.TargetName="rectangle3" Storyboard.TargetProperty="Width" From="90" To="200" RepeatBehavior="5x" Duration="0:0:2"/> <DoubleAnimation Storyboard.TargetName="rectangle4" Storyboard.TargetProperty="Width" From="90" To="200" Duration="0:0:2"/> </Storyboard> </BeginStoryboard> </EventTrigger> </StackPanel.Triggers> </StackPanel> </Window>

In the code, there are four rectangles and a button added to the Window. The RepeatBehaviour property is attached to all the four rectangles. When you run the code by pressing F5, and click the Start Button, the animation starts and the rectangle starts increasing. You will notice that the first rectangle goes on increasing indefinitely, as the RepeatBehavior property attached with rectangle1 is set to Forever. The second rectangle stops increasing after 2 seconds, as the RepeatBehavior property attached with rectangle2 is set to 0:0:2. The third rectangle stops increasing after five instances, as the RepeatBehavior property attached with rectangle3 is set to 5x. The fourth rectangle increases only once and then stops, as there is no RepeatBehavior property attached with rectangle4. You can see the output after the animation starts in Figure 1.25:

Figure 1.25: Controlling Animation

59

Chapter 1

Specifying the Behavior of Animation after Ending


The default behavior of the animation in WPF is to come back to its original size and location at the end. You can change the default behavior using the FillBehavior property. The FillBehavior property of the Timeline specifies the nature of animation after it has stopped. The different values of the FillBehavior property are Stop and HoldEnd. The Stop value of the FillBehavior causes the animation to revert back to its normal state. The HoldEnd value of the FillBehavior causes the animation to remain at the end value when the animation ends. Lets create an animation in which you can specify the behavior of animation. For this, create a WPF application named BehaviorofAnimation (available on the CD-ROM) and add the following code given in Listing 1.27 to Window1.xaml: Listing 1.27: Using the FillBehavior property
<Window x:Class="BehaviorofAnimation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="450"> <Grid> <Ellipse Height="41" HorizontalAlignment="Left" Margin="10,10,0,0" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="100" Fill="CadetBlue"/> <Rectangle HorizontalAlignment="Left" Margin="10,81,0,0" Name="ellipse1" Stroke="Black" Width="100" Fill="Aquamarine" Height="31" VerticalAlignment="Top" /> <Button Height="23" HorizontalAlignment="Left" Margin="22,0,0,79" Name="button1" VerticalAlignment="Bottom" Width="75"> Start <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Width" From="100" To="400" Duration="0:0:2" FillBehavior="HoldEnd"/> <DoubleAnimation Storyboard.TargetName="ellipse1" Storyboard.TargetProperty="Width" From="100" To="400" Duration="0:0:2" FillBehavior="Stop"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid> </Window>

In this code, there is an ellipse, rectangle, and a button. The animation is attached on the click of the Button. When you run the application by pressing F5, and click the Start button, the ellipse and the rectangle starts increasing. After the animation ends, the ellipse stays at the end, while the rectangle comes back to its original state. This is because, the FillBehavior property attached with the ellipse is set to Stop and the rectangle is set to HoldEnd. You can see the output after the animation ends in Figure 1.26:

Figure 1.26: Behavior of Animation after Ending

60

Using Graphics, Animation, and Multimedia in WPF

Running Multiple Animations Simultaneously


In WPF, you can run multiple animations simultaneously by using the ParallelTimeline class. The animation starts according to the specified BeginTime property. The child timelines also run in parallel to each other. You can nest multiple Storyboards inside a ParallelTimeline element within a parent Storyboard. This way, all the Storyboard and their animations will run in parallel to each other. Lets create an animation that runs multiple animations concurrently. For this, create a WPF application named MultipleAnimations (available on the CD-ROM) and add the following code given in Listing 1.28 to Window1.xaml: Listing 1.28: Using the ParallelTimeline class
<Window x:Class="MultipleAnimations.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Grid.Triggers> <EventTrigger RoutedEvent="Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ParallelTimeline> <Storyboard Storyboard.TargetName="button1" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"> <ColorAnimation From="Plum" To="Green" By="Blue" Duration="0:0:5"/> </Storyboard> <Storyboard Storyboard.TargetName="button1" Storyboard.TargetProperty="(RenderTransform).(RotateTransform.Angle)"> <DoubleAnimation From="0" To="180" Duration="0:0:5" BeginTime="0:0:2" FillBehavior="HoldEnd"/> </Storyboard> </ParallelTimeline> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Grid.Triggers> <Button Width="150" Height="35" Name="button1" Background="Plum"> Click me <Button.RenderTransform> <RotateTransform Angle="0" CenterX="105" CenterY="30"> </RotateTransform> </Button.RenderTransform> </Button> </Grid> </Window>

In this code, a Button is added to the application. There are multiple animations applied to the Button. When you run the code by pressing F5, and click the Button, the Button starts changing color. After some time, the Button starts rotating. This type of animation is applied using the ParllelTimeline class. The Button starts changing color after clicking as there is no specified BeginTime property with the color changing event. The Button starts rotating as there is the specified BeginTime property and so the Button starts rotating after the specified time. You can see the output after clicking the Click me button in Figure 1.27:

61

Chapter 1

Figure 1.27: Running Multiple Animations

Controlling Storyboards Interactively


Storyboard in WPF is the container timeline that provides the object and its property information for its animations. To animate a property using Storyboard, you should create an animation for each property that you want to animate and also create a Storyboard to contain animations. As discussed earlier, a controllable storyboard can start, stop, pause, resume, seek, stop, and removed. You can control a storyboard either through XAML or the code.

In XAML
The common practice of controlling a Storyboard is through the XAML code. To start a Storyboard in XAML, you use the BeginStoryboard property and an Event Trigger. The BeginStoryboard property starts the Storyboard. An Event Trigger helps you to implement the animation started by the BeginStoryboard property. Lets create an application to control the Storyboard through the XAML code. For this, create a WPF application named Storyboard_XAML (available on the CD-ROM) and add the following code given in Listing 1.29 to Window1.xaml: Listing 1.29: XAML code
<Window x:Class="Storyboard_XAML.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="500"> <Grid> <Ellipse Height="57" Margin="10,26,0,0" Name="Circle" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70" Fill="Aqua"/> <Button HorizontalAlignment="Left" Margin="10,0,0,34" Name="Start" Width="75" Height="23" VerticalAlignment="Bottom">Start</Button> <Button Height="23" Margin="140,0,0,34" Name="Stop" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" >Stop</Button> <Button Margin="0,0,332,34" Name="Pause" HorizontalAlignment="Right" Width="75" Height="23" VerticalAlignment="Bottom">Pause</Button> <Button Height="23" Margin="210,0,193,34" Name="Resume" VerticalAlignment="Bottom">Resume</Button> <Button Height="23" HorizontalAlignment="Left" Margin="355,0,0,34" Name="SkipToFill" VerticalAlignment="Bottom" Width="75">SkipToFill</Button> <Button Height="23" HorizontalAlignment="Left" Margin="282,0,0,34" Name="Seek" VerticalAlignment="Bottom" Width="75">Seek</Button> <Grid.Triggers> <EventTrigger RoutedEvent="Button.Click" SourceName="Start"> <BeginStoryboard Name="BeginAnimation"> <Storyboard> <DoubleAnimation Storyboard.TargetName="Circle" Storyboard.TargetProperty="Width" Duration="0:0:3" From="70" To="400"/> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="Stop"> <StopStoryboard BeginStoryboardName="BeginAnimation"/>

62

Using Graphics, Animation, and Multimedia in WPF


</EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="Pause"> <PauseStoryboard BeginStoryboardName="BeginAnimation"/> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="Resume"> <ResumeStoryboard BeginStoryboardName="BeginAnimation"/> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFill"> <SkipStoryboardToFill BeginStoryboardName="BeginAnimation"/> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="Seek"> <SeekStoryboard BeginStoryboardName="BeginAnimation" Offset="0:0:1" Origin="BeginTime"/> </EventTrigger> </Grid.Triggers> </Grid> </Window>

In this code, there is an ellipse and six Buttons added to the application. Each Button performs a different function with respect to the Storyboard. When you run the application, by pressing F5, you will notice the behavior of each Button. The Start Button starts the animation and the Storyboard. The Pause Button pauses the Storyboard at wherever point it is specified. The Stop Button stops the Storyboard and brings the ellipse to the start point. The Resume Storyboard resumes the Storyboard from the point it had been paused. The Seek button starts increasing the width of the ellipse from the point specified in the Origin property. The SkipToFill button fills the area of the Storyboard by jumping to the last point. You can see the output in the Figure 1.28:

Figure 1.28: Controlling Storyboard in XAML

In Code
When you are controlling the Storyboard through code, you must create a NameScope class for a FrameworkElement class to register the names of the objects to animate with the FrameworkElement class. To start an animation in code, you should use the BeginStoryboard action with an EventTrigger. You can also use an event handler and the Begin method of the Storyboard. You can create the same effect as XAML through the code as well. Lets create an animation in which you can control the Storyboard though code. For this, create a WPF application named Storyboard_Code (available on the CD-ROM) and add the following code given in Listing 1.30 to Window1.xaml: Listing 1.30: Storyboard in Code
<Window x:Class="Storyboard_Code.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Width="100" Name="button1" Click="button1_Click" HorizontalAlignment="Left" Margin="0,27,0,0" Height="29" VerticalAlignment="Top">Click to grow</Button> </Grid> </Window>

63

Chapter 1

The code in Listing 1.30 is the XAML code, which is used to add a Button named button1 to the application. This Button will be animated in the code-behind file. Add the code given in Listing 1.31 to Window1.xaml.cs: Listing 1.31: Animating Button
using using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes; System.Windows.Media.Animation;

namespace Storyboard_Code { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); NameScope.SetNameScope(this, new NameScope()); this.RegisterName(button1.Name, button1); } private void button1_Click(object sender, RoutedEventArgs e) { DoubleAnimation myAnimation = new DoubleAnimation(); myAnimation.From = 100; myAnimation.To = 300; myAnimation.AutoReverse = true; myAnimation.RepeatBehavior = RepeatBehavior.Forever; myAnimation.Duration = new Duration(TimeSpan.FromSeconds(2)); Storyboard myStoryboard = new Storyboard(); myStoryboard.Children.Add(myAnimation); Storyboard.SetTargetName(myAnimation, button1.Name); Storyboard.SetTargetProperty(myAnimation, new PropertyPath(Button.WidthProperty)); myStoryboard.Begin(this); } } }

The preceding code adds a Storyboard to the Button. The Button is animated to grow as you click on it. When you run the code by pressing F5, a Button is added to the Window. As you click on the Button, it starts increasing. The output is shown in Figure 1.29:

64

Using Graphics, Animation, and Multimedia in WPF

Figure 1.29: Controlling Storyboard in code

Using DoubleAnimation to Transform Controls


DoubleAnimation animates the value of the Double property between two target values over a specified duration. The animation updates the value of property over a period of time. You can create simple animation such as moving a shape as well as advance animations such as enlarging a shape using DoubleAnimation. You can also use DoubleAnimation to transform controls. You can set the Storyboard.TargetProperty of the DoubleAnimation class to transform controls. Lets create an application to transfom controls. For this, create a WPF application name DoubleAnimation (available on the CD-ROM) and add the following code given in Listing 1.32 to Window1.xaml: Listing 1.32: Using DoubleAnimation to transform Controls
<Window x:Class="DoubleAnimation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="400" Width="400"> <Window.Resources> <Style x:Key="WindowStyle" /> <Style x:Key="WindowBackground" TargetType="{x:Type Window}"> <Style.Triggers> <EventTrigger RoutedEvent="Window.Loaded"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard RepeatBehavior="Forever"> <ColorAnimation From="LightBlue" To="LightPink" Storyboard.TargetProperty="Background.Color" Duration="0:0:10" Timeline.DesiredFrameRate="10" AutoReverse="True" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style> </Window.Resources> <Window.Style> <StaticResource ResourceKey="WindowBackground"/> </Window.Style> <StackPanel> <StackPanel HorizontalAlignment="Center" > <Button Height="42" Width="207">Click to Show Text <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ParallelTimeline>

65

Chapter 1
<DoubleAnimation Storyboard.TargetName="myBorder" Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="1" Duration="0:0:3" AutoReverse="False" /> <DoubleAnimation Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:3" AutoReverse="True" /> </ParallelTimeline> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Button.Triggers> </Button> <Border Width="300" Height="200" Name="myBorder" BorderBrush="Black" BorderThickness="5" Opacity="0.5" Style="{StaticResource WindowStyle}"> <Border.RenderTransform> <ScaleTransform ScaleX="0" ScaleY="1" CenterX="200" /> </Border.RenderTransform> <TextBlock Width="300" Height="300" TextWrapping="Wrap" FontSize="60" TextAlignment="Center"> <TextBlock.Foreground> <RadialGradientBrush GradientOrigin="0,0" Center="0.5,0.5" RadiusX="1" RadiusY="1"> <GradientStop Color="LightPink" Offset="0.25" /> <GradientStop Color="DeepPink" Offset="0.5" /> <GradientStop Color="Pink" Offset="1" /> </RadialGradientBrush> </TextBlock.Foreground> Hello WPF </TextBlock> </Border> </StackPanel> </StackPanel> </Window>

In this code, a Button is added to the Window. When you run the code, by pressing F5, and click the Click to Show Text button, a TextBlock appears on the Window with a scrolling effect. This effect is possible with the help of the transfomming effect of DoubleAnimation. After clicking the Button, the output of the code is shown in Figure 1.30:

Figure 1.30: Transformming Control using DoubleAnimation

Creating Local Animations


You have learned to create animations by using the Storyboard, either through XAML or through code. There can be instances when you can create animations without using a Storyboard. This type of animation is termed

66

Using Graphics, Animation, and Multimedia in WPF

as local animation. You can use the BeginAnimation method to apply local animation. The local animation cannot be created in the XAML code. You can create local animations in the code-behind file. You should add the System.Windows.Media.Animation namespace in your code file for creating local animation. Lets create animations which are locally created. For this, create a WPF application named LocalAnimation (available on the CD-ROM) and add the following code given in Listing 1.33 to Window1.xaml: Listing 1.33: Creating Local Animation
<Window x:Class="LocalAnimation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Height="23" HorizontalAlignment="Left" Margin="25,31,0,0" Name="Button1" VerticalAlignment="Top" Width="91" Click="button1_Click">One Rotation</Button> <Rectangle Margin="131,0,0,50" Name="rectangle1" Stroke="Black" Fill="Aqua" Height="66" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="7" /> <Button Height="23" HorizontalAlignment="Right" Margin="0,31,23,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click">Forever</Button> <Ellipse Margin="66,82,86,50" Name="ellipse1" Stroke="Black" /> </Grid> </Window>

This is the XAML code which is used to add two buttons, an ellipse, and a rectangle to create a clock type figure. To create a local animation, you need to add the code given in Listing 1.34 to Window1.xaml.cs: Listing 1.34: Local Animation
using using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes; System.Windows.Media.Animation;

namespace LocalAnimation { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { DoubleAnimation rect = new DoubleAnimation(); rect.From = 0; rect.To = 360; rect.Duration = new Duration(TimeSpan.FromSeconds(7)); RotateTransform rotate = new RotateTransform(); rectangle1.RenderTransform = rotate; rotate.BeginAnimation(RotateTransform.AngleProperty, rect); } private void button2_Click(object sender, RoutedEventArgs e)

67

Chapter 1
{ DoubleAnimation rect = new DoubleAnimation(); rect.From = 0; rect.To = 360; rect.Duration = new Duration(TimeSpan.FromSeconds(7)); rect.RepeatBehavior = RepeatBehavior.Forever; RotateTransform rotate = new RotateTransform(); rectangle1.RenderTransform = rotate; rotate.BeginAnimation(RotateTransform.AngleProperty, rect); } } }

The preceding code adds the animation effect on the click event of the Button. When you click button1, the rectangle which appears as the hand of the clock, rotates and completes one rotation around the ellipse. There is only one rotation as there is no RepeatBehavior property attached to the button1. When you click button2, the rectangle rotates around the ellipse. The rotation keeps on repeating itself, as the RepeatBehavior property attached to button2 is set to Forever. The output of the code is shown in Figure 1.31:

Figure 1.31: Local Animation

Using Keyframe Animation


The KeyFrame animation enables you to animate an object using more than two target values. You need to specify the Duration property when using the KeyFrame animation. You can create different types of animation using KeyFrame. There are different types of animation available for the different types of object which you have already learned in Table 1.25 of this chapter.

Animating Rectangles
Rectangle is a type of object. The LinearDoubleKeyFrame class is used to animate rectangles. The LinearDoubleKeyFrame class animates the Double value of the previous key frame to its own Value using linear interpolation. A KeyFrame has a target Value and a KeyTime. The KeyTime specifies the time at which the KeyFrame value should be reached. The KeyFrame starts when the previous KeyFrame ends. Lets create an animation of rectangle using the LinearKeyFrame class. For this, create a WPF application named AnimatingRectangle (available on the CD) and add the following code given in Listing 1.35 to Window1.xaml: Listing 1.35: Using LinearDoubleKeyFrame Class
<Window x:Class="AnimatingRectangle.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="400" Width="400"> <Grid> <Rectangle Margin="108,0,130,0" Name="rectangle1" Stroke="Black" Height="40" Width="40" VerticalAlignment="Top" Fill="Red"> <Rectangle.RenderTransform>

68

Using Graphics, Animation, and Multimedia in WPF


<TranslateTransform x:Name="KeyFrameAnimation" X="50" Y="50"/> </Rectangle.RenderTransform> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="KeyFrameAnimation" Storyboard.TargetProperty="Y" Duration="0:0:20"> <LinearDoubleKeyFrame Value="10" KeyTime="0:0:0"/> <LinearDoubleKeyFrame Value="30" KeyTime="0:0:2"/> <LinearDoubleKeyFrame Value="100" KeyTime="0:0:7"/> <LinearDoubleKeyFrame Value="250" KeyTime="0:0:20"/> <LinearDoubleKeyFrame Value="10" KeyTime="0:0:10"/> <LinearDoubleKeyFrame Value="100" KeyTime="0:0:20"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> </Grid> </Window>

In this code, a rectangle is added to the Window. When you run the code by pressing F5, you get a red color rectangle on the Window. When you click the rectangle, the rectangle starts moving. The speed of the movement of the rectangle is determined by the KeyTime property. The Value property specifies the position of the rectangle on the Window. The output of the code is shown in Figure 1.32:

Figure 1.32: Animating Rectangle

Animating Strings
You can animate the string, which means the text, by using KeyFrame. The string is animated using the DiscreteStringKeyFrame class. This class animates the string value of the previous key frame to its own Value using discrete interpolation. Lets create an animation of string using the DiscreteStringKeyFrame class. For this, create a WPF application named AnimatingStrings (available on the CD-ROM) and add the following code given in Listing 1.36 to Window1.xaml:

69

Chapter 1

Listing 1.36: Using the DiscreteStringKeyFrame Class


<Window x:Class="AnimatingStrings.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Margin="17,97,18,82" Name="button1" FontSize="17"> Example <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <StringAnimationUsingKeyFrames Storyboard.TargetName="button1" Storyboard.TargetProperty="(Button.Content)" Duration="0:0:10" FillBehavior="Stop"> <DiscreteStringKeyFrame Value="" KeyTime="0:0:1"/> <DiscreteStringKeyFrame Value="Key" KeyTime="0:0:2"/> <DiscreteStringKeyFrame Value="KeyFrame" KeyTime="0:0:3"/> <DiscreteStringKeyFrame Value="KeyFrame Ani" KeyTime="0:0:4"/> <DiscreteStringKeyFrame Value="KeyFrame Animat" KeyTime="0:0:5"/> <DiscreteStringKeyFrame Value="KeyFrame Animation" KeyTime="0:0:6"/> <DiscreteStringKeyFrame Value="Your" KeyTime="0:0:7"/> <DiscreteStringKeyFrame Value="Your Text" KeyTime="0:0:8"/> <DiscreteStringKeyFrame Value="Your Text Changes" KeyTime="0:0:9"/> </StringAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> </Grid> </Window>

In this code, a Button with some text is added on the Window. When you run the code by pressing F5, and click the Button, the text disappears from the Button and a new text appears one by one. The text which appears one by one is specified by using the Value property. The difference between the span of time of the text appearing on the Button is specified using the KeyTime property. After clicking the Button, you can see the output in Figure 1.33:

Figure 1.33: Animating String

Controlling the Timing of Keyframe Animations


You can control the timing of the KeyFrame within the KeyFrame animation. The KeyFrame animation has the Duration property. You can allot time to each part of the KeyFrame by specifying the KeyTime for each key

70

Using Graphics, Animation, and Multimedia in WPF

frame in the animation. You can specify the KeyTime as a TimeSpan property, as a percentage, or Uniform property or Paced property. Lets create an animation to control the timing of the KeyFrame animation. For this, create a WPF application named ControllingTiming (available on the CD-ROM) and add the following code given in Listing 1.37 to Window1.xaml: Listing 1.37: Using the KeyTime Property
<Window x:Class="ControllingTiming.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="400" Width="400"> <Grid> <Rectangle Margin="17,14,0,0" Stroke="Black" Height="116" VerticalAlignment="Top" Fill="Orange" HorizontalAlignment="Left" Width="125"> <Rectangle.RenderTransform> <TranslateTransform x:Name="RectangleTranform1" X="0" Y="0"/> </Rectangle.RenderTransform> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RectangleTranform1" Storyboard.TargetProperty="X" Duration="0:0:10" RepeatBehavior="Forever"> <LinearDoubleKeyFrame Value="350" KeyTime="0:0:10"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> <Rectangle Height="54" Margin="17,15,0,0" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="62" Fill="Red"> <Rectangle.RenderTransform> <TranslateTransform x:Name="RectangleTranform2" X="0" Y="0"/> </Rectangle.RenderTransform> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RectangleTranform2" Storyboard.TargetProperty="X" Duration="0:0:10" RepeatBehavior="Forever"> <LinearDoubleKeyFrame Value="350" KeyTime="100%"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> <Rectangle Margin="79,68,0,0" Stroke="Black" Height="62" VerticalAlignment="Top" Fill="OrangeRed" HorizontalAlignment="Left" Width="63"> <Rectangle.RenderTransform> <TranslateTransform x:Name="RectangleTranform3" X="0" Y="0"/> </Rectangle.RenderTransform> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RectangleTranform3" Storyboard.TargetProperty="X" Duration="0:0:10" RepeatBehavior="Forever"> <LinearDoubleKeyFrame Value="350" KeyTime="Uniform"/> </DoubleAnimationUsingKeyFrames>

71

Chapter 1
</Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> <Rectangle Height="30" Margin="57,53,0,0" Stroke="Black" VerticalAlignment="Top" HorizontalAlignment="Left" Width="42" Fill="Orange"> <Rectangle.RenderTransform> <TranslateTransform x:Name="RectangleTranform4" X="0" Y="0"/> </Rectangle.RenderTransform> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="RectangleTranform4" Storyboard.TargetProperty="X" Duration="0:0:10" RepeatBehavior="Forever"> <LinearDoubleKeyFrame Value="350" KeyTime="Paced"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> </Grid> </Window>

In this code, rectangle is added to the Window, which starts moving once the Window is loaded. When you run the code by pressing F5, you can see that there are actually four rectangles added to the application, which are moving together in the same pace. This is because of the KeyTime property, which enables the rectangle to move at the same speed. The output of the code is shown in Figure 1.34:

Figure 1.34: Controlling Timing of KeyFrame

Animating Geometries
There are different types of geometry in WPF, such as Simple Geometry, Path Geometry, and Composite Geometry. You can apply animation to the different types of geometry to create a visually appealing application in WPF. Lets create an application with animating geometries. For this, create a WPF application named AnimatingGeometry (available on the CD-ROM) and add the following code given in Listing 1.38 to Window1.xaml: Listing 1.38: Using Animation for Geometry
<Window x:Class="AnimatingGeometry.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300">

72

Using Graphics, Animation, and Multimedia in WPF


<Canvas> <Path Fill="Pink" Stroke="Black" StrokeThickness="5"> <Path.Data> <EllipseGeometry x:Name="MyGeometry" Center="200,200" RadiusX="25" RadiusY="50" /> </Path.Data> <Path.Triggers> <EventTrigger RoutedEvent="Path.Loaded"> <BeginStoryboard> <Storyboard> <PointAnimation Storyboard.TargetName="MyGeometry" Storyboard.TargetProperty="Center" From="200,200" To="50,50" Duration="0:0:2" AutoReverse="true" RepeatBehavior="Forever"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Path.Triggers> </Path> </Canvas> </Window>

In this code, EllipseGeometry is used. An Ellipse is added to the application which is moved using animation. When you run the application by pressing F5, the Ellipse starts moving from the point specified in the From property to the point specified in the To property. The speed of the movement is determined by the Duration property. The output is shown in Figure 1.35:

Figure 1.35: Animating Geometry

Using Animation with 3-D Models


The topics till now dealt with animation in 2-D model. You can also apply animations to the 3-D models in WPF. Animating a 3-D model in WPF will give your 3-D application a rich look. You can apply different animations on the 3-D model. One way of animating a 3-D model is to animate the camera. You can also use the Rotation3DAnimation class to animate a 3-D model. The Rotation3DAnimation class applies the rotation effect on the 3-D model.

Animating Cameras
In WPF, you can animate the camera. The camera in WPF is animated using the Point3DAnimation and Vector3DAnimation to animate the Position and LookDirection property of the PerspectiveCamera. The Point3DAnimation class animates the value of the Point3D property using the linear interpolation between the start and the end values. The Vector3DAnimation class animates the value of Vector3D property. Lets create an application of animating the camera of the 3-D model. For this, create a WPF application named AnimatingCamera (available on the CD-ROM) and add the following code given in Listing 1.39 to Window1.xaml:

73

Chapter 1

Listing 1.39: Using the Point3DAnimation and Vector3DAnimation Class


<Window x:Class="AnimatingCamera.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <DockPanel> <Canvas Width="321" Height="201"> <Viewport3D Name="MyAnimatedObject" Width="150" Height="150"> <Viewport3D.Camera> <PerspectiveCamera x:Name="myCamera" Position="0,0,1" LookDirection="0,0,-1" FieldOfView="100" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="-0.612372,-0.5, -0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="0.612372,-0.5,0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Color="Yellow" Offset="0.5" /> <GradientStop Color="Red" Offset="1" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D x:Name="myRotateTransform3D" > <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,3,0" Angle="40" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> <Viewport3D.Triggers> <EventTrigger RoutedEvent="Viewport3D.Loaded"> <BeginStoryboard> <Storyboard>

74

Using Graphics, Animation, and Multimedia in WPF


<Point3DAnimation Storyboard.TargetName="myCamera" Storyboard.TargetProperty="Position" From="0,0,2" To="1,2,3" Duration="0:0:4" RepeatBehavior="Forever"/> <Vector3DAnimation Storyboard.TargetName="myCamera" Storyboard.TargetProperty="LookDirection" From="0,0,-1" To="-1,-2,-3" Duration="0:0:4" RepeatBehavior="Forever"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Viewport3D.Triggers> </Viewport3D> </Canvas> </DockPanel> </Window>

In this code, the 3-D model is added to the application. When you run the application by pressing F5, you can see the 3-D model moving. The animation moves the camera around the object. The object is not changing the position or rotating. It is the moving camera that makes it appear so. As the position of the camera changes using Point3DAnimation, the direction, the camera is pointing to, keeps the object within the view of the camera using the Vector3DAnimation. When you run the code by pressing F5, you get the output as shown in Figure 1.36:

Figure 1.36: Animating Camera

Rotating 3-D Model Using Rotation3DAnimation


In WPF, you can use the Rotation3DAnimation class to animate the Rotation property of the RotateTransfrom3D object applied to 3-D object. The Rotation3DAnimation class animates the value of the Rotation3D property using the linear interpolation between two values. The values are determined using the combination of From, To, and By properties that are set for the animation. Lets create an application to rotate a 3-D model using the Rotation3DAnimation class. For this, create a WPF application named Rotating3DModel (available on the CD-ROM) and add the following code given in Listing 1.40 to Window1.xaml: Listing 1.40: Using Rotation3DAnimation Class
<Window x:Class="Rotating3DModel.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <DockPanel> <Canvas Width="321" Height="201"> <Viewport3D Name="MyAnimatedObject" Width="150" Height="150"> <Viewport3D.Camera> <PerspectiveCamera x:Name="myCamera" Position="0,0,1" LookDirection="0,0,-1" FieldOfView="100" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content>

75

Chapter 1
<DirectionalLight Color="White" Direction="-0.612372,0.5,-0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Color="White" Direction="0.612372,-0.5,0.612372" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D> <ModelVisual3D.Content> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D TriangleIndices="0,1,2 3,4,5 " Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 " TextureCoordinates="0,0 1,0 1,1 1,1 0,1 0,0 " Positions="-0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 " /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <MaterialGroup> <DiffuseMaterial> <DiffuseMaterial.Brush> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Color="Yellow" Offset="0.5" /> <GradientStop Color="Red" Offset="1" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </MaterialGroup> </GeometryModel3D.Material> <GeometryModel3D.Transform> <RotateTransform3D x:Name="myRotateTransform3D" > <RotateTransform3D.Rotation> <AxisAngleRotation3D Axis="0,3,0" Angle="40" /> </RotateTransform3D.Rotation> </RotateTransform3D> </GeometryModel3D.Transform> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> <Viewport3D.Triggers> <EventTrigger RoutedEvent="Viewport3D.Loaded"> <BeginStoryboard> <Storyboard> <Rotation3Danimation Storyboard.TargetName="myRotateTransform3D" Storyboard.TargetProperty="Rotation" AutoReverse="True" RepeatBehavior="Forever"> <Rotation3DAnimation.From> <AxisAngleRotation3D Axis="0,3,0" Angle="-60" /> </Rotation3DAnimation.From> <Rotation3DAnimation.To> <AxisAngleRotation3D Axis="1,0,1" Angle="60" /> </Rotation3DAnimation.To> </Rotation3DAnimation> </Storyboard> </BeginStoryboard> </EventTrigger> </Viewport3D.Triggers>

76

Using Graphics, Animation, and Multimedia in WPF


</Viewport3D> </Canvas> </DockPanel> </Window>

In this code, a 3-D object is added to the application. The animation is attached to the 3-D object. When you load the Window, the 3-D object starts moving. The RepeatBehavior property of the 3-D object is set to True. When you run the code by pressing F5, you get the output, as shown in Figure 1.37:

Figure 1.37: Rotating a 3-D Model

Multimedia in WPF 3.5


This section of the chapter introduces you to the multimedia features of WPF. The multimedia feature allows you to integrate sound and video into your applications in order to enhance the user experience. WPF includes support for playing the audio and video files supported by Windows Media Player. It also allows you to play more than one media file together. The most impressive part of multimedia in WPF is that it gives you tools to integrate video content with the rest of the user interface. For example, you can place a video window on a spinning 3-D cube. Multimedia in WPF includes images, audio and video, which are the rich ways of conveying information and user experiences. In this section, you will leran about: WPF Images Audio and Video in WPF Lets discuss these in detail.

WPF Images
Images in WPF are a core part of most applications. Images in WPF include icon, background, and even part of animation. You can work in a variety of ways with images in WPF. WPF Imaging enables you to display, transform, and format images. WPF imaging is designed to overcome the shortcoming of GDI and provide a new set of API to display and use images within the application. You can access the WPF imaging API in two ways, such as a managed component and an unmanaged component. The managed WPF imaging is available in the System.Windows.Media.Imaging namespace and System.Windows.Media namespace. The managed component utilizes the unmanaged component to provide integration of the images with other WPF features such as animation and graphics. The unmanaged component provides improved performance and security on the local image formats which includes bitmap (BMP), Joint Photographics Experts Group (JPEG), Portable Network Graphics (PNG), Tagged Image File Format (TIFF), Microsoft Windows Media Photo, Graphics Interchange Format (GIF), and icon (.ico). In WPF, the Image class represents the control that displays an image. You can load all the image types supported by WPF with the help of the Image control. The image content is used to determine the final size and location of the control. So, until the image is loaded, the ActualHeight and ActualWidth of the control will

77

Chapter 1

be zero. The Stretch property of the Image control determines how the image is stretched to fill the image element. You can add the Image control to your application by adding the following code:
<Image .../>

The inheritance hierarchy of the Image control is as follows:


System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Image

The noteworthy properties of the Image control are listed in Table 1.32: Table 1.32: Properties of the Image control

Property
Stretch Source

Description
Gets or sets a value that describes how an Image should be stretched to fill the destination rectangle Gets or sets the ImageSource for the image

You can drag and drop the Image control from the Toolbox and add it to the WPF application. The Image control added to the WPF application is shown in Figure 1.38:

Image control

Figure 1.38: Image control

You can see that, as you add the Image control from the Toolbox, the XAML code is added to the application. Lets now learn about the different image formats used in WPF.

The BitmapSource Class


In WPF, you use the codec to decode or encode a specific image format. WPF includes codec for the following types of images, such as BMP, JPEG, TIFF, PNG, Windows Media Photo, GIF, and ICON image. The BitmapSource class is used to decode and encode images. It is the basic building block of the WPF Imaging. A BitmapSource can perform either of the two functions: either it can be an individual frame of multiple frame images or it can be the result of a transform performed on BitmapSource. The BitmapSource is not used to represent a multi-frame image or an animation. The BitmapSource class represents the single, constant set of

78

Using Graphics, Animation, and Multimedia in WPF

pixels at a certain size and resolution. The BitmapSource is an abstract class. The inheritance hierarchy of the BitmapSource class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.ImageSource System.Windows.Media.Imaging.BitmapSource

The noteworthy properties of the BitmapSource class are listed in Table 1.33: Table 1.33: Properties of BitmapSource class

Property
CanFreeze DependencyObjectType Dispatcher DpiX DpiY Format HasAnimatedProperties Height IsDownloading IsFrozen IsSealed Metadata Palette PixelHeight PixelWidth Width

Description
Retrieves a value that indicates whether the object can be made unmodifiable Retrieves the DependencyObjectType that wraps the CLR type of this instance Retrieves the Dispatcher the Bitmapsource class DispatcherObject is associated with Retrieves the horizontal dots per inch (dpi) of the image Retrieves the vertical dots per inch (dpi) of the image Retrieves the native PixelFormat of the bitmap data Retrieves a value that indicates whether one or more AnimationClock objects is associated with any of the BitmapSource class dependency properties Retrieves the height of the source bitmap in device-independent units Retrieves a value that indicates whether the BitmapSource content is currently downloading Retrieves a value that indicates whether the object is currently modifiable Retrieves a value that declares whether the BitmapSource class instance is currently read-only Retrieves the metadata that is associated with the bitmap image Retrieves the color palette of the bitmap Retrieves the height of the bitmap in pixels Retrieves the width of the bitmap in pixels Retrieves the width of the bitmap in device-independent units

The noteworthy methods of the BitmapSource class are listed in Table 1.34: Table 1.34: Methods of BitmapSource class

Method
Clone CloneCurrentValue Create CopyPixels

Description
Creates a modifiable clone of the BitmapSource Creates a modifiable clone of the BitmapSource object Creates a new BitmapSource that has the specified properties and options Creates a new BitmapSource class that has the specified properties and options

The BitmapFrame is used to store the actual bitmap data of the image format. The formats such as GIF and TIFF support multiple frames per image, but some image format support a single BitmapFrame.

Image Metadata
Metadata describes the content or characteristic of the file. There is a different metadata associated with each image, but WPF imaging provides a uniform way of storing and retrieving metadata for each image. You can access the metadata of the image through the Metadata property of the BitmapSource object. The Metadata returns a BitmapMetadata object that includes all the metadata information contained by the image. The BitmapMetadata can be a single schema or a collection of schemas. The image metadata schemas supported by WPF imaging are Exchangeable Image File (Exif), tEXt (PNG Textual Data), image file directory (IFD), International Press Telecommunications Council (IPTC), and Extensible Metadata Platform (XMP).

79

Chapter 1

If the BitmapMetadata is exposed by a BitmapFrame that is obtained by using the BitmapDecoder, it is a read-only by default. The mutable operations will throw an exception. If the BitmapMetadata is exposed by a BitmapFrame that wraps another BitmapSource, it is mutable on construction. You can use the GetQuery and SetQuery methods to construct and read metadata queries.

Audio and Video


In this section, you will learn two more areas of WPF, such as audio and video. WPF gives you the ability to play a wide variety of sound formats, which includes anything supported by the Windows Media Player. Similarly, WPF also supports the video format which includes the MPEG and WMV files. You can also integrate the audio and video into the rest of the WPF application. For example, you can use video and combine it with animation, 3-D objects, and animation. You can integrate the audio and video content in your application. WPF uses the MediaElement control for playing both video and audio.

The MediaElement and MediaPlayer Classes


The MediaElement and MediaPalyer classes are used in WPF to present audio, video, and video with audio content. The MediaElement class is the UIElement and can be consumed as the content of many controls. It can be used both in XAML as well as code. The MediaPlayer class is designed for Drawing objects. The MediaPlayer cannot be used in XAML. You can declare an instance of the MediaPlayer class in XAML; you cannot load and play the media without using the code. To play media in XAML, you need to use MediaElement. The MediaPlayer class is found in the System.Windows.Media namespace. You need to create a MediaPlayer object, and then call the Open method to load the audio file, and call the Play to begin it playing. The audio played using the MediaPlayer class is played asynchronously; there is no option of synchronous playback. The inheritance hierarchy of the MediaPlayer class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Freezable System.Windows.Media.Animation.Animatable System.Windows.Media.MediaPlayer

The noteworthy properties of the MediaPlayer class are listed in Table 1.35: Table 1.35: Properties of MediaPlayer class

Property
Balance BufferingProgress CanPause Clock DownloadProgress HasAnimatedProperties HasAudio HasVideo IsBuffering IsFrozen IsMuted NaturalDuration NaturalVideoHeight NaturalVideoWidth Position ScrubbingEnabled

Description
Gets or sets the balance between the left and right speaker volumes Retrieves the percentage of buffering completed for streaming content Retrieves a value indicating whether the media can be paused Gets or sets the MediaClock associated with the MediaTimeline to be played Retrieves the percentage of download progress for content located at a remote server Retrieves a value that indicates whether one or more AnimationClock objects is associated Retrieves a value that indicating whether the media has audio output Retrieves a value that indicates whether the media has video output Retrieves a value that indicates whether the media is buffering Retrieves a value that indicates whether the object is currently modifiable Retrieves a value that indicates whether the media is muted Retrieves the natural duration of the media Retrieves the pixel height of the video Retrieves the pixel width of the video Gets or sets the current position of the media Gets or sets a value that indicates whether scrubbing is enabled

80

Using Graphics, Animation, and Multimedia in WPF

Table 1.35: Properties of MediaPlayer class

Property
Source SpeedRatio Volume

Description
Retrieves the media Uri Gets or sets the ratio of speed that media is played at Gets or sets the medias volume

The noteworthy methods of the MediaPlayer class are listed in Table 1.36: Table 1.36: Methods of MediaPlayer class

Method
Close Play Pause Stop

Description
Closes the media. Begins playback Pauses playback but does not change the position Stops playback and resets the position to the beginning of the file

The MediaElement is the WPF element that wraps all the functionality of the MediaPlayer class. You can declare an instance of the MediaElement in the XAML. You should note that if you are the MediaElement for video, you should place it where the video window should appear. The inheritance hierarchy of the MediaElement class is as follows:
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.MediaElement

The noteworthy properties of the MediaElement class are listed in Table 1.37: Table 1.37: Properties of MediaElement class

Property
Balance BufferingProgress CanPause Clock DownloadProgress HasAudio HasVideo IsBuffering IsMuted LoadedBehavior NaturalDuration NaturalVideoHeight NaturalVideoWidth Position ScrubbingEnabled Source SpeedRatio

Description
Gets or sets a ratio of volume across speakers Retrieves a value that indicates the percentage of buffering progress made Retrieves a value indicating whether the media can be paused Gets or sets the clock associated with the MediaTimeline that controls media playback Retrieves a percentage value indicating the amount of download completed for content located on a remove server Retrieves a value indicating whether the media has audio Retrieves a value indicating whether the media has video Get a value indicating whether the media is buffering Gets or sets a value indicating whether the audio is muted Gets or sets the load behavior MediaState for the media Retrieves the natural duration of the media Retrieves the height of the video associated with the media Retrieves the width of the video associated with the media Gets or sets the current position of progress through the medias playback time Gets or sets a value that indicates whether the MediaElement will update frames for seek operations while paused Gets or sets a media source on the MediaElement Gets or sets the speed ratio of the media

81

Chapter 1

Table 1.37: Properties of MediaElement class

Property
Stretch UnloadedBehavior Volume

Description
Gets or sets a Stretch value that describes how a MediaElement fills the destination rectangle Gets or sets the unload behavior MediaState for the media Gets or sets the media volume

The noteworthy methods of the MediaElement class are listed in Table 1.38: Table 1.38: Methods of MediaElement class

Method
ArrangeOverride MeasureOverride OnCreateAutomationPeer OnRender

Description
Arranges and sizes a MediaElement control Updates the DesiredSize of the MediaElement Creates and returns an AutomationPeer object for the MediaElement Draws the content of a DrawingContext object during the render pass of a MediaElement control

You can drag and drop the MediaElement control from the Toolbox and add it to the WPF application. The MediaElement control added to the WPF application is shown in Figure 1.39:

MediaElement control

Figure 1.39: MediaElement control

You can see that as you add the MediaElement control from the Toolbox, the XAML code is added to the application.
You should set the LoadedBehavior property of the MediaElement to Manual in order to interactively stop, pause, and play the media.

Modes of Media Playback


You can use media object; MediaPlayer and the MediaElement class in two different modes; the independent mode and the clock mode. The mode is determined by the Clock property. If the Clock is set to null, the media object is in the independent mode. If the Clock is set to non-null, the media object is in the clock mode. The default mode is the independent mode. You can control the media playback in the independent mode by using

82

Using Graphics, Animation, and Multimedia in WPF

the media object control methods which are Play, Pause, Close, and Stop. You can control the media playback in the clock mode by using the ClockController control methods. The ClockController is obtained from the ClockController property of the MediaClock. You cannot use the media object control methods in the Clock mode. If you attempt to use the method, an InvalidOperationException will be thrown. The MediaPlayer class is used in two different modes: independent mode and clock mode. In the independent mode, the MediaPlayer is like an image and the media which is opened by the Open method drives the playback. In the clock mode, the MediaPlayer can be combined with animation, and so it will have the corresponding Timeline and Clock class attached to it. You should use the VideoDrawing or DrawingContext class to display media loaded using MediaPlayer. The MediaElement can also be used in two different modes: independent or clock mode. In the independent mode, the MediaElement is similar to an image, and the Source URI can be directly specified. In the clock mode, the MediaElement can be used with animation, and so will have the Timeline and Clock class.

Using Multimedia in WPF 3.5


After graphics and animation, another rich way of conveying information is multimedia. Multimedia is that part of WPF which will not only give rich user interface, but also will convey your message in a better way. Multimedia allows you to play both audio and video files in WPF. You can integrate multimedia with animations and create a rich looking interface. You can create effects such as placing a video window on a sipping 3-D cube. Lets now learn how to use multimedia in WPF.

Displaying Images using the Image Control


In multimedia, you can display images using the Image control. A BitmapImage is used to define the image source. The DecodePixelWidth of the BitmapImage is set to the same width as the Width of the Image. This is done so that minimum amount of memory is used in rendering the image. The Stretch property determines the nature of stretch of the image. Lets create an application to display images. For this, create a WPF application named ImageControl (available on the CD) and add the following code given in Listing 1.41 to Window1.xaml: Listing 1.41: Using Image Control
<Window x:Class="ImageControl.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="400" Width="400"> <StackPanel Height="300" Width="300"> <Image Width="250" Stretch="UniformToFill"> <Image.Source> <BitmapImage DecodePixelWidth="200" UriSource=" D:\.NET Framework 3.5\Chapter 1\Chapter 1\ImageControl\Image.jpg"/> </Image.Source> </Image> </StackPanel> </Window>

You need to change the path of the image specified in the UriSource according to the image location in your system.

In this code, an image is loaded to the application using the Image control. The Stretch property determines how the image is stretched to fill the Image control. When you run the code by pressing F5, you get the output as shown in Figure 1.40:

83

Chapter 1

Figure 1.40: Image Control

You have learned about the Image control in detail in Chapter 17, Templates, and Commands.

Working

with WPF 3.5 Controls, Resources, Styles,

Transforming Images
In WPF, you can transform images using the properties of the BitmapImage. The different transformations that you can apply to a WPF image are rotating, converting, and cropping the image. You can rotate an image by using the Rotation property of the BitmapImage. You can convert an image to a different pixel format, such as grayscale, by using the FormatConvertedBitmap class. You can crop an image either by using the Clip property or the CroppedBitmap property. If you want to display a portion of an image, you should use the Clip property and if you want to encode and save a cropped image, the CroppedBitmap should be used. Lets create an application and perform the different transformations. For this, create a WPF application named TransformingImages (available on the CD) and add the following code given in Listing 1.42 to Window1.xaml: Listing 1.42: Transformation of Images
<Window x:Class="TransformingImages.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="400" Width="400"> <Grid> <Image Width="150" HorizontalAlignment="Left" VerticalAlignment="Top"> <Image.Source> <TransformedBitmap Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\TransformingImages\Image.jpg" > <TransformedBitmap.Transform> <RotateTransform Angle="180"/> </TransformedBitmap.Transform> </TransformedBitmap> </Image.Source> </Image> <Image Width="150" HorizontalAlignment="Right" VerticalAlignment="Top"> <Image.Source> <FormatConvertedBitmap Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\TransformingImages\Image.jpg" DestinationFormat="Gray4" /> </Image.Source> </Image> <Image Width="200" Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\TransformingImages\Image.jpg" HorizontalAlignment="Center" VerticalAlignment="Center">

84

Using Graphics, Animation, and Multimedia in WPF


<Image.Clip> <EllipseGeometry Center="100,70" RadiusX="70" RadiusY="50" /> </Image.Clip> </Image> </Grid> </Window>

In this code, a single image is transformed in three different ways. In the first image, the image is rotated using the RotateTransform property. The second image is converted to a different pixel format. The third image is cropped using the EllipseGeometry. When you run the code by pressing F5, you get the output as shown in Figure 1.41:

Figure 1.41: Transforming Images

Stretching Images
You can use the Stretch property of the Image control to control how an image is stretched to fill the container. The values of the Stretch property are None, Fill, Uniform, and UniformToFill. The image is not stretched if the Stretch property is set to None. If the image is larger than the output area, then the image is clipped. The Fill value scales the image to fill the output area. In this case, the aspect ratio of the image may not be preserved. The Uniform value scales the image, so that it completely fits the output area. The aspect ratio of the image in this case is preserved. The UniformToFill value scales the image to completely fill the output area. The aspect ratio of the image is preserved. Lets use the Strecth property on the Image control. For this, create a WPF application named StretchingImages (available on the CD-ROM) and add the following code given in Listing 1.43 to Window1.xaml: Listing 1.43: Using the Stretch Property
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <DockPanel> <Grid Margin="10" ShowGridLines="True" VerticalAlignment="Center" HorizontalAlignment="Center"> <Grid.ColumnDefinitions> <ColumnDefinition Width="175" /> <ColumnDefinition Width="175" /> <ColumnDefinition Width="175" /> <ColumnDefinition Width="175" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition />

85

Chapter 1
<RowDefinition Height="200"/> </Grid.RowDefinitions> <Border Grid.Column="0" Grid.Row="1" BorderThickness="3" BorderBrush="Black"> <Image Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\StretchingImages\Image.jpg" Stretch="None" /> </Border> <Border Grid.Column="1" Grid.Row="1" BorderThickness="3" BorderBrush="Black"> <Image Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\StretchingImages\Image.jpg" Stretch="Uniform" /> </Border> <Border Grid.Column="2" Grid.Row="1" BorderThickness="3" BorderBrush="Black"> <Image Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\StretchingImages\Image.jpg" Stretch="UniformToFill" /> </Border> <Border Grid.Column="3" Grid.Row="1" BorderThickness="3" BorderBrush="Black"> <Image Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\StretchingImages\Image.jpg" Stretch="Fill" /> </Border> </Grid> </DockPanel> </Page>

In this code, images are displayed on the Window. The same image is displayed using the four values of the Strecth property. When you run the code by pressing F5, you get the output as shown in Figure 1.42:

Figure 1.42: Stretching Images

Using MediaElement to Control the Media Playback


In WPF, you can play media files also. The MediaElement class is used for playing the audio or video content in WPF. The Uri class is used to specify the path of the media you want to include. Lets create an application using the MediaElement class. For this, create a WPF application named MediaElement (available on the CDROM) and add the following code given in Listing 1.44 to Window1.xaml: Listing 1.44: Using the MediaElement Class
<Window x:Class="MediaElement.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid Background="AliceBlue">

86

Using Graphics, Animation, and Multimedia in WPF


<MediaElement Margin="40,0,78,0" Name="mediaElement1" Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\MediaElement\One Step Beyond.wma" LoadedBehavior="Manual" UnloadedBehavior="Stop" Height="120" VerticalAlignment="Top" /> <Button HorizontalAlignment="Left" Margin="0,0,0,106" Name="button1" Width="75" Click="button1_Click" Height="23" VerticalAlignment="Bottom">Play</Button> <Button Margin="105,0,98,106" Name="button2" Click="button2_Click" Height="23" VerticalAlignment="Bottom">Stop</Button> <Button Margin="0,0,13,106" Name="button3" Click="button3_Click" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75">Pause</Button> <Label Height="28" HorizontalAlignment="Left" Margin="0,0,0,66" Name="label1" VerticalAlignment="Bottom" Width="120">Volume</Label> <Slider Height="21" Name="slider1" VerticalAlignment="Bottom" ValueChanged="ChangeMediaVolume" Margin="66,0,62,73" /> <Label Height="28" HorizontalAlignment="Left" Margin="0,0,0,47" Name="label2" VerticalAlignment="Bottom" Width="120">Speed</Label> <Slider Height="21" Margin="66,0,62,47" Name="slider2" VerticalAlignment="Bottom" ValueChanged="ChangeMediaSpeedRatio"/> </Grid> </Window>

You need to change the path of the media file specified in this application as well as all the applications in this chapter that are using the media file according to its location in your system.

In this code, two labels, three buttons and two sliders are added to the application along with MediaElement control. The buttons are used for playing, pausing, and stopping the media. The sliders are used to control the volume and change the speed of the music. To control the functioning of the Button control and the Slider control, you need to add the code given in Listing 1.45: Listing 1.45: Adding code for Controlling the Controls
using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes;

namespace MediaElement { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { mediaElement1.Position = TimeSpan.Zero; mediaElement1.Play(); } private void button2_Click(object sender, RoutedEventArgs e)

87

Chapter 1
{ mediaElement1.Stop(); } private void button3_Click(object sender, RoutedEventArgs e) { mediaElement1.Pause(); mediaElement1.Position = TimeSpan.FromSeconds(slider1.Value); } private void ChangeMediaVolume(object sender, RoutedPropertyChangedEventArgs<double> args) { mediaElement1.Volume = (double)slider1.Value; } private void ChangeMediaSpeedRatio(object sender, RoutedPropertyChangedEventArgs<double> args) { mediaElement1.SpeedRatio = (double)slider2.Value; } } }

In this code, the click event of the Button control and the movement of the Slider control are controlled. When you run the code by pressing F5, you can see the output as shown in Figure 1.43:

Figure 1.43: Using the MediaElement control

If you do not add the buttons for controlling the playback of the media, the media loaded using the MediaElement control plays automatically once the Window is loaded.

Adding Media Using MediaPlayer


You can add media using the MediaPlayer class in WPF. The difference between the MediaElement and MediaPlayer class is that, you can declare an instance of the MediaPlayer class in XAML, but you cannot load and play the media without using code. To play media only in XAML, use the MediaElement class. Lets create an application to play the media using the MediaPlayer class. For this, create a WPF application named UsingMediaPlayer (available on the CD-ROM) and add the following code given in Listing 1.46 to Window1.xaml: Listing 1.46: Using MediaPlayer class
<Window x:Class="UsingMediaPlayer.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Margin="77,100,64,111" Name="button1" Click="button1_Click">Click to Play</Button> </Grid> </Window>

88

Using Graphics, Animation, and Multimedia in WPF

In this code, a Button is added to the Window. The media is attached to the click event of the Button. The code for the click event of Button is given in Listing 1.47: Listing 1.47: Adding code for the MediaPlayer
using using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes; System.Windows.Media.Animation;

namespace UsingMediaPlayer { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { MediaTimeline myTime = new MediaTimeline(new Uri(@"C:\Users\avantika\Documents\Visual Studio 2008\Projects\UsingMediaPlayer\Love Comes.wma", UriKind.Relative)); myTime.RepeatBehavior = RepeatBehavior.Forever; MediaClock myClock = myTime.CreateClock(); MediaPlayer myPlayer = new MediaPlayer(); myPlayer.Clock = myClock; VideoDrawing myDrawing = new VideoDrawing(); myDrawing.Rect = new Rect(0, 0, 100, 100); myDrawing.Player = myPlayer; } } }

The code calls the media file when you click the Button. The final output is shown in Figure 1.44:

Figure 1.44: Using the MediaPlayer

89

Chapter 1

The media file attached to the code plays when you click the Button.

Using Storyboard to Control the Media Playback


You have learned to control the playback of media through user input. You have added code on the click of the Button to control the media playback. You can control the media playback through XAML code. You need to use the Storyboard to control the media playback through XAML code. You cannot use the MediaPlayer class to control the media through XAML code. When you use the Storyboard to control the timing of MediaElement, the functionality is same as the Timeline object used in animation. The MediaTimeline uses the BeginTime property to specify when to start the MediaElement. It also uses the Duration property to specify how long the MediaElement is active. Lets create an application to control the media playback using Storyboard. For this, create a WPF application named Storyboard_MediaPlayback (available on the CD-ROM) and add the following code given in Listing 1.48 to Window1.xaml: Listing 1.48: Using Storyboard
<Window x:Class="Storyboard_MediaPlayback.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid Background="Aquamarine"> <Button HorizontalAlignment="Left" Margin="0,0,0,99" Name="button1" Width="75" Height="23" VerticalAlignment="Bottom">Play</Button> <Button Margin="67,0,136,99" Name="button2" Height="23" VerticalAlignment="Bottom">Pause</Button> <Button Margin="137,0,66,99" Name="button3" Height="23" VerticalAlignment="Bottom">Resume</Button> <Button HorizontalAlignment="Right" Margin="0,0,0,99" Name="button4" Width="75" Height="23" VerticalAlignment="Bottom">Stop</Button> <MediaElement Margin="0,0,118,0" Name="mediaElement1" Height="120" VerticalAlignment="Top" MediaOpened="Element_MediaOpened"/> <Slider Height="21" Margin="77,0,101,54" Name="slider1" VerticalAlignment="Bottom" /> <Grid.Triggers> <EventTrigger RoutedEvent="Button.Click" SourceName="button1"> <EventTrigger.Actions> <BeginStoryboard Name="Play"> <Storyboard> <MediaTimeline Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\Storyboard_MediaPlayback\Media.wma" Storyboard.TargetName="mediaElement1" CurrentTimeInvalidated="MediaTimeChanged"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="button2"> <EventTrigger.Actions> <PauseStoryboard BeginStoryboardName="Play"> </PauseStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="button3"> <EventTrigger.Actions> <ResumeStoryboard BeginStoryboardName="Play"> </ResumeStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="Button.Click" SourceName="button4"> <EventTrigger.Actions> <StopStoryboard BeginStoryboardName="Play"> </StopStoryboard> </EventTrigger.Actions> </EventTrigger> </Grid.Triggers> </Grid>

90

Using Graphics, Animation, and Multimedia in WPF


</Window>

In this code, MediaTimeline control is added to play media file. The Buttons are added to control the playback of the media. The Slider is added to show the progress of media. The playback of media is controlled by using the Storyboard on the click of the Button. The functionality for the progress bar, which is the Slider control, is added through the code file given in Listing 1.49: Listing 1.49: Controlling the Slider Control
using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes;

namespace Storyboard_MediaPlayback { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void Element_MediaOpened(object sender, EventArgs e) { slider1.Maximum = mediaElement1.NaturalDuration.TimeSpan.TotalMilliseconds; } private void MediaTimeChanged(object sender, EventArgs e) { slider1.Value = mediaElement1.Position.TotalMilliseconds; } } }

In this code, the functionality of the progress bar is controlled. When you run the code by pressing F5, the Window with the Button for Play, Pause, Resume, and Stop along with the Slider is displayed. As you click the Play Button, the media starts playing. The Slider progresses as the media is playing. After running the code, you can see the Window as shown in Figure 1.45:

Figure 1.45: Controlling Media using Storyboard

91

Chapter 1

Playing a Media on a User Event


In WPF, you can play the media file on a user event. For example, you can load a new Window on the click of the Button and play the media along with animation in that Window. The loading of a new Window on the click of the Button is the user event. You can integrate animation with media to create a visually appealing application. Lets create an application to play the media on a user event. For this, create a WPF application named PlayingMedia_UserEvent (available on the CD-ROM) and add the following code given in Listing 1.50 to Window1.xaml: Listing 1.50: Adding Button in XAML File
<Window x:Class="PlayingMedia_UserEvent.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Name="button1" Click="button1_Click">Click to play</Button> </Grid> </Window>

The code in Listing 1.50 will add a Button to the Window1. When you will click the Button, the Window1 will close itself and a new Window with the name Window2 will appear which will be playing the animation and the media file. For the Window1 to close and the new Window to open, you need to add the code given in Listing 1.51 in the code-behind file, which is Window1.xaml.cs: Listing 1.51: Adding code on the Click Event of button1
using using using using using using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input; System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes; System.Diagnostics;

namespace PlayingMedia_UserEvent { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { // InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { Window2 myWindow = new Window2(); myWindow.Show(); this.Close(); } } }

You need to load a new Window on the click of the Button and play the media and animation on the second Window. For this, right-click the project name which is PlayingMedia_UserEvent in the Solution Explorer. Select Add New Item, as shown in Figure 1.46:

92

Using Graphics, Animation, and Multimedia in WPF

Figure 1.46: Adding New Item

The Add New Item Window opens. Select Window(WPF) and provide a name to it, if you wish. The default name is Window2.xaml and click on Add, as shown in Figure 1.47:

Figure 1.47: Adding Window2

A new Window with the name Window2.xaml is added to your project. Listing 1.52: Adding XAML code for media and animation to Window2
<Window x:Class="PlayingMedia_UserEvent.Window2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window2" Height="300" Width="300"> <Canvas Background="Pink"> <Path Stroke="Purple" StrokeThickness="10"> <Path.Data> <EllipseGeometry x:Name="MyEllipseGeometry" Center="125,125" RadiusX="50" RadiusY="25" /> </Path.Data> </Path> <Path Stroke="Gold" StrokeThickness="10"> <Path.Data>

93

Chapter 1
<EllipseGeometry x:Name="MyEllipseGeometry2" Center="125,125" RadiusX="25" RadiusY="50" /> </Path.Data> </Path> <MediaElement Name="mediaElement1"> <MediaElement.Triggers> <EventTrigger RoutedEvent="MediaElement.Loaded"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard SlipBehavior="Slip"> <MediaTimeline Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\PlayingMedia_UserEvent\Media.wma" BeginTime="0:0:0"> </MediaTimeline> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyEllipseGeometry" Storyboard.TargetProperty="RadiusY" RepeatBehavior="Forever"> <DoubleAnimationUsingKeyFrames.KeyFrames> <LinearDoubleKeyFrame Value="100" KeyTime="0:0:4"/> </DoubleAnimationUsingKeyFrames.KeyFrames> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyEllipseGeometry2" Storyboard.TargetProperty="RadiusX" RepeatBehavior="Forever"> <DoubleAnimationUsingKeyFrames.KeyFrames> <LinearDoubleKeyFrame Value="100" KeyTime="0:0:4"/> </DoubleAnimationUsingKeyFrames.KeyFrames> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </MediaElement.Triggers> </MediaElement> </Canvas> </Window>

As you run the code by pressing F5, the Window1 will appear as shown in Figure 1.48:

Figure 1.48: Button on Window1

When you click the Button on Window1, it disappears and Window2 is loaded, which plays the animation along with the media file. The output of Window2 is shown in Figure 1.49:

94

Using Graphics, Animation, and Multimedia in WPF

Figure 1.49: Animation on Window2

Transforming a Video in MediaElement


In WPF, you can transform the MediaElement control. By transformation, it implies that you can rotate the MediaElement control to display the video in the angle you like. You can use the TransformGroup class to apply RotateTransform or ScaleTransform to the MediaElement control. Lets create an application with transformation applied to the MediaElement control. For this, create a WPF application named TransformingVideo (available on the CD-ROM) and add the following code given in Listing 1.53 to Window1.xaml: Listing 1.53: Transforming Video in MediaElement
<Window x:Class="TransformingVideo.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <MediaElement Source="C:\Users\avantika\Documents\Visual Studio 2008\Projects\TransformingVideo\Video.wmv" Margin="41,0,27,36" Name="myMedia" LoadedBehavior="Manual"> <MediaElement.LayoutTransform> <TransformGroup> <RotateTransform Angle="400" /> </TransformGroup> </MediaElement.LayoutTransform> </MediaElement> <Button Height="23" Margin="104,0,99,18" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Play</Button> </Grid> </Window>

In this code, the MediaElement is added to the Window. The MediaElement control is added to the application which is transformed using RotateTransform. A Button is added to the application and the code is added on the click event of the Button control for the media file to play. The code for the click event of the Button control is given in Listing 1.54: Listing 1.54: Adding code for the click event of Button
using using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Windows; System.Windows.Controls; System.Windows.Data; System.Windows.Documents; System.Windows.Input;

95

Chapter 1
using using using using System.Windows.Media; System.Windows.Media.Imaging; System.Windows.Navigation; System.Windows.Shapes;

namespace TransformingVideo { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { myMedia.Position = TimeSpan.Zero; myMedia.Play(); } } }

In this code, the click event of the Button control is added. When you run the code in Listing 1.53 and Listing 1.54 by pressing F5, you get the output Window, as shown in Figure 1.50, with the Button added to it. When you click the Play button, the media file is loaded to the Window:

Figure 1.50: Transforming Video in MediaElement

Summary
In this chapter, you have learned about drawing graphics in Windows Form applications with the help of different classes. You have also learned about using the graphics, animation, and multimedia features in WPF 3.5. In addition, you have learned about creating different shapes and geometries and adding colors to them with the help of brushes. The chapter also describes use of multimedia in WPF 3.5. In the next chapter, you learn about data binding in Windows Form and WPF applications

Quick Revise
Q1. Ans. __________ is the successor to GDI which is responsible for the integration of graphics in Window Form. GDI+.

96

Q2. Ans. Q3. Ans. Q4. Ans. Q5. Ans.

Q6. Ans.

Q7. Ans.

Q8. Ans.

Q9. Ans.

The __________ class enables you to combine a collection of drawings that can be operated as a single drawing. DrawingGroup. You can use a Storyboard to group multiple animations. (True/False) True. The BitmapSource classe is used in WPF to present audio, video, and video with audio content. (True/False) False. Mention the important classes in WPF that allow you to work with the 2-D graphics. The WPF classes that pertain to 2-D graphics are: The System.Windows.Shapes.Shape class: Provides the functionality to work with simple 2-D shapes such as ellipse and rectangle The System.Windows.Media.Geometry class: Provides the functionality to work with geometric shapes and curves The System.Windows.Media.Drawing class: Provides the functionality to work with 2-D drawings What are the brushes that are available in WPF? The brushes available in WPF are objects of the classes that inherit the System.Windows.Media.Brush class. The brushes that are available in WPF 3.5 are: SolidColorBrushPaints a given area with a solid color LinearGradientBrushPaints a given area with linear gradient RadialGradientBrushPaints a given area with radial gradient DrawingBrushPaints a given area with a drawing ImageBrushPaints a given area with an image VisualBrushPaints a given area with a Visual object How many types of projection cameras are available for 3-D graphics in WPF? WPF supports mainly two types of projection cameras for 3-D objects: Orthographic cameraRenders the 3-D scene such that the exact scale of the object is preserved Perspective cameraRenders the 3-D scene such that the objects that are far appear smaller, while the objects that are near appear larger What are the different kinds of animation supported in WPF? WPF has a rich support for animations, which can be used to change property values, reposition elements, change colors, and so on. The functionality to create and manipulate animations is provided by the System.Windows.Media.Animation namespace. Animation in WPF can be of three types: Basic animationRefers to the animation in WPF that is created by changing the property value from a starting value to a destination value. Alternatively, an offset value can also be provided to indicate the amount of change during the animation. The stating value is specified by the From property, the destination value is specified by the To property, and the offset value is specified by the By property. This is why basic animation is also known as From/To/By animation. Keyframe animationRefers to the animation that is created by using keyframes, which are the destination values for a property. There can be several keyframes in a single keyframe animation. Path animationRefers to the animation that is created by changing the property value with respect to a given path described by a PathGeometry object. It is ideal for situations when the movement of an object or element has to be along a path. The lines and curves in the given path determine the property value. What are the two modes of media playback? The MediaPlayer and MediaElement controls have two modes in which media can be played back. These two modes depend on the Clock property of the controls. The two playback modes are:

97

Chapter 1

Q10. Ans.

Clock modeRefers to the mode when the Clock property is set to any value other than the null value. The methods of the ClockController object are used to control the playback of the media. Independent modeRefers to the mode when the Clock property is set to the null value. The Play, Pause, Close, and Stop methods can be used to control the playback of the media in the independent mode. What are the image formats supported in WPF? The file formats of images that are supported in WPF are: Bitmap (.bmp) Joint Photographic Experts Group (.jpg and .jpeg) Portable Network Graphics (.png) Tagged Image File Format (.tiff) Graphics Interchange Format (.gif) Icon (.ico) Windows Media Photo

98

You might also like