C#中的堆积柱形图

时间:2016-03-02 10:29:01

标签: c# charts stacked-chart

我正在尝试设置我的程序,以便用户可以显示堆积的柱形图,显示每个部门中显示的拒绝类别的数量(例如,5显示在部门1中,3显示在部门2中,等等) 。我已经在网上浏览了一下并自己解决了这个问题,但我似乎无法让它发挥作用。如果有人能够提供帮助那就太棒了。

当用户按下按钮切换到堆积柱形图时,图表当前的作用是什么: Stacked Column Chart

代码:

pair*

1 个答案:

答案 0 :(得分:5)

创建堆积图表很简单。即使您拥有正确的数据。

创建堆积图很难。即使您没有合适的数据。

要遵循以下规则:所有系列中的数据都必须对齐才能使堆叠正常工作!

这听起来很简单,但实际上比人们想象的要复杂得多。

在我们开始之前的几个例子之前,简单规则的细节分解为:

  • 规则#1 您需要在每个系列中都有一个数据点,以获得任何系列中的每个 x值。**

  • 规则#2 您的积分需要采用正确的顺序,即x值递增

  • 规则#3为了让您控制要显示的点数范围和图表的其他方面,所有x值应为数字

有关堆积图表的工作示例,请查看this post!那里的问题是'如何避免差距?' 但它真的归结为'如何使堆叠工作正常?'

请注意,该示例使用来自以代码编写的DataSource的数据。从正在进行的数据库中读取它没有什么不同。

解决方案是添加虚拟点以填补空白。

这将是您的一个问题,因为您无法预期查询中的数据是完整的。

要解决此问题,您可以将查询更改为填补空白的某些join,或让图表帮助您。

我不会进入SQL选项,虽然它似乎是最自然的选项。但请注意,为了遵循规则#2,您需要在查询中添加order子句,以便在任何情况下按x值对记录进行排序,即通过拒绝类别。

让我们看看一个名为Chart.DataManipulator.InsertEmptyPoints的有趣辅助函数:

这个功能有几个重载;我们将使用包含我们想要对齐的所有系列名称的字符串。这不仅会添加缺失点,而且实际上会将它们插入缺失的位置,因此我们现在可以通过规则#1& 2!

在进入更多细节之前(是的,更多细节,叹息,但只是有很多东西要做对..)让我们看看规则#3:

这适用于所有图表类型,并且图表控件的一个规则用户最常打破,通常甚至没有注意到..:

所有X值都应为数字!

如果您添加字符串,那么这些字符串将填充到轴标签中,否则将被丢弃。最值得注意的是,结果数据点的x值均为0

只要你不需要它们就可以了,但是一旦你这样做,你就会有一个令人讨厌的惊喜。由于它们已经消失,您无法使用它们来计算任何内容,或格式化标签,或显示工具提示等,或使用它们来设置要​​显示的范围。

请注意,即使x值都是0,数据点仍然沿x轴展开;你再也不能控制它......

所以你需要决定一些方案来把你的x值变成数字!

一种是设置一个数据结构,其中列出了所有值:

 List<string> catLookup = new List<string>() { "ARTEFACT", "et..cetc.."};

然后您可以找到这样的每个值:

 int found = catLookup.FindIndex(x => x == someValueWeSearch);

这样可行,但如果您的应用程序是真实的,它应该能够与数据一起增长;所以你应该从数据库中读取所有可能的值。如果设备正确,则已经有一个查找表可供使用,使用其密钥将是最自然的选择。

如果不是,您仍然可以通过简单的查询读取值:

Select distinct reject_category from tblReject_test order by reject_category;

现在让我们进行调整,以对齐我们拥有的所有系列:

  string seriesNames = String.Join(",", seriesLookup.Keys);
  chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Number, seriesNames);

现在回到原始代码以及您需要做的事情:

首先,你的所有值都是字符串。所以你应该把你的循环变成这样的东西:

while (reader.Read())
{
    string seriesName = reader[1].ToString();
    int seriesIndex   = seriesLookup.FindIndex(x => x == seriesName);
    string catName    = reader[2].ToString();
    int catIndex      = catLookup.FindIndex(x => x == catName);

    charRejections.Series[seriesName ].Points.AddXY(catIndex, 
                                              Convert.ToInt16((reader["reject"]));
}

您会注意到我不仅插入了辅助变量,使调试变得更加容易,而且还有第二次查找来保存创建系列所需的部门并将点添加到各自的系列中。

我留给你创造这个;如果找不到类别或部门,还要添加必要的检查..

相关问题