Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

Programming Windows Phone 7 : The Intricacies of Layout - The Retro Canvas

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
3/4/2011 10:30:14 PM
The Canvas is certainly the most old-fashioned sort of panel. To position elements within the Canvas you supply horizontal and vertical coordinates relative to the top-left corner.

The Canvas has two unusual characteristics:

  • In its MeasureOverride method, Canvas always calls Measure on its children with a size consisting of both an infinite width and an infinite height. (Accordingly, in ArrangeOverride, Canvas sizes each child based on the child’s DesiredSize.)

  • From its MeasureOverride method, Canvas returns a size consisting of a zero width and a zero height.

The first item means that children of a Canvas are always displayed in their smallest possible sizes, which is nothing at all for an Ellipse and Rectangle, and the native pixel size of a bitmap for an Image. Any HorizontalAlignment of VerticalAlignment properties set on children of a Canvas have no effect.

The second item implies that Canvas has no footprint of its own in the Silverlight layout system. (You can override that with explicit Width or Height settings on the Canvas.) This is actually very useful in some circumstances where you want an element to exist somewhere “outside” of the layout system and not affect the positioning of other elements.

Here’s a program that uses a Canvas to display seven Ellipse elements in a type of overlapping chain in the shape of a catenary. A Style object (defined in the Resources collection of the Canvas itself) gives each Ellipse a finite Width and Height; otherwise they would not show up at all.

Example 1. Silverlight Project: EllipseChain File: MainPage.xaml (excerpt)
<Grid x:Name="ContentPanel" Grid.Row="1">
<Canvas>
<Canvas.Resources>
<Style x:Key="ellipseStyle"
TargetType="Ellipse">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="Stroke" Value="{StaticResource PhoneAccentBrush}" />
<Setter Property="StrokeThickness" Value="10" />
</Style>
</Canvas.Resources>

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="0" Canvas.Top="0" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="52" Canvas.Top="53" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="116" Canvas.Top="92" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="190" Canvas.Top="107" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="263" Canvas.Top="92" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="326" Canvas.Top="53" />

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="380" Canvas.Top="0" />
</Canvas>
</Grid>


Notice I’ve removed the Margin on the content panel so the math comes out to 480. Here’s what it look like:



The Canvas is ideal for the arbitrary positioning of elements, which of course is much more associated with vector graphics programming than with control layout.

But get a load of that odd-looking syntax, rather different from anything in XAML I’ve yet described:

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="190" Canvas.Top="107" />

Those Left and Top properties position the upper-right corner of the element relative to the upper-right corner of the Canvas. The properties appear to be defined by the Canvas class, and yet they are set on the Ellipse element! When I first saw this syntax many years ago, I was baffled. Why does the Canvas class need to define Left and Top properties? Shouldn’t FrameworkElement define these properties?

Of course, in graphical programming environments of days gone by, everybody has Left and Top properties because that’s how the system works.

But it doesn’t quite make sense for Silverlight. Canvas needs for its children to have Left and Top properties set, but other panels do not. In fact, other panels—including custom panels that you have yet to write or even conceive—might need quite different properties set on their children.

For this reason, Silverlight supports the concept of attached properties. The Left and Top properties are indeed defined by the Canvas classbut you set these properties on the children on the Canvas. (You can set them on elements that are not actually children of a Canvas, but they will be ignored.)

It’s instructive to look at a program that sets these attached properties in code. The EllipseMesh program creates a bunch of overlapping ellipses in the content grid. The XAML file has an empty Canvas with a SizeChanged event handler assigned:

Example 2. Silverlight Project: EllipseMesh File: MainPage.xaml (excerpt)
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Canvas Name="canvas"
SizeChanged="OnCanvasSizeChanged" />
</Grid>

Although Canvas has no footprint in the layout system, it still has a size and a SizeChanged event. With every SizeChanged call, the event handler empties out the Canvas (just for convenience) and fills it up again with new Ellipse objects:

Example 3. Silverlight Project: EllipseMesh File: MainPage.xaml.cs (excerpt)
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}

