Introduction
My idea was to create a control that can generate three-dimensional pie chart controls. I found several other controls on CodeProject, but none of them let me specify inclination, rotation, thickness, radius, and surface brightness and transparency. Additionally, many were lacking event-driven hooks, such as events which fire on items being clicked or mouse focus changing. Furthermore, none of them were written in the style of a standard Windows Forms control, e.g., the ListView
control with an Items
collection for storing ListViewItem
s. So, I set out to write a control that would offer these features, along with an easily extensible interface.
Background
As a basis for my PieChart
, I relied heavily on the look-and-feel of the pie chart control written by Julijan Sribar. In addition to the features offered by his control, the PieChart
allows you to specify the inclination of the pie in the plane, as well as whether or not the radius is auto-sized or fixed. As a further aide to designing with this control, the Items
collection of the PieChart
is editable at design time in Visual Studio.
Using the code
The control is structured much like a standard Windows Forms control, in terms of use. The PieChart
itself contains an Items
property, which is of type PieChart.ItemCollection
. This collection stores objects of type PieChartItem
. Each PieChartItem
is comprised of the Text
, ToolTipText
, Color
, Offset
, and Weight
properties. To create and use the control, use the Windows Forms designer in Visual Studio to add a PieChart
to a form. Then, you can use the control as easily as this:
PieChart pieControl = new PieChart();
pieControl.Items.Add(new PieChartItem(10,
Color.Red, "Text", "ToolTipText"));
pieControl.Items.Add(new PieChartItem(5,
Color.Blue, "Blue", "BlueTips"));
pieControl.AutoSizePie = true;
pieControl.TextDisplayMode =
PieChart.TextDisplayTypes.FitOnly;
The control defines special styles for normal items and focused items. An item becomes focused when the mouse moves over the control. The default item styles can be set using the ItemStyle
property, while the focused item styles can be set with the FocusedItemStyle
property. Below are the styles allowed for items.
SurfaceAlphaTransparency
A floating-point value between 0 and 1 that is multiplied by the item's color's alpha channel to determine the item's transparency.
SurfaceBrightnessFactor
A floating-point value between -1 and 1 that modifies the item's surface brightness. Positive values increase the brightness (with 1 increasing the brightness to white), while negative values decrease the brightness (with -1 causing black).
EdgeBrightnessFactor
A floating-point value between -1 and 1 that modifies the item's edge brightness using the same algorithm as the SurfaceBrightnessFactor
.
You may want to define custom actions when a property changes or when the state of the control is modified. Below is a list of the additional events that are fired by the control.
ItemClicked
ItemFocusChanging
ItemFocusChanged
AutoSizePieChanged
RadiusChanged
InclinationChanged
RotationChanged
ThicknessChanged
ShowEdgesChanged
TextDisplayModeChanged
ShowToolTipsChanged
Printing and Saving
You can use the control to print and save charts. In the demo, the File->Save menu allows you to save the chart as a PNG, JPEG, GIF, or BMP. The image will have all of the same properties as the control, and will be sized to fit the chart using the Padding
, Radius
, and AutoSizePie
properties of the PieChart
. However, you can specify different sizes in the code if you like. Also, the control can print your chart using a PrintDocument
. Simply register the PrintDocument
with the PieChart
using the PieChart.AttachPrintDocument
method, and then invoke the PrintDocument.Print
method to initiate the printing. Note: I do not have access to a printer, and have only tested printing to the Microsoft Office Document Image virtual printer. Please alert me to any printing bugs.
Points of Interest
I personally find it annoying when a control attempts to redraw itself constantly while editing items in a loop. For example, you might write a loop that iterates through your items and changes the text of all of the items.
foreach (PieChartItem item in PieChart1.Items)
{
item.Text = item.Weight.ToString();
}
Since changing the Text
property of a PieChartItem
causes the control to be redrawn, the control will redraw once for every item. To avoid this kind of a problem, I created the functions BeginModification
and EndModification
. Each time BeginModification
is called, a counter is incremented; and each time EndModification
is called, the counter is decremented. As long as the counter is greater than 0, changes to the control will not cause the control to refresh. Upon calling EndModification
the final time, the control will refresh if it has been structurally or visually modified. Note that calling BeginModification
without a corresponding call to EndModification
will cause the control to never redraw! Therefore, you should put the call to EndModification
in the finally
block of a try
-catch
block. The following code modifies the loop so that it does not redraw for every item:
try
{
PieChart1.BeginModification();
foreach (PieChartItem item in PieChart1.Items)
{
item.Text = item.Weight.ToString();
}
}
finally
{
PieChart1.EndModification();
}
History
- Revision 0: Original version.
- Revision 1: Added support for printing, saving, and changing the control's padding.