Specialized Layout Panels for Silverlight

An overview of some layout panels in Silverlight.FX: XGrid, FormPanel, HStackPanel, VStackPanel and TilePanel - specialized for simplifying layout of a few mainline app scenarios.

The layout system in Silverlight is, in my opinion, one of the key differentiators in presentation engine capabilities from HTML/CSS (on a related note, see my post long ago about my browser/scripting wish list and the references to need for core layout primitives).

The Silverlight platform provides a set of out-of-the-box layouts like Grid, so you don't have to simulate them with low-level absolute positioning, and float/clear css attributes. However, beyond that, you can build your own first class layouts, and in this post I'll discuss the handful of layout panels that I've written for Silverlight.FX, that I've found useful in application building.

Layout Panels Class Hierarchy

Silverlight.FX currently has five layout panels: TilePanel, HStackPanel, VStackPanel (which derive from a base AnimatedPanel), XGrid, and FormPanel. It also has something called TemplatePanel, but I'll discuss that in a separate post, as it does a bit more than layout. I wanted to share a bit of information about the current set of panels, their scenarios and the motivation for them.

XGrid
XGrid derives from Grid, and is there to simply make it easier to specify the rows and columns. Instead of a Grid where you have to write several lines of XAML just to define a set of RowDefinitions and ColumnDefinitions (anyone who has used Grid knows what I am talking about), you can simply write the following XAML:

<fxui:XGrid Columns="20,*,5,350,20" Rows="20,40,*,5,250,20">
  <Image Source="/Themes/StoreLogo.png" Grid.Column="1" Grid.Row="1"
    Margin="0,4,0,4" VerticalAlignment="Center" HorizontalAlignment="Left" /> 
  ...
</fxui:XGrid>

The layout functionality is identical. Personally I believe this is easier to type in and more importantly easier to read and focus on the contents of the Grid, rather than the row/column structure of the Grid (both of which I think are valuable). In all my app building I've been able to completely switch to XGrid, except for once where I had to specify minimum width. I think the native Grid is just fine for those exceptional scenarios.


FormPanel
Grid (and XGrid) are all-powerful, and very general purpose. However, they're not optimized for laying out forms (labels, textboxes etc.). You have to position each control in a specific Grid cell, and you have to specify margins and alignment on each control. Essentially you're mixing a lot of layout details into the content of the Grid, and reducing that would be nice. Secondly the sheer number of Grid.Row/Column/RowSpan/ColumnSpan, Margin, and HorizontalAlignment, VerticalAlignment attributes takes over and makes it harder to see the more meaningful attributes on your Grid's chidren.

This led to FormPanel. This panel intrinsically understands the notion of Labels and associated controls, as well as heuristics to line them and stack them vertically, separated with appropriate margins and alignment. For example, here is a form I have in one of my apps and the associated XAML.

FormPanel screenshot

<fxui:FormPanel Width="400" Height="400">
  <fxui:Label Text="Title:" />
  <TextBox Text="{Binding Project.Title}"
    IsReadOnly="True" />
 
  <fxui:Label Text="Keywords:" />
  <TextBox Text="{Binding Project.Keywords}" />
  <TextBlock Style="{StaticResource deEmphasizedText}"
    Text="Individual words separated by spaces" />
 
  <TextBlock fxui:FormPanel.IsLabeled="False"
   Text="The project summary should ... paragraph."
   TextWrapping="Wrap" />
 
  <fxui:Label Text="Summary:" />
  <TextBox Text="{Binding Project.Summary}" />
  <fxui:Label Text="Description:"
    fxui:FormPanel.LabelPosition="Top" />
  <TextBox Text="{Binding Project.Description}"
    Height="120" />
</fxui:FormPanel>

I personally like my XAML to be minimal and communicative of actual intent and behavior, rather than appear complicated as a result of a bunch of layout information mixed in. FormPanel derives from Grid, so it doesn't actually need to replicate a ton of layout logic. It inherits all that which keeps size and complexity minimal.

FormPanel interprets Label controls as Labels, and the next control in the collection as its associated control. It provides some attached properties that can be specified on its children to control the layout such as relative positioning of the label, and whether elements span the full width of the container if they don't have a corresponding Label... that sort of thing. The best way to check these out are to look at the doc-comments with the API in class browser.


