viernes, 14 de marzo de 2008

Silverlight Layout Controls

Silverlight Layout Controls

Layout controls.

In this post I will talk about Silverlight 2 layout controls, what they are, how they behave, how to use them and configure them.

Canvas

This is the simplest layout control in Silverlight, actually it exists since version 1 and 1.1 Alpha.

I think that more than a layout control this is a container control this is because its only function is to “group” controls more that arrange them in certain way.

This is how it looks in the toolbox

Its function is to position its children using X and Y coordinates, it uses two attached properties for that purpose Canvas.Left and Canvas.Top.

If you add an element into a canvas and see its properties you’ll notice it has a Left and a Top property in the layout section of the properties pane.



Modifying these properties changes the position of the element within the canvas, they are measured relative to the top-left corner of the canvas itself, you can use values lower than zero and greater than the size of the Canvas, this will cause the element to get outside its container (the Canvas) but it will still behave the same way as if it where in.


How do layout properties (alignment and margins) of the child elements affect their position into the Canvas?

The HorizontalAlignment and VerticalAlignment properties have no effect on the position of your control, but the Margins do, well… only the left and top, this directly affects the X and Y coordinates of your control but not in the Left and Top property, I mean you will see your control moving but its positioning properties still the same, what they do is increasing or decreasing the distance between the borders of the Canvas and the control.


How does resizing my Canvas will affect its content?

Resizing your canvas will not affect neither the visibility of your control nor the position of it.

This is how it XAML looks:


<Canvas Width="222" Height="253" HorizontalAlignment="Left" VerticalAlignment="Top"> <Ellipse Height="142" Width="133" Canvas.Left="8" Canvas.Top="8" Fill="#FFFFFFFF" Stroke="#FF000000" HorizontalAlignment="Right" VerticalAlignment="Stretch" Margin="0,29,-1872,368" Stretch="Fill" /> </Canvas>



Grid

This is one of the most powerful and versatile of the layout controls from my point of view.

This is how it looks in the toolbox


Its function is to arrange the controls it contains as if they where inside a table, and for that purpose you can define rows and columns to it.

Defining the Rows and Columns

There area three ways to do this, as far as I know

a) Select you Grid as the active element (double click on it), it should look like this in the control tree: with the yellow border.

You will notice that in the design surface it will get a top an left “border” it didn’t had; using the selection tool go to those borders some “rules” will appear on your grid pointing to the row or column you are going to define, the top area is used to define columns while the left area is used to define rows; when you click in this areas the row/column will be defined and some lines delimiting them will appear, this lines will go away (only the lines, not the definition of your rows an columns) if the active selected item is not the grid.



If you want to remove a column or row from the gird you just have to select it and hit the “Del” key.

I must make notice that all the rows and columns you define using this method are proportional measured (you can see this in the XAML because the size of the Row/Column uses a *), this means that if your grid gets resized its columns and rows will resize too, you can change this behavior using one of the other two methods to define rows and columns of your gird.

TIP: If you want to see the grid lines even though the active selected item is not your grid turn the ShowGridLines property of your grid to True, this can only be done in XAML.

b) The second method is using the property editor offered by Expression Blend.

Select the gird which you want to edit, this time is enough to just selected, it does not need to be the active item; go in the properties panel to the Layout section and expand the advanced properties, you will see the ColumDefinitions and RowDefinitions properties:




When you click on the “Edit items in collection” button you will get an editor like this:




Where you can add, delete or move up and down your column or row definitions. This is also the place to define if the dimensions of you row/column will be proportional (resizing when the grid resize) or fixed (keep its size when the gird gets resized), to do this go to the layout section and change between “Star” and “Pixel” unit of the height/width of your row/column, “Star” is for proportional, “Pixel” for fixed.

c) The last way to define the layout of your grid is to edit the XAML, this can be done in both Expression Blend and Visual Studio, it’s easier in Visual Studio because of the intellisense

