从数据表绘制图表

我正在尝试绘制一个包含多个系列的图表。 它的数据来自数据库,通过DataAdapter进入DataTable ,就像这样;

 public DataTable deaths_per_reason_per_year(string farmerid) { dt = new DataTable(); try { conn.Open(); // (select formatted to fit SO lines) SqlCommand cmd = new SqlCommand("SELECT DATEPART(yyyy, DeathDate) AS 'Year', Reason, COUNT(DeathID) AS 'Number of Deaths' FROM [Farmstat_V1.0].[dbo].[Death] WHERE FarmerID = '" + farmerid + "' GROUP BY Reason, YEAR(DeathDate);", conn); SqlDataReader reader = cmd.ExecuteReader(); dt.Load(reader); } catch (Exception) { throw; } finally { conn.Close(); } return dt; } 

这给了我以下输出;

带有sql输出的DataTable

当我尝试将DataTable分配给表单上的图表时,用这个;

 StatsDataAccess sda = new StatsDataAccess(); chart1.DataSource = sda.deaths_per_reason_per_year(FarmerID); chart1.Series["Series1"].XValueMember = "Year"; chart1.Series["Series1"].YValueMembers = "Number of Deaths"; chart1.Series["Series2"].XValueMember = "Reason"; chart1.Series["Series2"].YValueMembers = "Number of Deaths"; chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false; chart1.Series["Series1"].IsValueShownAsLabel = true; chart1.DataBind(); 

我得到一个看起来像这样的绘制图形,我已经通过图表的属性窗格添加了系列;

产量

但我想要一个看起来像这样的输出;

实际产出

我试过谷歌没有成功。 有人可以帮我这个吗? 我非常感激。 谢谢

最明显的问题是关于x值的数据类型。

所有X值在内部都是double类型。

介绍

  • 如果在X值中添加带有数字的DataPoints ,则会按预期处理和存储它们
  • 如果使用DateTime X-Values添加DataPoints ,它们也会转换为double(通过OLE自动化日期转换)

但是如果添加无法转换为数字的类型(如字符串),事情会变得奇怪。 在内部 ,X值全部为0 ,因为除了标签显示字符串之外,它们还有什么用。

显示的DataPoints被视为具有0,1,2,3 …的X值,并且这些点以良好且相等的间距显示。

对许多新手而言,这看起来很好,他们从来不知道他们已经有效地失去了X值。

尝试使用数字格式或尝试使用X值计算时出现问题。

你的问题

你的’问题’是你的select提供DATEPARTfunction的整数,所以你做得对,事实上你做得太好了,无法解决这个问题。

它听起来很完美,它是 ..

..然而, Chart试图显示许多具有Auto设置的项目,虽然它们通常正常工作,但在这里他们没有,因为他们试图在x = 0启动图表,当然, 2014-2016的三个实际值被挤压到权利无法承认。

解决方案很简单:将显示最小值设置为:

 chart1.ChartAreas["ChartArea1"].AxisX.Minimum = 2014; 

一切都很好。 您可能想要从您的Points的x值计算该值,而且,您可以,因为您拥有它们。

这是最好的方法,只要您的系列具有有意义的X值数字。

不幸的是,第二个系列似乎并没有……

丑陋的替代方案是将年份转换为字符串,但是,除非你真的必须这样做,否则不要这样做!

解决了扩展问题之后,代码的另一个大问题变得可见:

您的数据映射是错误的。

比较数据表和所需的输出,您的数据绑定根本不会映射到这样的图表。

解决方案:您应该根据reasons将数据拆分为多个单独的源,即您要绑定Series

我会为每个reason创建一个单独的DataViews ,每个DataViews都基于相同的DataTable但使用不同的Filter (reason =’reason1′..),然后将每个DataView绑定到一个Series

在我的头顶,这是它的样子:

 DataTable DT = yourTable; DataView dv1 = new DataView(DT); DataView dv2 = new DataView(DT); .. dv1.RowFilter = "reason=='Sold'"; dv2.RowFilter = "reason=='Other'"; .. yourSeries1.Points.DataBind(dv1, "year", "deathcount", ""); .. 

现在所有Series DataPoints都以相同的方式绑定,所有Series显示和缩放都是固定的。