HStackPanel, VStackPanel
I got tired of having to specify the Orientation property on StackPanel all too often. Beyond that, I really dislike specifying alignments and margins on the children of StackPanel to get reasonable looking UI where controls are correctly aligned and spaced apart, since its mixing layout into content, and that makes it harder to switch layout at a future date.

<fxui:HStackPanel
  ChildFlow="Right" ChildAlignment="Center" ChildSpacing="4">
  <TextBlock Text="Quantity:" />
  <TextBox x:Name="quantityTextBox" Text="1"
    Width="50" Height="23" />
  <Button Width="75" Height="23"
    Content="Add to Cart" />
</fxui:HStackPanel>

HStackPanel screenshot

Both HStackPanel and VStackPanel derive from AnimatedPanel, which is a base class in Silverlight.FX that makes it simple to create animated layouts if that is desirable for the scenario. The app developer simply needs to turn on animation, and the specific layout panel does not have to deal with the details of animating children, starting/stopping animation, interpolation, easing etc.


TilePanel
TilePanel doesn't exactly fall into the general forms scenarios, but it is nice for showing a set of items that are equally distributed in a tiling fashion.

For example, I can use a TilePanel within an ItemsControl as follows:

TilePanel screenshot

<ItemsControl ItemsSource="{Binding Products}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <fxui:TilePanel TileHeight="200" TileWidth="200"
        UseAnimatedLayout="True" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <app:Product />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

To see the layout live in action, check out either Silverlight Store or Flickr Tiles. Basically each child, a tile, is equally sized and is arranged from left to right and top to bottom. This panel also derives from AnimatedPanel, and as such tiles can be animated and eased into the position as the size of the panel changes, or the tiles get re-ordered or added/removed into the UI.


If you're interested in using AnimatedPanel to build a custom panel, or want to see how any of these work under the covers, you can check them out by downloading the sources for Silverlight.FX.

I have a handful of other panels I'd like to add to the framework over time, but I really would like to hear what do you think? What other layout scenarios do you think are interesting for mainline form layout scenarios, where you think a specialized layout panel would help much more than a general Grid? And beyond that, what other layout panels do you think would be most interesting for adding nice visual touches and flair to an application's UX?


[ Tags: | | | ]
Posted on Friday, 3/6/2009 @ 9:40 PM | #Silverlight


Comments

16 comments have been posted.

Jelen

Posted on 3/6/2009 @ 11:00 PM
Thank you for your work at Silverlight.fx - I will blog it soon. Have a nice day.

ahmed

Posted on 3/6/2009 @ 11:18 PM
that's really awesome, i think these controls should be added to the default installation of silverlight, is there any plans ?

Joe Audette

Posted on 3/7/2009 @ 3:56 AM
This is really great stuff. It fills in some gaps and makes it more intuitive to do layout.
Many Thanks!

Jared

Posted on 3/7/2009 @ 9:36 AM
Nikhil, I created an AnimatedWrapPanel that integrates nicely with your Silverlight.FX Framework. Email me and I can get it to you.

Miguel de Icaza

Posted on 3/8/2009 @ 9:24 AM
Hello Nikhil,

The thing that makes CSS unique is that it is easy to separate the style from the content.

On CSS you build with divs and classes, and you use CSS to place things on the screen.

With Silverlight this is not possible, the content is mixed with the style. Silverlight layout is closer to the HTML-like table layout where people had to put things inside tables (grids, stack panels are merely variations on tables). It seems to me that most people are happy moving away from having to specify the container (table or Silverlight container control).

Nikhil Kothari

Posted on 3/8/2009 @ 11:12 AM
Hi Miguel,
You can use resource dictionaries and they come close to style sheets, and provide some separation of style from content. With SL3 they get a bit better... though I know there are some things that css really excels at, esp. having multiple styles combine to affect the same element, and selectors as a way of matching elements to style rules.

I think things like look and feel (colors, brushes, fonts, effects, control templates) are prime candidates for what goes into a style sheet/resource dictionary. I am not so sure about layout. I've seen simple pages, and they were fine, but the moment you have something more complex, separating layout causes more maintainability issues, and gets in the way of understanding, esp. if you've got one person who put it together and another person who has to pick it up. Saw the same thing happen when we were exploring some stock app templates for Silverlight.

As an aside there was (in the Avalon days), a thought to have a <Panel Layout="Grid"> type of approach. However, apparently users liked having more concrete layout containers... hence the system we have today <Grid>... though I could certainly see how one could in fact build <GenericPanel> and use attached properties to affect layout, and then perhaps specify layout choice externally in a style...

