在开发应用程序时,经常需要展示数据的分布情况,饼图是一种直观且常用的数据可视化方式。然而,现有的饼图控件往往不能满足所有需求,例如倾斜角度、旋转、厚度、半径和表面亮度透明度的自定义设置。此外,很多控件缺乏事件驱动的钩子,例如点击事件或鼠标焦点变化事件。为了解决这些问题,决定开发一个全新的饼图控件,它不仅具备上述特性,还提供了易于扩展的接口。
在开发这个饼图控件时,参考了Julijan Sribar编写的饼图控件的外观和感觉。除了他控件提供的功能外,饼图控件还允许用户指定饼图在平面上的倾斜角度,以及半径是自动调整还是固定。为了便于设计,饼图控件的Items集合可以在Visual Studio的设计时编辑。
这个控件的使用方式类似于标准的Windows Forms控件。饼图控件本身包含一个Items属性,该属性的类型是PieChart.ItemCollection。这个集合存储了PieChartItem类型的对象。每个PieChartItem由Text、ToolTipText、Color、Offset和Weight属性组成。要在Visual Studio的Windows Forms设计器中添加饼图控件到窗体,然后可以像下面这样轻松使用控件:
C# PieChart pieControl = new PieChart();
// 添加一个权重为10,颜色为红色,文本为"Text",提示文本为"ToolTipText"的项
pieControl.Items.Add(new PieChartItem(10, Color.Red, "Text", "ToolTipText"));
// 添加另一个权重为5,颜色为蓝色,文本为"Blue",提示文本为"BlueTips",偏移量为25像素的项
pieControl.Items.Add(new PieChartItem(5, Color.Blue, "Blue", "BlueTips", 25));
// 设置控件自动适应饼图
pieControl.AutoSizePie = true;
// 设置控件仅在文本适合其切片内时显示文本
pieControl.TextDisplayMode = PieChart.TextDisplayTypes.FitOnly;
控件定义了普通项和焦点项的特殊样式。当鼠标移动到控件上时,一个项就会变成焦点。可以使用ItemStyle属性设置默认项样式,使用FocusedItemStyle属性设置焦点项样式。以下是允许为项设置的样式:
可能想要在属性更改或控件状态修改时定义自定义操作。以下是控件触发的附加事件列表:
可以使用控件来打印和保存图表。在演示中,文件->保存菜单允许将图表保存为PNG、JPEG、GIF或BMP格式。图像将具有与控件相同的所有属性,并使用PieChart的Padding、Radius和AutoSizePie属性来适应图表的大小。当然,也可以在代码中指定不同的大小。此外,控件可以使用PrintDocument打印图表。只需使用PieChart.AttachPrintDocument方法将PrintDocument注册到PieChart,然后调用PrintDocument.Print方法即可开始打印。
注意:没有打印机访问权限,并且只测试了打印到Microsoft Office Document Image虚拟打印机。如果有任何打印问题,请告知。
个人发现,当在循环中编辑项目时,控件不断尝试重绘自己是非常烦人的。例如,可能会编写一个循环,遍历项目并更改所有项目的文本。
C# foreach (PieChartItem item in PieChart1.Items)
{
item.Text = item.Weight.ToString();
}
由于更改PieChartItem的Text属性会导致控件重绘,控件将为每个项目重绘一次。为了避免这种问题,创建了BeginModification和EndModification函数。每次调用BeginModification时,计数器会增加;每次调用EndModification时,计数器会减少。只要计数器大于0,对控件的更改就不会导致控件刷新。在最后一次调用EndModification时,如果控件在结构上或视觉上被修改,控件将刷新。请注意,如果没有相应的EndModification调用,BeginModification将导致控件永远不会重绘!因此,应该在try-catch块的finally块中调用EndModification。以下代码修改了循环,使其不会为每个项目重绘:
C# try
{
PieChart1.BeginModification();
foreach (PieChartItem item in PieChart1.Items)
{
item.Text = item.Weight.ToString();
}
}
finally
{
PieChart1.EndModification();
}