Confessions of a .NET Developer!

Create a Custom Panel in WPF – Part II

So in our previous post we explained the basics of creating our own custom panel. In this post i will implement those basics.

So i will create an AlternatePanel. Here the items of the Panel will be shown in an alternate way vertically.
Like, first item will be aligned to the left, the second will be aligned to the right, the third to left etc.

Here is the class :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace MakeNewPanel
{
    public class AlternatePanel:Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            Double cHeight = 0.0;
            Double cWidth = 0.0;
            Double secondMax = 0.0;
          
            foreach (UIElement child in this.Children)
            {
                child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
                if (child.DesiredSize.Width > cWidth)
                {
                    secondMax = cWidth;
                    cWidth = child.DesiredSize.Width;
                }            
                cHeight += child.DesiredSize.Height;
            }

            if (Double.IsPositiveInfinity(availableSize.Width))
            {
                return new Size(cWidth + secondMax, cHeight);
            }
            else
            {
                return new Size(availableSize.Width, cHeight);
            }
        }

Above is the code for MeasureOverride. What i am trying to achieve here is that, i will calculate the total height of the children and calculate the sum of maximum and the second maximum width of the child. This total height and width will be used to define the size of the panel.

protected override Size ArrangeOverride(Size finalSize)
        {
            Boolean isRight = false;

            Double x = 0.0;
            Double y = 0.0;

            foreach (UIElement child in this.Children)
            {
                if (isRight == false)
                {
                    Rect rec = new Rect(new Point(0, y+1), child.DesiredSize);
                    child.Arrange(rec);
                    isRight = true;
                }
                else
                {
                    Rect rec = new Rect(new Point(x, y+1), child.DesiredSize);
                    child.Arrange(rec);
                    isRight = false;
                }
                y += child.DesiredSize.Height;    //Positions y points down from the top
                x = child.DesiredSize.Width;       //Gets the previous child's width
            }
            return finalSize;
        }
    }
}

This shows the ArrangeOverride function which was a bit tricky. The first child will be aligned to left and the next child to the right. The right alignment is given to the child from the left + previous child’s width.

The positioning of the Rectangles is done by providing the Point(x,y) with respect to the Panel and the Child.DesiredSize as the width and height of the Child.
I have added an extra 1 to the y point of child to give a small space between the top and below children while arranging the items.

Like shown below:
Arrange items

Here is the XAML that i am using :
XAML :

As you can see, i have used a ListBox with my custom panel as ItemsPanel. You can add images instead of items. But this will not be fast and UI may hang because its not a VirtualizingPanel. For loading thousands of images, you should use a VirtualizingStackPanel. I am currently trying to create a custom panel called VirtualizingWrapPanel but its very difficult to implement one. Microsoft has not provided a VirtualizingWrapPanel. Here is an excellent blog which implements VirtualizingPanel written way back in early 2006!
VirtualizingTilePanel

That’s It!!
This was a simple example of creating a custom panel. Likewise you can create your own panel which can like arrange the items diagonally or change my code to arrange the items alternatively in a horizontal fashion.

Here is the project :
(I will try to upload the project file once i know how to do it!! :P)

Just remove the extension “.doc” .

Here are a few links which have their own implementation of Panel.

An Animated WrapPanel

Hope you enjoyed it! Happy coding! 🙂

Advertisements

February 21, 2011 - Posted by | WPF

1 Comment »

  1. nice article

    Comment by vikram | November 25, 2014 | Reply


Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: