Page view counter

Silverlight Toolkit WrapPanel


The Silverlight Toolkit includes a couple new panels, one of which is the incredibly handy WrapPanel.

[ Updated Jan. 4 to include working example ] 

In its most straight forward use, the WrapPanel allows you to add UIElements which it positions sequentially (typically left to right) until there is insufficient space, at which time it creates a new row beneath the most recent; that is, it wraps.

Creating a simple test program reveals a few interesting aspects about the wrap panel. To do this, open Visual Studio and create a new Silverlight Application. Be sure to add a reference to the Microsoft Windows Controls.dll that came with the Toolkit (the trick is remembering where you've put them!)

AddRefToMicrosoftWindowsControls

You'll also need to create a namespace at the top of Page.xaml, but Intellisence is prepared to be of some assistance,

AddNameSpace

That done, my sample program creates a wrap panel with a single button in it; here's the complete Xaml listing:

<UserControl x:Class="WrapPanel.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:controls="clr-namespace:Microsoft.Windows.Controls;
assembly=Microsoft.Windows.Controls" Width="800" Height="600"> <Grid x:Name="LayoutRoot" Background="White"> <controls:WrapPanel x:Name="WPanel" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Orientation="Horizontal"> <Button x:Name="Add" Content="Add!" FontFamily="Georgia" FontSize="24" Width="Auto" Height="Auto" Background="#FF0000FF" Margin="5" /> </controls:WrapPanel> </Grid> </UserControl>

 

The goal of the code that supports this page is that when the user clicks on the add button one of four controls is randomly chosen, created and added to the panel. 

using System;
using System.Windows;
using System.Windows.Controls;

namespace WrapPanel
{
  public partial class Page : UserControl
  {
    private Random rand = new Random();

    public Page()
    {
      InitializeComponent();
      Add.Click += new RoutedEventHandler( Add_Click );

    }

To support that goal, a private member variable of type Random is added as is an event handler for the "Add" button that was created in the Xaml.

All the interesting work happens in the event handler. If you start by creating controls all of the same size,

 void Add_Click( object sender, RoutedEventArgs e )
 {
   Button b = new Button();
   b.Content = DateTime.Now.ToLocalTime().ToString();
   b.Width = 120;
   b.Height = 35;
   b.Margin = new Thickness( 5 );
   this.WPanel.Children.Add( b );
}

you get a very uniform appearance as each control is added until there is not enough room and then a new row is begun. (in the example shown I've made the control somewhat smaller and the Add button the same size as the buttons I'm creating):

UnifromSizes

If,  instead, you create different objects, then different things begin to happen. In the next example I'll create one of four types of objects

void Add_Click( object sender, RoutedEventArgs e )
{
  int choice = rand.Next( 0, 4 );
  Control c;
  switch ( choice )
  {
    case 0:
      // make a button
    case 1:
      // make a text box
    case 2:
      // make a short list
    case 3:
    default:
     // make a password control
  }

 // set the font size
 // set the width and height and margin
 // add the control to the wrap panel
  
}

A few interesting questions arise. What if I set their font size randomly and what if I set the height to auto (you do this programmatically by setting it to the value double.Nan).

void Add_Click( object sender, RoutedEventArgs e )
{
  /*
  Button b = new Button();
  b.Content = DateTime.Now.ToLocalTime().ToString();
  b.Width = 120;
  b.Height = 35;
  b.Margin = new Thickness( 5 );
  this.WPanel.Children.Add( b );
  */

  
  int choice = rand.Next( 0, 4 );
  Control c;
  switch ( choice )
  {
    case 0:
      Button b = new Button();
      b.Content = DateTime.Now.ToLocalTime().ToString();
      c = b;
      break;
    case 1:
      TextBox t = new TextBox();
      t.Text = rand.Next(0,int.MaxValue-1).ToString();
      c = t;
      break;
    case 2:
      ItemsControl i = new ItemsControl();
      i.Items.Add( "Cormac McCarthy" );
      i.Items.Add( "Neal Stephenson" );
      i.Items.Add( "Marcel Proust" );
      i.Items.Add( "Virginia Woolfe" );
      c = i;
      break;
    case 3:
    default:
      PasswordBox p = new PasswordBox();
      p.Height = 35;
      p.Password = "Secret";
      c = p;
      break;
  }

  c.FontSize = rand.Next( 6, 18 );
  if ( c is ItemsControl )
  {
    c.FontSize = Math.Max( c.FontSize, 10 );
  }
  c.Width = Double.NaN;
  c.Height = Double.NaN;
  c.Margin = new System.Windows.Thickness( 5 );
  
  this.WPanel.Children.Add( c );
 
}

AutoSizedWrapPanel

I find the results interesting, though not necessarily what I want.  One approach is to fix the height of the buttons, which gives another, also interesting effect. A quick way to try this is to make a small code modification:

if ( c is ItemsControl )
{
  c.FontSize = rand.Next( 8, 18 );
  c.Height = Double.NaN;
  //c.FontSize = Math.Max( c.FontSize, 10 );
}
else
{
  c.FontSize = 12;
  c.Height = 30;
}

This causes the other controls not to resize but to center on the larger list.

CenteredOnList

By using panels within panels, you can of course get just about any effect you like.

(I've not posted the source code because it's all here)

Here is a working example in an iframe:

 

 

Previous  The Wrap Panel


This work is licensed under a Creative Commons Attribution By license.
Published Friday, January 02, 2009 9:31 PM by jesseliberty
Filed under: , ,

Comments

# The Wrap Panel

The Silverlight Toolkit includes a wrap panel that allows you to add elements to it and will automatically

Friday, January 02, 2009 9:53 PM by Jesse Liberty - Silverlight Geek

# Silverlight Cream for January 02, 2009 -- #474

In this issue: Jesse Liberty, Terence Tsang, Hannes Preishuber, Tim Heuer, and Damon Payne. Shoutouts

Saturday, January 03, 2009 12:46 AM by Community Blogs

# Dew Drop - January 3, 2009 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop - January 3, 2009 | Alvin Ashcraft's Morning Dew

Saturday, January 03, 2009 3:58 PM by Dew Drop - January 3, 2009 | Alvin Ashcraft's Morning Dew

# re: Silverlight Toolkit WrapPanel

Button links now. Thanks.

Saturday, January 03, 2009 10:23 PM by jesseliberty

# Silverlight Travel &raquo; Silverlight Toolkit WrapPanel

Pingback from  Silverlight Travel &raquo; Silverlight Toolkit WrapPanel

Monday, January 05, 2009 11:29 AM by Silverlight Travel » Silverlight Toolkit WrapPanel

# re: Silverlight Toolkit WrapPanel

Jesse,

FYI, your posts are really hard to read on Outlook and I imagine than in most RSS Readers. I suggest you tro follow Jeff Wilcox tip:

www.jeff.wilcox.name/.../blog-syntax

or

www.manoli.net/csharpformat

Sunday, January 11, 2009 4:04 AM by mamadero2