C# 结合条形图和点图
我遇到了一个小问题,我想创建一个如下所示的图表:C# 结合条形图和点图,c#,charts,bar-chart,series,C#,Charts,Bar Chart,Series,我遇到了一个小问题,我想创建一个如下所示的图表: aSeries["DrawSideBySide"] = "false"; aSeries.SetCustomProperty("DrawSideBySide", "false"); 所以基本上 系列1=标准条形图。如果在“时间最大值”(系列2)系列2之前结束,则显示绿色=系列1项目顶部的数据点/标记 我正在努力解决这个问题 我的代码: chart_TimeChart.Series.Clear(); strin
aSeries["DrawSideBySide"] = "false";
aSeries.SetCustomProperty("DrawSideBySide", "false");
所以基本上
系列1=标准条形图。如果在“时间最大值”(系列2)系列2之前结束,则显示绿色=系列1项目顶部的数据点/标记
我正在努力解决这个问题
我的代码:
chart_TimeChart.Series.Clear();
string series_timeneeded = "Time Needed";
chart_TimeChart.Series.Add(series_timeneeded);
chart_TimeChart.Series[series_timeneeded]["PixelPointWidth"] = "5";
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Size = 10;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = true;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Enabled = true;
chart_TimeChart.Series[series_timeneeded].BorderWidth = 2;
chart_TimeChart.Series[series_timeneeded].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_timeneeded].YValueType = ChartValueType.Time;
chart_TimeChart.ChartAreas[0].AxisY.LabelStyle.Format = "HH:mm:ss";
chart_TimeChart.Series[series_timeneeded].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
chart_TimeChart.Series[series_timeneeded].Points.AddXY("item"+ " " + (i + 1).ToString(), DateTime.Now.Add(Timespans[i]));
}
chart_TimeChart.Series.Add(series_FinishTime);
chart_TimeChart.Series[series_FinishTime].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_FinishTime].BorderWidth = 0;
chart_TimeChart.Series[series_FinishTime].MarkerSize = 15;
chart_TimeChart.Series[series_FinishTime].MarkerStyle = MarkerStyle.Square;
chart_TimeChart.Series[series_FinishTime].MarkerColor = Color.Black;
chart_TimeChart.Series[series_FinishTime].YValueType = ChartValueType.DateTime;
chart_TimeChart.Series[series_FinishTime].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
DateTime YPosition = GetFinishTime(i);
chart_TimeChart.Series[series_FinishTime].Points.AddXY("item"+ " " +(i+1).ToString(), YPosition);
}
代码将显示为:
但我希望它看起来像这样:
aSeries["DrawSideBySide"] = "false";
aSeries.SetCustomProperty("DrawSideBySide", "false");
!!请参阅下面的更新强>
如果确实要创建堆叠条形图,则图表有两个问题:
- 如果要堆叠数据点,它们需要有有意义的x值;如果没有它们,它怎么知道彼此要叠加什么呢
DataPoint.XValue
字段是double
,当您向其中添加string
时,它被设置为0
!!您的字符串将复制到标签
,但在其他情况下会丢失
因此,您需要为x值提供合适的数值
- 您还需要对要堆叠的序列进行分组。为此,有一个名为
的特殊属性,用于对应堆叠的序列进行分组StackedGroupName
yourSeries1.SetCustomProperty("StackedGroupName", "Group1");
有关完整示例,请参见
它还显示了一种使用您选择的字符串值设置标签的方法
这是制作真正的StackedBar
图表的方法。您的变通方法可能有效,也可能无效。您可以尝试使颜色透明或与图表的底色相等;但在我看来,这只不过是一次黑客攻击
更新 我想我误解了这个问题。从我看到的情况来看,您并不是真的想要创建堆叠图表 相反,你要努力解决这些问题:
- 在同一y点显示条形图
- 让一些酒吧隐形
- 将垂直线显示为标记
- 一些列类型包括所有
,条
,然后一些列具有一个鲜为人知的特殊属性列
Auto
,其工作方式类似于True
。这通常是很好的,因为我们不希望条形图相互重叠,从而有效地隐藏所有或部分重叠点
但这里我们确实希望它们共享相同的y位置,因此我们需要为至少一个系列
将属性设置为false
;其他(在Auto
上)将跟随..:
您可以这样做:
aSeries["DrawSideBySide"] = "false";
aSeries.SetCustomProperty("DrawSideBySide", "false");
或者像这样:
aSeries["DrawSideBySide"] = "false";
aSeries.SetCustomProperty("DrawSideBySide", "false");
- 接下来,我们隐藏覆盖的
;这很简单:系列
- 最后一个问题是显示线标记。没有这样的样式,所以我们需要使用自定义样式。为此,我们需要创建一个合适的位图,并将其添加到图表的
集合中Images
MarkerImage
不会被缩放,因此我们需要在调整图表大小或添加/删除点时创建合适的大小。我暂时不考虑这个复杂问题
int pointCount = 10;
Bitmap bmp = new Bitmap(2, chart.ClientSize.Height / pointCount - 5);
using (Graphics g = Graphics.FromImage(bmp)) g.Clear(Color.Black);
NamedImage marker = new NamedImage("marker", bmp);
chart.Images.Clear(); // quick & dirty
chart.Images.Add(marker);
结果如下:
请注意:
- 我建议对重复引用的所有图表元素使用变量,而不是一直使用索引引用。代码更少,更易于阅读,更易于维护,而且性能可能更好
- 由于代码要求可见数据点为红色或绿色,
将不会显示良好的表示。有关绘制多色图例项的示例,请参见图例
- 我使用图表高度;不建议这样做,因为可能有
或标题
或更多图例
;相反,您应该使用图表区
图表区域的高度,或者更精确地说,使用
内部绘图位置的高度。您需要将这些从百分比转换为像素。不要太用力,请看下面或下面 或者更多的例子
- 标记应根据
以及可能来自调整大小
事件进行调整。将它放在一个好的函数中调用(例如,AxisViewChanged
)总是一个好主意void setMarkerImage(图表、系列s、字符串名称、整数宽度、颜色c)
- 如果需要反复调整标记图像的大小,可能需要编写更好的代码来清除旧标记图像;这应该包括处理以前使用的
位图
var oldni = chart.Images.FindByName("marker");
if (oldni != null)
{
oldni.Image.Dispose();
chart.Images.Remove(oldni);
oldni.Dispose();
}
- 在某些情况下,需要轻推图表以更新其某些属性
就是这样一种轻推RecreacteAxesCale
ChartArea ca = chart.ChartAreas[0];
ca.RecalculateAxesScale();
float cah = ca.Position.Height;
float iph = ca.InnerPlotPosition.Height;
float h = chart3.ClientSize.Height * cah / 100f * iph / 100f;
int mh = (int)(h / s.Points.Count);
- 最后一点:原始答案强调了使用有意义的x值的重要性。弦是无用的!这对于堆放钢筋非常重要;但现在,当我们希望酒吧坐在相同的垂直位置时,这同样重要!将x值添加为字符串再次导致无意义
(因为我们有
条
x值沿纵轴移动,反之亦然。)顺便说一句。我尝试了“chart\u TimeChart.Series[Series\u FinishTime][“PixelPointWidth”]”0"; 但显然这不起作用,因为我无法将宽度设置为零。请查看更新后的答案。我一开始误解了你的问题,对不起!您仍然将charttype设置为stackedbars。我不认为这是你真正想要的。您仍然可以将x值添加为字符串。不过,你需要数字。你需要想出一个方案,使用简单的数字将点分组到各自的插槽中。您好,很抱歉