65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义蜘蛛网图或雷达图控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (21投票s)

2012年8月25日

CPOL

4分钟阅读

viewsIcon

70491

downloadIcon

2664

一个易于使用的 WPF 蜘蛛(雷达)图控件。

引言

虽然我在网上找到了许多免费的图表组件,但我需要一个简单的蜘蛛图或雷达图控件。如果您不知道什么是雷达图,以下是维基百科对它们的解释:“雷达图是一种图形化方法,用于以二维图表的形式显示多变量数据,其中三个或更多定量变量从同一点开始的轴上表示。轴的相对位置和角度通常不具信息意义。

由于这是WPF应用程序的一部分,我真的不想使用任何嵌入的Flash图表或使用WinForms的图表。由于这次Google未能帮助我,我决定自己动手做一个。

让我们从最终结果开始,这样您就可以决定是否值得继续阅读。

Example of how the WPF spider or radar chart.

Using the Code

使用此图表非常简单。只需引用WpfCharts程序集,然后在您的XAML代码中,您可以这样使用它:

<WpfCharts:SpiderChart Title="Spider chart"  
                       Lines="{Binding Lines}" 
                       Axis="{Binding Axes}" 
                       Minimum="0" 
                       Maximum="1" 
                       Ticks="5" 
                       ShowLegend="True" 
                       LegendLocation="BottomRight" 
                       LegendBackgroundColor="Aquamarine"/> 

那么,这些依赖属性是什么意思?

  • Title:如果您连这个属性的作用都猜不到,我听说他们正在招聘服务员。
  • Lines:一个可观察的集合(如果您想动态添加线,否则列表也可以)ChartLine对象。一个ChartLine对象包含有关要使用的颜色和数据点的信息。
  • Axis:您在每个轴(辐条)末端看到的标签。显然,应该有多少个轴就应该有多少个图表线中的点(每个辐条一个点)。实际上,您至少需要三个轴才能创建雷达图。
  • 沿轴的MinimumMaximum值。在我的例子中,所有轴都有相同的范围,所以只有一个最小值和最大值。
  • Ticks表示您希望有多少条虚线(刻度线)。
  • ShowLegendLegendLocationLegendBackgroundColor也应该很清楚。

请注意,您只能动态添加线,但不能添加轴(辐条)。

作为ChartLine的示例,请参见下面的示例,其中线的名称、线和填充颜色将在图例中重用。

var chartLine = new ChartLine {
    LineColor = Colors.Red,
    FillColor = Color.FromArgb(128, 255, 0, 0),
    LineThickness = 2,
    PointDataSource = new[] { 0.1, 0.2, 0.3, 0.21, 0.6, 0.28, 0.97 },
    Name = "Chart 1"
} 

关注点

我通常会尽量避免创建WPF自定义控件,因为重新样式化现有控件要容易得多。然而,在这种情况下,我没有看到一个简单的出路,所以让我简要解释一下我的进展。

我从一个空白解决方案开始,添加了一个WPF自定义控件项目(WpfCharts)和一个WPF应用程序(TestSpiderChart),该应用程序引用了WpfCharts。WPF自定义控件项目总是包含一个UserControl1类,我立即删除了它,以及在Themes\Generic.xaml文件中对它的样式引用。在WpfCharts中,我添加了一个新的自定义控件(WPF),名为SpiderChart,它会自动在Generic.xaml中添加一个ControlTemplate(描述控件的外观和感觉)。

蜘蛛图的主要组成部分是中心辐射布局。很容易找到RadialPanel的示例,它可以将所有子元素排列成一个圆形。我使用了Jobi Joy的Jobi Joy的示例,但如果您需要一个,也可以看看Jeow Li Huan更高级的版本Jeow Li Huan,它修复了几个边缘情况,并且基于Charles Petzold的。

RadialPanel重命名为SpiderChartPanel后,我添加了几个依赖属性(DP)来设置Minimum、Maximum、Ticks和Lines。顺便说一句,Dr. WPF发布了一套广泛的代码片段。输入dp并按Tab键即可查看可用DP的概览。我在SpiderChart类中添加了相同的DP以及更多DP,并更新了Generic.xaml中的控件模板以使用它们。

如果您查看代码,您会发现大部分代码都非常直观。雷达图的实际绘制(带有辐条的背景、刻度线和线条)是通过重写SpiderChartPanel中的OnRender方法来完成的。Axis标签绑定到SpiderChartPanelItemsSource DP,因此我们可以使用Generic.xaml中的ItemTemplate来设置样式和绘制它们。

但是,我遇到了两个小问题:首先,我注意到SpiderChartPanel中的OnRender方法只被调用一次,在子集合设置之前(因此没有绘制任何内容)。因此,我在MeasureOverride中添加了一个对InvalidateVisual()的调用,这样OnRender就可以在子集合设置后被调用。我很确定这不是最佳实践,我尝试使用DP的FrameworkPropertyMetadata选项之一(AffectsRender)来实现这一点,但徒劳无功。有人有什么建议吗?

另一个问题是我希望能够动态添加Lines。如果Lines绑定到ItemsSource DP,那么这将开箱即用,但在这种情况下,PanelItemsSource已经被Axis标签占用了。因此,我需要创建一个第二个DP,它充当图表线的ItemsSource。这实际上非常简单,如您在此处所见,事件处理程序只需要再次调用OnRender来重绘控件。您可以通过单击“添加行”按钮来查看它。

// Add handler in case the Lines collection implements INotifyCollectionChanged
var newValueINotifyCollectionChanged = (e.NewValue as IEnumerable) as INotifyCollectionChanged;
if (newValueINotifyCollectionChanged != null)
	newValueINotifyCollectionChanged.CollectionChanged += target.LinesCollectionChanged;

就这样,各位。编码愉快!

历史

  • 2012年8月25日:文章v1提交
© . All rights reserved.