Anyway, great to hear from you.

Nirmal J. Shah

Posted on 3/8/2009 @ 7:52 PM
Nice article. Thanks Nikhil. Silverlight.FX is great initiative!

Santiago Palladino

Posted on 3/9/2009 @ 4:50 AM
Hey Nikhil,

It's a great job you've done with this library. Just one comment about the XGrid: if its only difference with grid is the way of specifying its rows and cols, then why not just defining a new auxiliary attached property for grids, that uses your syntax and applies the rows and cols to the target grid?

That way, you would not need to change all grids for XGrids, and you may just write:

<Grid fxui:XColumns="20,*,5,350,20" fxui:XRows="20,40,*,5,250,20">
<Image Source="/Themes/StoreLogo.png" Grid.Column="1" Grid.Row="1"
Margin="0,4,0,4" VerticalAlignment="Center" HorizontalAlignment="Left" />
...
</Grid>

Peter O'Toole

Posted on 3/9/2009 @ 7:19 AM
Regarding Miguel's point -- CSS is excellent for specifying fonts, colors, etc. But I think you find more and more that people who were afraid to speak up to the CSS zealot are finally coming out and admitting how difficult css-positioning is. Positioning even simple columnar layouts is extremely frustrating. What HTML desperately needs is what you already find in XUL or Silverlight, namely HBox, VBox, a less annoying table ( like Grid ), and I guess it already has a wrapping container by default.

That said, I *really* wish Silverlight would make specifying fonts and colors and such as easy as it is with CSS, especially the actual cascading effect and ability to target elements by selectors. I like how Flex takes the approach of using the CSS specification, even if it is for a different set of properties than HTML specifies.

--Pete

Mike

Posted on 3/9/2009 @ 8:12 AM
Are these usable in WPF too?

mike

Posted on 3/9/2009 @ 1:21 PM
@Peter O'Toole

No, CSS needs no such thing. It is designed to style documents, HTML is meant to create documents as well. This is completely different from UI. It would be like saying that Silverlight grids are difficult to create a magazine layout with. True, because it's not meant for that.

Use Flex, Silverlight or something like ExtJS to create your application (layouts).

Nikhil Kothari

Posted on 3/9/2009 @ 6:14 PM
@Santiago - you're absolutely right. XGrid could have been done with a couple of attached properties. Honestly I didn't think about it. In reality, I used to call XGrid as Grid, so I could keep using the same tag name. However in the interest of keeping things less confusing for those using Silverlight.FX beyond me, I gave it a new name... with the X prefix - there are other controls with the X prefix as well. Anyway, thats how this ended up being a new derived Panel.

@Peter - I do wish we had a CSS syntax (though the folks working on WPF didn't choose that some years back) ... what can I say ... other than it might be interesting to build a light-weight mini-CSS engine in an extension on top of Silverlight.FX using the behavior system.

@Mike - I haven't tried using Silverlight.FX in WPF; I suspect some of it works, and some of it might not...

Ben Hayat

Posted on 3/20/2009 @ 9:32 AM
Hi Nikhil;

Are you planning to port the FX library to SL3 any time soon?

Thanks!
..Ben

Nikhil Kothari

Posted on 3/20/2009 @ 10:00 PM
@Ben - there are a couple of small things I want to do for SL2, and then freeze that, and quickly move to SL3 asap - there are some key things in SL3 around the Application object, that will help Silverlight.FX ... and also have some other ideas around using the new capabilities.

Elite Teuton

Posted on 5/25/2009 @ 8:15 AM
Hi Nikhil,

Great Work!.
I am trying out to build a custom panel as I figured out the panel provided by SLight will not be of much help to me. I wan to achieve a UI which look similar to :
http://netfxlive.com/designer/ . Can you guide me to any link which will tell me how to build a custom panes. Found lots of tutorials on Custom Control but nothing on custom panels. Any suggestions are welcome.

- Cheers
Elite Teuton

Elite Teuton

Posted on 5/25/2009 @ 8:33 AM
Hi Nikhil,

Great Work!.
I am trying out to build a custom panel as I figured out the panel provided by SLight will not be of much help to me. I wan to achieve a UI which look similar to :
http://netfxlive.com/designer/ . Can you guide me to any link which will tell me how to build a custom panes. Found lots of tutorials on Custom Control but nothing on custom panels. Any suggestions are welcome.

- Cheers
Elite Teuton
Post your comment and continue the discussion.