.NET & Funky Fresh

Syndication

News

  • <script type="text/javascript" src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&amp;MarketPlace=US&amp;ID=V20070822/US/bluspiconinc-20/8001/8b68bf4b-6724-40e7-99a5-a6decf6d8648"> </script>
Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
.NET 3.0 Crash Course - Part 4: WPF Layout

      In the last part I covered the basics of Xaml and how you can use it to define various UI constructs.  When building a UI, one of the first issues you’ll deal with is how to arrange all of the UI pieces on screen.  In previous MS technologies we have had limited support for layout.  .NET 2.0 offers WinForms developers some long awaited options in this area.  WPF, however, has made layout a first class citizen from the beginning.

      There is quite a variety of layout options to choose from.  I can only cover a few here, so be sure to look in the SDK for things that inherit from “panel” in order to see more of what is available.  Let’s begin with an example:

<StackPanel>

   <TextBlock>My UI</TextBlock>

   <ListBox>

      <ListBoxItem>Item 1</ListBoxItem>

      <ListBoxItem>Item 2</ListBoxItem>

   </ListBox>

   <RichTextBox/>

</StackPanel>

A StackPanel layout.

StackPanel is one of the simplest layout options available.  It does exactly what its name implies: stack elements, either vertically or horizontally.  Vertical is the default, but you can specify horizontal by setting the ‘Orientation’ property approriately:

<StackPanel Orientation="Horizontal">

Most layouts will require more advanced functionality.  A typical application will likely use DockPanel as its root layout element:

<DockPanel>

   <TextBlock DockPanel.Dock="Top">My UI</TextBlock>

   <ListBox DockPanel.Dock="Right">

      <ListBoxItem>Item 1</ListBoxItem>

      <ListBoxItem>Item 2</ListBoxItem>

   </ListBox>

   <RichTextBox/>

</DockPanel>

A DockPanel layout. 

DockPanel allows you to ‘dock’ elements to the top, bottom, left or right of the container.  The last element will, by default, fill the remaining space.  This Xaml sample presents a new markup construct that I intentionally did not discuss in the previous article: attached properties.  Notice that both ‘TextBlock’ and ‘ListBox’ have a ‘DockPanel.Dock’ attribute on them.  If you examine these classes, you will find that neither has a property that looks like this.  What you will find is that DockPanel declares a DependencyProperty called ‘DockProperty.’  This special type of DependencyProperty, called an ‘Attached Property’, allows a parent control to store information with its children (We don’t have time to get into details on DependencyProperties.  For a great discussion, see Charles Petzold’s book).  In this case, the DockPanel is storing information it needs for layout with its child controls.  In Xaml this manifests itself as an attribute on the child element in the form: ParentName.AttachedPropertyName.  Let’s look at another example of this syntax used by Grid:

<Grid>

   <Grid.RowDefinitions>

      <RowDefinition Height="*"/>

      <RowDefinition Height="3*"/>

   </Grid.RowDefinitions>

   <Grid.ColumnDefinitions>

      <ColumnDefinition/>

      <ColumnDefinition/>

   </Grid.ColumnDefinitions>

   <TextBlock Grid.ColumnSpan="2">My UI</TextBlock>

   <ListBox Grid.Row="1" Grid.Column="0">

      <ListBoxItem>Item 1</ListBoxItem>

      <ListBoxItem>Item 2</ListBoxItem>

   </ListBox>

   <RichTextBox Grid.Row="1" Grid.Column="1"/>

</Grid>

A Grid layout.  

 

Grid is perhaps the most common layout option and it is the most complex that we have looked at.  First, notice that inside of Grid, we have to declare our rows and columns.  In this grid we have two of each.  I have used a grid specific height notation for the rows.  In this case I have said “split the space such that the second row takes up three times as much as the first row.”  Because I have not declared a width on the columns, the space will be split evenly between the two.  Once I have declared the grid’s structure, I use attached properties to place my controls in the appropriate location.  This is mostly self explanatory except for the first child (TextBlock), which is missing column and row specifications.  The markup works because the grid will default its location to column and row zero.

      In a real world application, your layouts are likely to be formed by using various combinations of layout controls nested one in the other.  Try to avoid hard coding widths and heights on elements.  Let the controls do the work for you, adapting your UI to fit the available space.  With a little practice, you’ll begin to realize the flexibility of WPF’s layout system.  There are quite a lot of layout options.  Below is a list of other common layout panels that we don’t have time to look at markup for:

1.       Canvas:  Positions child elements exactly according to top and left coordinates (relative to the container).

2.       WrapPanel:  Similar to stack panel, but wraps elements to the next line when it cannot fit them.

3.       GroupBox:  Groups elements in a titled bounding box.

4.       Viewport:  Scales its child to fit the available space.

5.       Border:  Wraps its child in a border.

      In addition to these out of the box options, you can always inherit from panel and create your own.  If you search the web, you will find several examples of this.  One great resource is: Kevin’s Bag-O-Tricks.  He has a couple of custom panels to learn from as well as some good examples of how to build other custom controls.  You should also know that there are ‘Margin’ and/or ‘Padding’ properties available on most elements for fine grained control of layout.  With a little research you will find properties such as ‘VerticalAlignment’ and ‘HorizontalAlignment’, among others, that make WPF’s layout mechanism quite flexible and able to handle real world application needs.

NEXT POST: WPF Databinding


Posted 10-09-2006 7:10 AM by Rob Eisenberg
Filed under: , ,

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)