The next XAML, for example, defines a table of three rows and two columns, where the second row has a fixed size of 50 pixels, the first and the last row takes the 50% of the leftover vertical space and the columns uses the 30% and 70% of the horizontal space in the grid:

<Grid Background="#FFC5E7BD" ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="0.5*" /> <RowDefinition Height="50" /> <RowDefinition Height="0.5*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.3*" /> <ColumnDefinition Width="0.7*" /> </Grid.ColumnDefinitions> </Grid>
Once we define the layout of the Grid is time to position the controls in it. When we add a control inside a Grid it gets four new properties:



These properties are in the layout section on the properties pane and correspond to four attached properties: Gid.Row, Grid.RowSpan, Grid.Column and Grid.ColumnSpan.

The Row and Column properties are used to specify the cell in where we want to position the control, it is necessary to mention that those properties are zero based, it means that if you assign a 0 in the Column property, the object will be placed in the first Column and if you assign a 1 it will be in the second Column, the same applies to the Rows.

The RowSpan and ColumnSpan are used to specify how many Rows or Columns our object will use to be drawn, this will have no effect at least you set the HorizontalAlignment of the object to stretch and its Width to Auto for ColumnSpan or the VerticalAlignment to stretch and the Height of the control to Auto for RowSpan, if you do one of those configurations your control will extend its size to use all the available space in the assigned Columns/Rows.


How do layout properties (alignment and margins) of the child elements affect their position in the Cell?

The HorizontalAlignment and VerticalAlignment assign the alignment of our control inside the cell(s); all the options are self explicative and require no more detail, except for the stretch option, if the Width/Height of our control are set to auto this option will make the control use all the available space of its assigned cell(s), if the control has a fixed Width/Height it will be centered into its assigned cell(s).

The Margin properties will also affect the position of the object inside its cell(s), the Left margin will have effect only if the HorizontalAlignment property is not set to Right, in the same way the Right margin will have effect only if the HorizontalAlignment property is not set to Left; as you can imagine, the Top margin will affect our control only if the VerticalAlignment is not set to Bottom and the Bottom margin will affect it only if the Vertical Alignment is not set to Top.


How does resizing my Grid will affect its content?

Only the control that are inside cells that are proportionally sized (using the * in the size of the corresponding Row or Column) will be affected.

It will depend basically on three factors how your control behaves, this are:

Size (Width and Height)
Alignment (HorizontalAlignment and VerticalAlignment)
Stretch mode (which is located in the advanced zone of the appearance section of the property pane)

And the affection of your control can be in two ways:

· Size
· Position

The size of your control will be affected if the Width/Height of it is set to Auto, the
HorizontalAlignment/VerticalAlignment are set to Stretch and the Stretch mode (in the appearance section of the properties pane) of your control is other than None; How it gets resized depends on the Stretch mode of your control. If you set it to Fill it will use the available space of the cell even if the control has to be distort, if you use Uniform it will grow keeping the relation between Width and Height and without exceeding the available space; finally if you use UniformToFill it will grow keeping the relation between Width and Height but it will exceed the available size if necessary, if this happens the exceeding section of our control will be clipped.

The position of our control will change to keep the alignment assigned in the HorizontalAlignment/VerticalAlignment, it means, for example, than if our control is set to be Right alignment and our controls increases its width, the control will move to keep its right alignment.

To make it more clear here is an example:

XAML before resizing:

