Most
typical
Silverlight visual elements are shapes: geometrical elements
that make up the visual experience of the application. This section will
cover many of the available options.
Before we dive into the different supported shapes, we will examine
formatting options. There are several of them, and many of them are
specific to certain shapes, but the following three properties are shared
among all shapes:
Fill
-
How to fill the inner area of a shape (e.g., by providing a
color)
Stroke
-
How to paint the outline of a shape (e.g., by providing a color)
StrokeThickness
-
The width of the outline, in pixels (must not be an integral
value).
We start with probably the easiest shape: a line, represented in
XAML by the element. You need to provide the
start and end points of the line and use the Silverlight coordinate system
(which is pixel-based; the origin is in the top-left corner). The
associated attribute names are X1, Y1,
X2, and Y2. Example 1 paints a
simple triangle, using three lines, and Figure 1 shows
the browser output. Note that thanks to the 5-pixel width of the strokes,
the corners of the triangle are not perfect.
Example 1. A triangle with three lines, the XAML file (Page.xaml, project
Line)
Code View: <UserControl x:Class="Line.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Canvas> <Line Stroke="Red" StrokeThickness="5" X1="200" Y1="50" X2="350" Y2="250" /> <Line Stroke="Green" StrokeThickness="5" X1="350" Y1="250" X2="50" Y2="250" /> <Line Stroke="Blue" StrokeThickness="5" X1="50" Y1="250" X2="200" Y2="50" /> </Canvas> </Grid> </UserControl>
|
If you want to create a closed shape, such as a triangle, rectangle,
and so on, you would be better off using the
element, which combines all points. In the Points
property, you need to provide a list of points, using this
format:
X1,Y1 X2,Y2 X3,Y3 ... Xn,Yn
The rendering algorithm is as follows: the first point is connected
with the second one, the second one with the third one, and so on; at some
time, point number n–1 is connected with point
n. Finally, Silverlight connects
point n with the very first
point.
NOTE
If you want to omit the final step (e.g., if you create a shape
that is not closed because the last point is not connected with the
first one), use instead of
.
Example 2 once again creates the same triangle as
before, but this time the corners are much better, as Figure 2 shows. Since we cannot used alternating edge colors
when using , we added an additional visual
effect by setting the Fill property.
Example 2. A triangle as a polygon, the XAML file (Page.xaml, project Polygon)
<UserControl x:Class="Polygon.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas>
<Polygon Points="200,50 350,250 50,250"
Stroke="Black" StrokeThickness="5" Fill="Orange" />
</Canvas>
</Grid>
</UserControl>
A special case of a polygon is a rectangle, represented in
Silverlight with the
element. Here you do not provide the coordinates of all corners (or of the
top-left and bottom-right corner), but take a different approach: you
provide the width and height of the rectangle in its Width
and Height attributes.
A rounded corner is actually an ellipsis (which will get coverage of
its own next). You can now provide the radius of that ellipsis. If the
horizontal and vertical radii are the same, you get a circle, which is the
most common option for a rounded corner. However, you can also provide different
radius values to create a different visual effect. The attributes you need
to use are RadiusX and RadiusY.
Example 3 uses an ellipsis with a RadiusX:RadiusY ratio of 100:1. In Figure 3 you see the result: the rounded corners slightly
overlap the two horizontal edges of the rectangle.
Example 5-7. A rectangle with rounded corners, the XAML file (Page.xaml,
project Rectangle)
<UserControl x:Class="Rectangle.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas>
<Rectangle Width="200" Height="150"
Stroke="Black" StrokeThickness="5" Fill="Orange"
RadiusX="100" RadiusY="1"/>
</Canvas>
</Grid>
</UserControl>
The final shape is also the most important one, especially if you
have a complex design, such as a path, or the
element. Its most important property is Data, which
contains information defining the path. To tell the truth, it's usually
design tools that create paths, since any shape, regardless of how complex
it is, can be transformed into a path. This section will provide you with
a crash course on path syntax.
A path consists of several painting instructions: moving the virtual
"pen" to a certain position, drawing certain shapes, and ending the
drawing. Every instruction starts with a (case-insensitive) letter that
identifies the instruction, and several parameters may follow.
The first part of a path is the so-called fill rule. This takes care
of a special case: what happens if elements in the path overlap. You may
choose between the default values F0 and F1:
F0
-
Stands for EvenOdd, meaning that points that
have an even number of path segments between them and the end of the
canvas are considered outside the path; points with an odd number
are considered inside and would be filled.
F1
-
Stands for NonZero, meaning that all points
where a line between the point and the end of the canvas crosses the
path from the left side as often as from the right side are
considered inside the path.
Generally, EvenOdd is what you
will want, and since it is the default value, you do not have to provide
it at all.
Next up are the instructions. The first one is usually
M, which stands for "move." This moves the virtual pen to a certain
position but does not start drawing. The following path would put the pen
at x coordinate 40 and y
coordinate 30:
M 40,30
Starting from that point, several shapes are possible. We will start
once again with a line, denoted by the L command. You have to
provide only the end point of the line—the starting point is defined by
the current pen position! The following path would therefore draw a line
from (40,30) to (70,80):
M 40,30 L 70,80
NOTE
Special cases of lines are horizontal lines (H
command) and vertical lines (V command). For horizontal
lines you need to provide only the x coordinate of
the end point; for vertical lines you need to provide only the
y coordinate of the end point.
By using lines, you can create any geometric shape that does not
have curves. For curves, however, several options exist. The A command draws an elliptical arc. You need to provide a set of parameters:
The x and y radii of the ellipsis
The rotation angle of the ellipsis (use degrees)
Whether the angle is larger than 180 degrees (1) or
not (0)
Whether the arc is drawn in a positive direction
(1) or not (0)
The end point of the arc
The following markup would create an arc from (50,50) to (100,50),
using an x and y radius of 75 each, with a 90-degree rotation angle in the
positive direction:
M 50,50 A 50,50 90 0 1 100,50
A type of curve that is very common in the vector graphics field is
the Bézier curve, named after French automobile designer Pierre
Bézier. Assume that you have two points, A and B. Bézier defined a couple
of mathematical equations that define curves between those points. The
easiest one is a linear curve, but they are easy to draw without any extra
help from Silverlight. However, there are more complex variants. A
quadratic Bézier curve (called that because in the defining formula values
are squared) uses a so-called control point to shape the exact look of the
curve. The associated Silverlight path command, Q, provides
the coordinates of this control point and also of the end point; remember
that the start point is again defined by the current position of the
pen.
The following markup moves the pen to (125,125) and creates a Bézier
curve to (175,75), using (110,60) as a control point:
M 125,125 Q 110,60 175,75
A cubic Bézier curve goes one step further and uses two control
points. The associated Silverlight path command is C.
Here is an example—the curve goes from (150,125) to
(50,100), using the two control points (125,175) and (20,125):
M 150,125 C 125,175 20,125 50,100
NOTE
More advanced Bézier curves are available as well: they take the
previous point of the curve into account, making the curve look
smoother. For "smooth," the sister of the quadratic Bézier curve uses
the S command, and the "smooth" cubic Bézier curve uses
T. The syntax is the same as with the Q and
C commands.
One final command is missing. It is called Z and it closes a path, meaning that the
pen draws a straight line to the beginning of the path.
Example 4 shows several of the previous path
commands in action. In Figure 4, working clockwise,
you can see a straight line, an elliptical arc to the right of the
straight line, a quadratic Bézier curve to the right of the arc, and a
cubic Bézier curve. The control points for the Bézier curves have been
marked with an X so that you can see which points the curves are
approaching. These markers have also been created using a path (drawing
two crossing lines).
Example 5-8. Using paths, the XAML file (Page.xaml, project Path)
Code View: <UserControl x:Class="Path.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Canvas>
<Path Data="M 20,10 L 40,70" Stroke="Red" StrokeThickness="5" />
<Path Data="M 50,50 A 50,50 90 0 1 100,50" Stroke="Yellow" StrokeThickness="5" />
<Path Data="M 125,75 Q 200,100 175,125" Stroke="Green" StrokeThickness="5" /> <Path Data="M 195,95 L 205,105 M 205,95 L 195,105" Stroke="Black" StrokeThickness="2" />
<Path Data="M 150,125 C 125,175 20,125 50,100" Stroke="Blue" StrokeThickness="5" /> <Path Data="M 120,170 L 130,180 M 130,170 L 120,180" Stroke="Black" StrokeThickness="2" /> <Path Data="M 15,120 L 25,130 M 25,120 L 15,130" Stroke="Black" StrokeThickness="2" />
</Canvas> </Grid> </UserControl>
|
As mentioned at the beginning of this section, creating a path manually can be painful, so you should use graphics
software for that. However, you can now analyze and understand paths that are created by vector
graphic programs.
|
If you have used SVG before, this path syntax will be very similar
to what you are used to. Most vector formats use the same features for
their paths, so the different forms of syntax are very alike.
|
|
One more shape should not be forgotten: an ellipse, represented
by the element. The most
important attributes are Width and Height,
defining the size of the ellipse. Example 5 shows the
code for using an ellipse, and Figure 5 shows the
browser output.
Example 5-9. Using an ellipse, the XAML file (Page.xaml, project
Ellipse)
<UserControl x:Class="Ellipse.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas>
<Ellipse Width="400" Height="300"
Stroke="Black" StrokeThickness="5" Fill="Orange" />
</Canvas>
</Grid>
</UserControl>
An alternative approach to drawing shapes is to use a
so-called geometry element. It can be compared to shapes (there are
lines, rectangles, paths, etc.), but this element doesn't draw itself.
Instead, it can be used within other elements defining how they look.
For instance, the Clip property of a UI object can be set
to a geometry element defining a path. This path then defines the outer
border of the UI object. Or you could use a geometry element as the
Data property of a <Path> element and,
therefore, provide the layout of the path.
There are several geometry elements, including EllipseGeometry,
LineGeometry, PathGeometry, and
RectangleGeometry.
<Image Source="image.png">
<Image.Clip> <EllipseGeometry Center="150,75" RadiusX="300" RadiusY="150" /> </ImageClip> </Image>
You can also combine (group) geometry elements, by nesting them
under the <GeometryGroup> element. |
|
When the ellipse has the same width and height, you get a
circle.
|
|