Silverlight Custom Panels Part I : Ellipse Panel

This is the first part of a multi-part panel series. One of the areas that I was so impressed with WPF and Silverlight was the power of the layout system. An element’s layout is truly decoupled from the visual rendering of elements and as WPF/Silverlight developers we wield full control over that through something called a Panel.

A panel is responsible for two things. First, determining size through measurement and second, determining positioning through arrangement. These are exposed through methods called MeasureOverride and ArrangeOverride and are available when you inherit from the Panel class.

Below is an Arrange Override method that I wrote for an Ellipse Panel. Things to note are that I have some properties defined on my Panel that I am using. HorizontalScalar and VerticalScalar for the Width and Height of my Ellipse. Funny names, miainly because a Panel, as a UIElement already has a Width and Height, so to avoid confusion, there you go.

        protected override Size ArrangeOverride(Size finalSize)
        {
            Size returnSize = base.ArrangeOverride(finalSize);
            double count = 1;
            if(this.Children.Count != 0) 
            {
                count = Children.Count;
            }
            double angleIncrement = 360 / count;
            for (int i = 0; i < this.Children.Count; i++)
            {
                double centerX = (returnSize.Width / 2) - (CalculateAverageItemWidth() / 2);
                double centerY = (returnSize.Height / 2) - (CalculateAverageItemHeight() / 2);
                
                double angleDeg = -90 + i * angleIncrement;
                double angle = angleDeg * (Math.PI / 180.0);
                UIElement element = this.Children[i] as UIElement;
                
                double x = centerX + HorizontalScalar * Math.Cos(angle);
                double y = centerY + VerticalScalar * Math.Sin(angle);

                Rect r = new Rect(x, y, element.DesiredSize.Width, element.DesiredSize.Height);

                element.Arrange(r);

            }
            return returnSize;
        }

ellipse1

Positioning, that’s great. What’s next?

So is that it, right? Well not really. We can also inject some interesting effects on our elements by applying render transformations on them. Since we already have a nice autonomous bit of presentation logic this seems like the appropriate place to add affects like that. In my ellipse panel, I added a property that will basically change the rotation of elements to be facing up and down vs. relative outward.

double rotateAngle = 0;
if (AllowItemRotation)
{
    rotateAngle = ItemRotationOffset + angleDeg;
}

System.Windows.Media.RotateTransform tran = new System.Windows.Media.RotateTransform();
tran.Angle = rotateAngle;
element.RenderTransform = tran;
element.RenderTransformOrigin = new Point(0.5, 0.5);

 

ellipse2

As you can see now we have a much more non-desktop feel. We have effectively made this panel useful in both Vertically oriented displays and horizontally oriented displays (such as the Microsoft Surface). Now that is versatility!

One thought on “Silverlight Custom Panels Part I : Ellipse Panel

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