Tuesday, November 18, 2008

WPF Back to Basics - Panels

Something I am noticing amongst my WPF peers is limited knowledge of the layout tools available to us in WPF. Most of us come from a Win Forms or ASP.NET background to relate to a few concepts:

  1. Absolute positioning
  2. Table positioning

I have very limited experience in Win Forms programming but all the stuff I have done with has been absolute positioning eg this control is x pixels from the Left/Right and y pixels from Top/Bottom. In my ASP.NET career I have seen plenty of way to create layout from everyone's first love; tables, to frames, IFrames, Lists and divs (remember Layers anyone?).

Well WPF really brings a lot more to the table than that lot of layout options. Remember that HTML has kinda evolved to being what it is with CSS tacked on to help layout. It originally was a markup language for describing content not really for fancy presentation. WPF however was built ground up for fancy presentation.

Lets look at some of the layout options we have available to us out of the box and when each would be useful:

Grid

The grid is similar to a Table in HTML, similar but not the same. In a grid you specify how many rows and columns the grid will have. You then set an attached property on each of the child elements specifying which row and column (zero based index) it belongs to. Failure to do so will default in the value of 0 being assumed meaning it will displayed in the first row/column.

Grid also has the interesting feature that allows you to stack things in a z index. For example if you specify two things to appear in the same cell then the elements are piled on top of each other with the last element specified being on top. This can be useful in some scenarios, but generally is a mistake when a dev forgets to specify the correct column and row attached properties

When to use Grid?

I find that the Grid has been most useful to me when I need to display a form to fill in. Generally I have a Label in column 0, the field in column 1 and maybe a validation message in column 3. It also offers star notation for its column and row size values which can be nice for dynamic resizing of layouts.

Canvas

Canvas is a similar to absolute positioning in HTML/CSS. You just provide Left/Right and Top/Bottom coordinates. There are no boundaries so you provide any kind of values eg negative or very large. I find the canvas the least useful panel for the work I do. However it is showcased very nicely in the FamilyShow application by Vertigo.

When to use Canvas?

I would use canvas if I wanted to throw stuff on to a conceptual whiteboard or desktop. This would be great where the user could just drag things around and not have to be constrained by a less organic structure like a grid.

StackPanel

StackPanel is one of the simplest but best tools in your layout panel arsenal. It simply stacks its children one after the other in the orientation you specify. The  Orientation options are Horizontal and Vertical (the default). In a web world this would be like just placing a bunch of items in successive black elements (div tags). If we set the orientation to Horizontal then it would more similar to using span tag except in WPF the StackPanel will not wrap when it runs out of room. Also note that the StackPanel will take up as much room as it needs, but never any more room than it needs, so don't use StackPanel where you want a fill effect.

When to use the StackPanel?

Everywhere! ;-) I find that the StackPanel is great for Templates where I may want to stack a Header, a summary and a description for example. There are also useful when bundling text blocks together quickly where you may want "X by Y pixels" you can stack horizontally four text blocks of which two are bound to Width and Height properties.

WrapPanel

The WrapPanel is the answer when the StackPanel has scrolled of the edge of the screen because it has taken too much room. As I pointed out above the StackPanel will also take the space it needs, the WrapPanel however will respect one dimension and wrap to a new line of controls when it runs out of room in that dimension.

When to use the WrapPanel?

My favourite use of the WrapPanel is to replace an ItemPanelTemplate for an ItemsPanel property in an ItemsControl. Sorry if that makes very little sense. Lets provide some background; when you use an ItemsControl (or one of its inherited controls like ListBox, ListView, Selector etc) by default all of the Items it displays are just display one after the other in a vertical direction. That is because the implementation uses a StackPanel do do its dirty work. However by changing the ItemPanelTemplate we can have it use a WrapPanel instead. So? Well this is really sweet for when we want to display things like Thumbnail pictures. When we use the WrapPanel we get an effect like in Windows Explorer when you view images within a folder as thumbnails which displays images left to right and then when there is no more space it wraps to the next line and continues showing the images. If there are too many images for the page then a vertical scroll bar will be displayed.

DockPanel

DockPanel is one of the un-sung hero's of WPF layout. The general idea behind the DockPanel is that the control will fill the area it is given, and then allow its children to "dock" themselves to one of it's four sides (Left, Right, Top and Bottom). DockPanel uses a first-in-first-served notion. If I have a DockPanel and the first child of the DockPanel wants to dock to the right, it will take up as much horizontal space as it requests and 100% of the height of the DockPanel. If the next child wanted to dock to the Bottom then It would recieve as much vertical space that it needed and the remaining horizontal space left from the first child. Generally the last child is provided the remaining available space.

When to use the DockPanel?

The DockPanel is an underused panel in my experience. Many complex implementations using Grids with fixed column and row widths and then an Auto sized column and row in the middle for content should have used a DockPanel. I would imagine a large majority of applications now have a toolbar at the top, a status bar at the bottom, some menu system down the left and/or right side. This common layout just screams DockPanel.

 

Other notable mentions...

While this post is mainly about panels, the intention is to uncover the possibilities before you by having a better knowledge of WPF, because of that I think it is worth talking about some other controls that could be useful.

TabControl

Now I bet the first thing you will think is "I know what a tab control is...next.", but stop for just a second. With the power of WPF and it's lookless control sub-system I have seen some talented WPF people put together crazy solutions together where a stylised TabControl would have been fine. Essentially the TabControl is a Selector of headered controls. Select one Head and its contents show.

When to use the TabControl?

When ever you have a piece of functionality that has a set of buttons that stay visible, but pressing on one of them shows a view and hides another view, please consider tab control. An example that many could relate to would be the buttons down the left side of Outlook. When you select the Mail Button, the Mail Button is displayed as selected and the Mail content shows. Now this doesn't look like a normal TabControl but the effect is the same.

Viewbox

I thought I might make mention of this funky control. The Viewbox gives this cool scale effect that most would only associate with the Image control. As with an Image control that allows a Stretch property to be set so that it can scale out to fill the space it has been provided, the Viewbox can wrap another control to provide the same feature. Very cool.

When to use the Viewbox?

Use the view box when you want a control to always be completely visible and scale to the space it has been provided.

Toolbar / ToolbarTray

Toolbar is one of those useful controls to use to give common functionality to your application. Many Microsoft application have a toolbar in them. Visual Studio is a very good example of ToolbarTray and Toolbar usage. VS has an area defined that can house ToolBars. The user can choose which toolbars to show and hide and can even drag them around to change the order they are displayed. You get this for free if you use the ToolbarTray and add Toolbars to it.

When to use the ToolbarTray and Toolbar?

Use the ToolbarTray and the ToolBar controls to get similar functionality to Visual Studios toolbar features. Users feel comfortable with controls the already know and you will have less code to write. remeber you can always change the styles to jazz it up if you need.

Ribbon

The Microsoft Ribbon is now available. I have not played with it myself yet but there are videos from PDC that demo how you can code against the current release. Watch this space...

1 comment:

Lee Campbell said...

Mark Berry has a quick demo of various panels on windowsclient.net. Good for beginners.