ALLINSIGHT

Home of the AlmostImplementedException

WPF: How to extend the Shape-Class to draw a pie chart or a part of a circle

It is very easy to extend controls in WPF, but only with code behind you can do the real cool stuff. When you search the internet for code to draw a part of a circle, you will get alot of crappy code. Some try to do it with XAML-Code but can’t calculate the needed values there (which means they only can draw one specific circle-piece) and the others try it with 100 lines of code.
Today I will show you an easy and extendible way. First we will start to extend the Shape-Class. I use Shape because of the UI-Features it has, later on I want to provide some interactivity. If you don’t need that, just use Geometry. Both can be found in System.Windows.Media.
Shape is slower then Geometry, because of the UI overhead. More details are comming soon in a separate post.

When you extends Shape you have to implement a getter for DefiningGeometry as showed below. At first we’ll just return an empty StreamGeometry

This code is already useable in WPF but do nothing.

Now we define a few properties we’ll need.
For a start we need coordinates for the centre of the circle, the radius, the angle of the pie we want to draw and last but not least the rotation angle of a pie. This way we can draw any part of a circle, which means multiple pies of a circle a.k.a Pie-Chart.

It is important to define getter and setter to use the properties in XAML.

But now to the interesting part. To create a pie we have to draw a line, an arc and fill the area with a color. For this we write a new method called DrawGeometry.
The first few lines of code calculate the needed values to draw the line and arc. startPoint is the center of the circle and the startpoint of our line, outerArcStartPoint is the end of the line and the startingpoint for the arc. And finaly outerArcEndPoint is the end of the arc.
The last 3 lines do the actual trick. With BeginFigur we define the startpoint and with LineTo we draw the first line. ArcTo draws the arc of the circle. We don’t need a line back to the starting point, the shape-class do that for us. Thats all we need.

As you may have noticed, there is a helper-function called ComputeCartesianCoordinate. This function just calculates the x and y coordinates we need.
To use this new code we have to change the DefiningGeometry getter to call DrawGeometry and do some extra stuff to improve the performance.

Now the final touch. Set the fill-color and a border-color.

Thats all we need to draw a pie or a pie-chart. And here is an example how to use the Pie-class

This XAML-Code draws 2 Pies with different angles and the second one rotated by 90°. Thats all we need to draw our own pie-chart. Just calculate the angle of all pieces (12.8% = 360° / 100 * 12.8). The rotation is the added value of all angles before the current pie.
Certainly we want to change the color of a pie to draw a nicer chart. But our Pie-class already can do that (because of the Shape extension). Just set Fill in the XAML-Code: Fill="Aquamarine".

Conclusion
It is very easy to extend Shape or Geometry to draw custom shapes and its the best way to implement things you want to reuse.
To use this example in a productive environment we have to add alot more features. Currently you can’t change a value after it is set, because the Pie don’t update the UI when we set a property. Expect this and a little more (animations and nicer colors) in one of my next posts.

Here is the complete Pie-class.

Share : Share on TwitterShare on FacebookShare on GooglePlusShare on PinterestShare on Linkedin

, , ,

One thought on “WPF: How to extend the Shape-Class to draw a pie chart or a part of a circle

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Share on TwitterShare on FacebookShare on GooglePlusShare on PinterestShare on Linkedin