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.

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in z Silverlight Archives. Bookmark the permalink.