Tuesday, July 14, 2009

Exercise for Part -1

I think the best thing to do here is, let's say I have some hypothetical layout that I want to achieve. Let's say one of the common layouts, favoured for years where we have a menu bar at the top, followed by a main content area, and a status bar area at the bottom. Let's see a mock up (designed as a simple WinForm) of what we are aiming for:


I think I have given you all the tools you need to carry out designing this sort of layout in WPF. Do you want a hint, I think you will need to use the StackPanel DockPanel Grid controls in order to get the job done.

If you're not sure how to do it. I shall give the XAML here below..

<Window x:Class="WPF_Tour_Beginners_Layout.PuttingItAllTogether"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStartupLocation="CenterScreen"
Title="PuttingItAllTogether" Width="640" Height="480" >

<DockPanel Width="Auto" Height="Auto" LastChildFill="True">

<Menu Width="Auto" Height="20" Background="#FFA9D1F4"
DockPanel.Dock="Top">


<MenuItem Header="File">
<MenuItem Header="Save"/>
<Separator/>
<MenuItem Header="Exit"/>

MenuItem>

<MenuItem Header="Help">

<MenuItem Header="About"/>
MenuItem>
Menu>


<StackPanel Width="Auto" Height="31" Background="#FFCAC5C5"
Orientation="Horizontal" DockPanel.Dock="Bottom">

<Label Width="155" Height="23" Content="Status Bar Message...."
FontFamily="Arial" FontSize="10"/>

StackPanel>


<StackPanel Width="136" Height="Auto" Background="White">

<Button Margin="5,5,5,5" Width="Auto" Height="26" Content="button1"/>
<Button Width="126" Height="26" Content="button2" Margin="5,5,5,5"/>
<Button Width="126" Height="26" Content="button3" Margin="5,5,5,5"/>

StackPanel>


<Grid Width="Auto" Height="Auto" Background="#FFCC9393">

<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>

Grid.ColumnDefinitions>

<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>

Grid.RowDefinitions>

<Rectangle Fill="Aqua" Margin="10,10,10,10" Grid.Row="0" Grid.Column="0"/>
<Rectangle Fill="Aqua" Margin="10,10,10,10" Grid.Row="0" Grid.Column="1"/>
<Rectangle Fill="Aqua" Margin="10,10,10,10" Grid.Row="1" Grid.Column="0"/>
<Rectangle Fill="Aqua" Margin="10,10,10,10" Grid.Row="1" Grid.Column="1"/>

Grid>

DockPanel>
Window>

There are a couple of tricks here, namely the following:

  • The Grid for the right hand content area, must be the last child declared in order for it to take up the remaining space that the parent DockPanel wants to fill, due to the LastChildFill="True"
  • The StackPanel used for the status bar, must be before any other child that is declared as being DockPanel.Dock="Left" or DockPanel.Dock="Right". As if there was another element before the status bar StackPanel, the status bar StackPanel would not be able to span the entire width available, as this space would have been stolen by any child that was DockPanel.Dock="Left" or DockPanel.Dock="Right". Try it, you'll see what I mean. Simply move the status bar XAML further down in the XAML file, say to the end.

Performance Considerations

As some panels can be bound to items (this will be discussed further in the DataBinding article) there may be occasions where the number of children elements displayed in a panel is quite large. For example, if a StackPanel contains a ListBox that is bound to a large database query. This would be lots of items, OK in this case it's the ListBox that will have lots of children. However, internally, the ListBox control uses a Vertical StackPanel to render its items by default. Mmmm, that's not so great.

However all is not that bad, WPF has one further trick up its sleeve to aid in this situation. We can use the dependency/attached property VirtualizingStackPanel.IsVirtualizing on a ListBox, which means that the ListBox controls internal StackPanel to render its items, will now be virtualized. But what the heck is a vitualizingStackPanel?

When a panel is virtualized, it means that only the visible elements are created. The rest aren't displayed. For example, creating a listbox displaying images bound to a database holding 100,000 rows. This would take a long time for the listbox to load. If you use a virtualize panel, then only the visible images will get created in the UI. When you scroll down, the currently visible items will get destroyed, and the new visible items will get loaded onto the UI. There is only one panel that supports virtualization and it is the VirtualizingStackPanel. If you need to create any new virtualized panels, you will have to write your own.


I suppose, I hope by now you have the basics of layout in WPF.

No comments:

Post a Comment

Please leave your comments here to improve myself!