Confessions of a .NET Developer!

Create a Custom Panel in WPF – Part I

In this post I shall explain how to create a custom panel to suit your needs using WPF.

We have a good set of panels or layouts available like Grid, StackPanel, WrapPanel, DockPanel, Canvas etc.
But sometimes you might feel that its not enough! You may feel like adding your own functionalities such as
arranging your items diagonally. For this, we need to make our own custom panel.

First lets go to the basics:
The Panel class is the class which handles the layout of its children.
The items of the Panel are basically arranged in the layout as rectangles. Basically each child in our panel is an instance of a UIElement. The Panel class stores the children in a UIElementCollection which is a collection class that only has the instances of the UIElements.

To create a custom panel, we need to create a class which inherits the Panel class. Add a namespace
using Systems.Windows.Controls; to inherit Panel. We shall be overriding two functions namely, MeasureOverride and ArrangeOverride which will help us to measure and arrange the children of our Panel.

How it works?
The parent(layout) and its children basically “talk” to each other. First the parent asks its children, how much space do you want? This step is done in the MeasureOverride function.
We shall implement the function like this:

protected override Size MeasureOverride(Size availableSize) 
              foreach(UIElement child in this.Children)
                   child.Measure(new Size(...,...));
              return new Size(...,...);

It really isn’t that simple!! There is more code to be done but this is just the important things to make note
The parameter availableSize is the size that is available to you to layout the children. For example, if you have a Panel of size 100*100 with margin set as 10,10,10,10, then the available size will be 80*80.
But if you have a scrollviewer around the panel, then the availableSize will be with the width and height as Infinity.

Next we are here enumerating over the Children collection and measuring the Size of each Child.
In the measure function you can pass the size that you want considering the want, even passing Infinity or availableSize itself. After this call, the desired size of the child is set which will be useful while arranging the children in the layout.
Note: If you pass Infinity as size in the measure call, the desired size will be its original size that it takes.

Next you can return the overall size of the panel by adding the width and height of the children, but it totally depends on you. Its a bad practice if one returns availableSize from MeasureOverride. For example, if you have a ScrollViewer around your panel or if you plan to use the panel in a ListBox with ScrollViewer.HorizontalScrollBarVisibility and VerticalScrollBarVisibility as “Auto”, then the availableSize will be Infinity and hence you will get an exception like this :
Layout measurement override of element ‘MakeNewPanel.AlternatePanel’ should not return PositiveInfinity as its DesiredSize, even if Infinity is passed in as available size.

It looks something like this :

Protected Override Size ArrangeOverride(Size finalSize)
              foreach(UIElement child in this.Children)
                    child.Arrange(new Rect(...,...));    //there are 6 overloads
              return new Size(...,...);

The parameter finalSize will never be of Size Infinity, and is usually the size of the Panel.
The important part is in the for loop. As i mentioned earlier, each child will be arranged as a rectangle, so basically we will be creating the rectangles and position or rather arrange them in the layout according to the way we want.
The return parameter is of least concern and you can pass finalSize as the parameter.

This is the end of Part I. In the next part I will show you how to implement the above basics to create our own custom panel! Part 2

Thank you for reading!


February 21, 2011 - Posted by | C Sharp, WPF

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: