从数据表绘制图表
我正在尝试绘制一个包含多个系列的图表。 它的数据来自数据库,通过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; }
这给了我以下输出;
当我尝试将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
提供DATEPART
function的整数,所以你做得对,事实上你做得太好了,无法解决这个问题。
它听起来很完美,它是 ..
..然而, 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
显示和缩放都是固定的。