void OnCanvasSizeChanged(object sender, SizeChangedEventArgs args)
{
canvas.Children.Clear();

for (double y = 0; y < args.NewSize.Height; y += 75)
for (double x = 0; x < args.NewSize.Width; x += 75)
{
Ellipse ellipse = new Ellipse
{
Width = 100,
Height = 100,
Stroke = this.Resources["PhoneAccentBrush"] as Brush,
StrokeThickness = 10
};

Canvas.SetLeft(ellipse, x);
Canvas.SetTop(ellipse, y);

canvas.Children.Add(ellipse);
}
}
}


Here’s what it looks like:



These two statements set the Left and Top attached properties:

Canvas.SetLeft(ellipse, x);
Canvas.SetTop(ellipse, y);

These are two static methods defined by the Canvas class. You can call these methods either before or after you add the child to the Children collection of the Canvas. Because these methods are static, you can even call them when a Canvas object does not yet exist.

Even more revealing is knowing how these two static methods are defined in the Canvas class. Right in the EllipseMesh program you can replace the two static method calls with the following statements:

ellipse.SetValue(Canvas.LeftProperty, x);
ellipse.SetValue(Canvas.TopProperty, y);

These equivalent calls make it clear that something is actually being set on the Ellipse objects. The SetValue method is defined by DependencyObject—a very basic class in the Silverlight class hierarchy—and LeftProperty and RightProperty are (despite their names) actually static fields of type DependencyProperty defined by Canvas.

My guess is that SetValue accesses an internal dictionary created and maintained by DependencyObject where the first argument to SetValue is the dictionary key and the second is the value. When Canvas is laying out its children in its ArrangeOverride method, it can access these values for a particular child element using either:

double x = GetLeft(child);
double y = GetTop(child);

or the equivalent:

double x = (double)child.GetValue(LeftProperty);
double y = (double)child.GetValue(TopProperty);

The GetValue method accesses the internal dictionary in the child and returns an object of type object that needs to be cast here to a double.

Watch out: I described how to replace the Canvas.SetLeft and Canvas.SetTop calls in EllipseMesh with equivalent calls to SetValue. But this call:

Canvas.SetLeft(ellipse, 57);

is not equivalent to this call:

ellipse.SetValue(Canvas.LeftProperty, 57);

The second argument of Canvas.SetLeft is defined to be of type double but the second argument of the general-purpose SetValue method is defined to be of type object. When the C# compiler parses that SetValue call it will assume the number is an int. Only at runtime will the error be caught. You can avoid the problem by making it explicitly a double:

ellipse.SetValue(Canvas.LeftProperty, 57.0);

Although we speak of the Left and Top attached properties of Canvas, nothing defined by Canvas is actually named Left or Top! Canvas defines static fields named LeftProperty and TopProperty, and static methods named SetLeft, SetTop, GetLeft and GetTop, but nothing named Left or Top. The XAML syntax shown here

<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="190" Canvas.Top="107" />

is actually rendered by making calls to Canvas.SetLeft and Canvas.SetTop.

You’ll see other attached properties around. The standard MainPage.xaml file has an attached property set on its root element:

shell:SystemTray.IsVisible="True"

In fact, the entire SystemTray class exists for the sole purpose of defining this attached property so you can set it on the PhoneApplicationPage derivative. It’s probably the PageApplicationFrame that hunts for this property on each page to determine whether the system tray should be visible.

Other -----------------
- Programming Windows Phone 7 : The Intricacies of Layout - A Custom Vertical StackPanel
- Programming Windows Phone 7 : The Intricacies of Layout - A Single-Cell Grid Clone
- Programming Windows Phone 7 : The Intricacies of Layout - The Mechanism of Layout
- Programming Windows Phone 7 : The Intricacies of Layout - Two ScrollViewer Applications
- Programming Windows Phone 7 : The Intricacies of Layout - Visibility and Layout
- Programming Windows Phone 7 : The Intricacies of Layout - Nested Panels
- Programming Windows Phone 7 : The Intricacies of Layout - Text Concatenation with StackPanel
- Programming Windows Phone 7 : The Intricacies of Layout - The StackPanel Stack
- Programming Windows Phone 7 : The Intricacies of Layout - The Single-Cell Grid
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server