<Grid Background="#FFC5E7BD" ShowGridLines="True" Width="396" Height="176"> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="0.4*" /> <RowDefinition Height="0.6*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50" /> <ColumnDefinition Width="0.3*" /> <ColumnDefinition Width="0.7*" /> </Grid.ColumnDefinitions> <Ellipse HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Grid.RowSpan="1" Fill="#FFFFFFFF" Stroke="#FF000000" Width="Auto" Height="Auto" /> <Ellipse HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Fill="#FFFFFFFF" Stroke="#FF000000" d:LayoutOverrides="GridBox" Grid.ColumnSpan="1" Grid.Column="1" Width="20" Height="20" /> <Ellipse HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Fill="#FFFFFFFF" Stroke="#FF000000" Height="20" Width="20" Grid.Column="2" d:LayoutOverrides="GridBox" /> <Ellipse HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Grid.RowSpan="1" Grid.Row="1" Fill="#FFFFFFFF" Stroke="#FF000000" Width="Auto" Height="Auto" Stretch="UniformToFill" /> <Ellipse HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Bottom" Fill="#FFFFFFFF" Stroke="#FF000000" d:LayoutOverrides="GridBox" Grid.ColumnSpan="1" Grid.Column="1" Grid.Row="1" Width="20" Height="20" /> <Ellipse HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Fill="#FFFFFFFF" Stroke="#FF000000" Height="20" Width="20" Grid.Column="2" d:LayoutOverrides="GridBox" Grid.Row="2" /> <Ellipse HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Grid.RowSpan="1" Grid.Row="2" Fill="#FFFFFFFF" Stroke="#FF000000" Width="Auto" Height="Auto" Stretch="Uniform" /> <Ellipse HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" Fill="#FFFFFFFF" Stroke="#FF000000" d:LayoutOverrides="GridBox" Grid.ColumnSpan="1" Grid.Row="2" Grid.Column="1" Width="Auto" Height="Auto" /> <Ellipse HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Center" Fill="#FFFFFFFF" Stroke="#FF000000" Height="20" Width="20" Grid.Column="2" Grid.Row="1" d:LayoutOverrides="GridBox" /> </Grid>
Result:



XAML after resizing (Only the changes are being shown):

<Grid Background="#FFC5E7BD" ShowGridLines="True" Width="200" Height="400">

Result:



StackPanel

The StackPanel is a very useful control when organizing many elements is the task to accomplish.

Its function is to stack its elements in an horizontal or vertical mode.

This is how it looks in the toolbox

The first thing you have to do when working with the stack panel is to decide how you want to arrange its children, vertically or horizontally, this is done using its Orientation property, which is located in the layout section of the properties pane:



Once this is done we can begin adding controls it:



How do layout properties (alignment and margins) of the child elements affect their position into the StackPanel?

The HorizontalAlignment will affect the position of your control only when the Orientation of your StackPanel is vertical and the control is not configured to use all the available Width of the StackPanel (Width = Autho, Stretch != None and HorizontalAlignment = stretch).



In the other hand, if your StackPanel’s Orientation is set to horizontal, the VerticalAlignment of your control will affect its position when it is not using all the available height of the panel.



In a similar way the margins will affect the position of your control depending of the Orientation of the StackPanel and the HorizontalAlignment/VerticalAlignment of the control.







How does resizing my StackPanel will affect its content?

The width/height of your control will be affected only when its configured to use all the available space of the panel.


ScrollViewer

The ScrollVieres is a perfect to use control when the content will grow (in terms of size or quantity) to an unknown size.

Its function is to show an Horizontal and/or a Vertical scroll bar when the content exceeds the container size.

This is how it looks in the toolbox

To use it you have to keep in mind to main properties, HorizontalScrollBarVisibility and VerticalScrollBarVisibility, which are located in the Miscellaneous section of the property pane:


Its possible values are Disabled, Auto, Hidden and Visible… I would recommend setting them both to Auto and letting the control decide when to show the scroll bars.

Its of great importance to be conscious that contrasting the past three layout controls which can have as many children as you want, the ScrollViewer can only have one control which will usually be some other container control like an stack panel or some controls like DataGrid, ListView, etc.

Border

The border is a simple control that behaves the same way that the ScrollViewer in the sense that it can only contain one control.

It is used to decorate some other control with a border stroke.

This is how it looks in the toolbox

Its important properties are the BorderBrush, BorderThikness and CornerRadius:



It is important to say that if we make the content of the Border exceed the Border dimensions, it will be clipped:





Well, this is it my first Silverlight tutorial, documentation, help post or however you want to name it, hope it be useful in some way to you.

No hay comentarios: