我正在尝试绘制一个包含多个系列的图表。它的数据来自数据库,通过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();
我得到一个看起来像这样的绘制图形,我已经通过图表的属性窗格添加了系列;
但我希望输出看起来像这样;
我尝试过谷歌而没有成功。有人可以帮我这个吗? 我非常感激。 感谢
答案 0 :(得分:1)
最明显的问题是关于x值的数据类型。
所有X值在内部都是double
类型。
<强>简介强>
DataPoints
数字,则会按预期处理和存储DataPoints
DateTime
X值,它们也会转换为双精度(通过OLE自动化日期转换)但是如果添加无法转换为数字的类型(如字符串),事情会变得奇怪。 内部 X值均为0
,因为除了标签显示字符串外,还有什么其他内容。
显示的DataPoints
被视为具有0,1,2,3的X值......并且这些点以良好且相等的间距显示。
许多新手看起来很好,他们从来不知道他们有效地<强>丢失了 X值。
当尝试使用数字格式或尝试使用X值计算时出现问题。
您的问题
你的“问题”是你的select
提供了来自DATEPART
功能的整数,所以你做对了,事实上你做得太好了,无法解决这个问题。
听起来很完美而且 ..
..但Chart
尝试使用Auto
设置显示多个项目,而通常工作正常,此处他们没有,因为他们尝试启动图表在x = 0
,当然2014-2016
的三个实际值被挤到右边,无法识别。
解决方案很简单:将显示最小值设置为:
chart1.ChartAreas["ChartArea1"].AxisX.Minimum = 2014;
一切都很好。您可能希望从Points
中的x值计算该值,而且,您可以,因为您拥有它们。
这是最好的方法,只要你的系列具有有意义的X值数字。
不幸的是,第二个系列似乎没有......
丑陋的替代方案是将年份转换为字符串,但是,除非你真的必须这样做,否则不要这样做!
修复了缩放问题后,您的代码的另一个大问题变得可见:
您的数据映射错误。
比较数据表和所需的输出,您的数据绑定根本不会映射到这样的图表。
解决方案:您应该将数据拆分为与reasons
一样多的单独来源,即您要Series
进行绑定。
我会为每个DataViews
创建一个单独的reason
,每个DataTable
基于相同的Filter
,但具有不同的DataView
(reason ='reason1'..)和然后将每个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
都以相同方式绑定,所有multiDexEnabled true
都会显示,缩放也是固定的。