Click here to Skip to main content
11,483,983 members (67,013 online)
Click here to Skip to main content

WrapPanel for Silverlight 2.0

, 6 Mar 2008 CPOL 76.2K 977 27
Rate this:
Please Sign up or sign in to vote.
A simple example of a custom panel using Silverlight 2.0.

Introduction

One of the most exciting features of Silverlight 2.0 (beta 1) is the ability to create custom panels - just like WPF! Silverlight 2.0 (beta 1) comes with three panels: Canvas, Grid, and StackPanel. Many people will miss other popular panels already included with WPF. This article shows how to build a simple WrapPanel using the extensibility features available with Silverlight 2.0.

Background

A custom panel in Silverlight (and WPF) contains two important parts: Measure and Arrange. This is a two-pass recursive system. The first round measures the size of all children in the panel. In a recursive manner, all children in turn measure the size of their children, and so on. In the next round, the children of the panel are arranged using whatever algorithm you like.

For a complete description of building a custom panel, see this MSDN article.

Using the code

The first important aspect of the custom WrapPanel is to inherit from Panel. Panel is an abstract class from which all panels must derive. The Orientation dependency property determines whether WrapPanel flows vertically or horizontally.

public class WrapPanel : Panel
{

  public Orientation Orientation
  { 
    get { return (Orientation)GetValue(OrientationProperty); }
    set { SetValue(OrientationProperty, value); }
   }

   public static readonly DependencyProperty OrientationProperty =
     DependencyProperty.Register("Orientation", 
     typeof(Orientation), typeof(WrapPanel), null);

 public WrapPanel()
 {
   // default orientation
   Orientation = Orientation.Horizontal;
 }

Next, we must override the Measure function. The input parameter 'availableableSize' to MeasureOverride tells the panel how much size it has to work with. This size is given to the panel by its parent. The most important aspect in measuring each child is to indicate to each child their allowed size. In this simple example, we are just saying to each child that they can have the whole space of the panel. The result of the measuring yields a 'DesiredSize' for each child - this desired size will be used when arranging the children.

protected override Size MeasureOverride(Size availableSize)
{
  foreach (UIElement child in Children)
  {
    child.Measure(new Size(availableSize.Width, availableSize.Height)); 
  }

  return base.MeasureOverride(availableSize);
 }

Finally, we must override the Arrange method. Here, we will position each child in the panel. In our case, we position items either horizontally or vertically. In the horizontal case, we arrange the children (left to right) until the right edge of the panel is reached; then, we move to the next line and continue laying out the children (left to right).

protected override Size ArrangeOverride(Size finalSize)
{
  Point point = new Point(0,0);
  int i = 0;

  if (Orientation == Orientation.Horizontal)
  {
    double largestHeight = 0.0;

    foreach (UIElement child in Children)
    {
      child.Arrange(new Rect(point, new Point(point.X + 
        child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));

      if (child.DesiredSize.Height > largestHeight)
         largestHeight = child.DesiredSize.Height;

      point.X = point.X + child.DesiredSize.Width;

      if ((i + 1) < Children.Count)
      {
        if ((point.X + Children[i + 1].DesiredSize.Width) > finalSize.Width)
        {
           point.X = 0;
           point.Y = point.Y + largestHeight;
           largestHeight = 0.0;
         }
       }
       i++;
     }
    }
    else
    {
       double largestWidth = 0.0;

       foreach (UIElement child in Children)
       {
         child.Arrange(new Rect(point, new Point(point.X + 
           child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));

         if (child.DesiredSize.Width > largestWidth)
           largestWidth = child.DesiredSize.Width;

          point.Y = point.Y + child.DesiredSize.Height;

          if ((i + 1) < Children.Count)
          {
            if ((point.Y + Children[i + 1].DesiredSize.Height) > finalSize.Height)
            {
              point.Y = 0;
              point.X = point.X + largestWidth;
              largestWidth = 0.0;
             }
           }

           i++;
          }
        }

    return base.ArrangeOverride(finalSize);
   }
 }
}

Points of interest

Note, the WrapPanel provided here functions mostly like the WPF WrapPanel. I noticed some minor differences, but have not had time to fix. Feel free to send along your suggested changes.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

lneir
Software Developer (Senior) Skype
United States United States
I work in the Bay Area primarily developing software on the Windows platform using C++, .NET/C#, WPF, and Silverlight.
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 Pin
lewax002-Feb-12 9:36
memberlewax002-Feb-12 9:36 
GeneralGreat silverlight control Pin
Michał Zalewski31-Oct-09 16:25
memberMichał Zalewski31-Oct-09 16:25 
GeneralSilverlightContrib Pin
rob_houweling26-Oct-08 1:11
memberrob_houweling26-Oct-08 1:11 
GeneralRe: SilverlightContrib Pin
lneir26-Oct-08 6:53
memberlneir26-Oct-08 6:53 
QuestionCan I use this code? Pin
Member 295213923-Sep-08 4:47
memberMember 295213923-Sep-08 4:47 
AnswerRe: Can I use this code? Pin
lneir23-Sep-08 7:00
memberlneir23-Sep-08 7:00 
Questionmodified to behave as animating panel Pin
Member 28546833-Jul-08 19:22
memberMember 28546833-Jul-08 19:22 
AnswerRe: modified to behave as animating panel Pin
lneir4-Jul-08 8:33
memberlneir4-Jul-08 8:33 
AnswerRe: modified to behave as animating panel Pin
Ray Guan17-Nov-10 23:59
memberRay Guan17-Nov-10 23:59 
GeneralThanks! Pin
Seth Webster13-Jun-08 17:23
memberSeth Webster13-Jun-08 17:23 
GeneralWrappanel inside another panel Pin
Member 380211822-May-08 8:33
memberMember 380211822-May-08 8:33 
GeneralRe: Wrappanel inside another panel Pin
vRud7-Jun-08 11:01
membervRud7-Jun-08 11:01 
GeneralRe: Wrappanel inside another panel Pin
chris rothery14-Aug-08 3:32
memberchris rothery14-Aug-08 3:32 
GeneralDoesn't work inside ScrollViewer Pin
raulgspan27-Mar-08 16:45
memberraulgspan27-Mar-08 16:45 
GeneralRe: Doesn't work inside ScrollViewer Pin
lneir27-Mar-08 17:05
memberlneir27-Mar-08 17:05 
QuestionRe: Doesn't work inside ScrollViewer Pin
Harlequin66622-Sep-08 6:14
memberHarlequin66622-Sep-08 6:14 
AnswerRe: Doesn't work inside ScrollViewer Pin
Harlequin66622-Sep-08 7:19
memberHarlequin66622-Sep-08 7:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 7 Mar 2008
Article Copyright 2008 by lneir
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid