I have a requirement to create line chart graphs that involve data from several sources, and I need to identify the sources in the x-axis legend (see the attached image for an example)
How would I achieve this effect with your graphing tools?
Hi Richard,
The easiest way to accomplish this is probably to combine the data sources together and plot one line. An alternative approach could be to set up each source as a separate series, and plot them each at a different location.
Please try this out and let me know if you need any further explanation.
To clarify, I am populating the grid with a NumberSeries object.
How can I use a NumberSeries object to achieve this effect?
OK had a few questions let tackle them the best I can:
My only remaining issue is how I can compress the vertical space between the bottom of the chart and the bottom title line. I am not 100% what you are referring to, my guess though is just adjusting your Bounds would get the behavior you are looking for, but from a later post sounds like you figured this one out.
I want the top and bottom cyan lines to be dotted or dashed, but regardless which LineDrawStyle I use, the lines always appear as solid. Why?
I am not sure what you are doing different in your live app, but in the one you just attached earlier, you pass in the same line style for each line. Doing a modification of that to create a new linestyle and pass that in for the different lines, and it worked fine.
LineStyle lineStyle1 = new LineStyle(LineCapStyle.NoAnchor, LineCapStyle.NoAnchor, LineDrawStyle.Solid); LineStyle lineStyle2 = new LineStyle(LineCapStyle.NoAnchor, LineCapStyle.NoAnchor, LineDrawStyle.DashDot);
NumericSeries min = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle2, 3, System.Drawing.Color.Red); NumericSeries max = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle2, 3, System.Drawing.Color.Red); NumericSeries avg = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle1, 1, System.Drawing.Color.Cyan); NumericSeries avgPlus = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle1, 1, System.Drawing.Color.Cyan); NumericSeries avgMinus = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle1, 1, System.Drawing.Color.Cyan); NumericSeries value = InfragisticsChartHelper.CreateCompositeLine(chart, chartLayer, lineStyle1, 3, System.Drawing.Color.Black); How can I add vertical lines to a composite chart? That depends on the context of the vertical lines that you want to add. There are the Major and Minor GridLine properties that you can modify. But my guess is you want something customized, either to align with a specific value or to separate groups of Categories. That gets a bit more tricky. I would need to know the specific context of what you are trying but my guess is that you would want to look into the FillSceneGraph event. It allows you to do a plethora of types of customizations not specifically built into the Chart. Search of the site for FillSceneGraph ideas https://www.google.com/?gws_rd=ssl#q=FillSceneGraph+site:infragistics.com&spf=1 Vertical Lines in a Line Chart https://www.infragistics.com/community/forums/t/84464.aspx How do I eliminate the extra line under the top title? Your last sample didn't have a top title. And adding one there, while the placement would be currently in the middle of the Line Chart, it doesn't add a line. Also the image that you recently attached while it has a top title doesn't have the line. Can you include a sample that shows it or an image that has it, and point to it, and I can try to see what is painting it.
Let me know if that helps,
As I indicted, I got the chart bounds thing figured out, and the dot/dash lines also works - these was a problem with how I was using it.
So here are my current questions/issues (I have included a sample image to illustrate)
1. The horizontal line I would like to have removed is shown in the image. Note that I have set the BorderStyle of the chart to None.
2. The vertical lines I would like to add are also shown in the image. The reason for this is that the results being charted can correspond to several different order numbers (up to three), and I would like to add a vertical line as a way of showing the order number breaks (if there is only one order then, of course, no vertical lines would be displayed). These lines would therefore need to be programmatically positioned.
3. Is there a way to eliminate the mouse behavior of displaying the Y value of a point for a given NumericSeries? The problem is when the lines are close together it may be hard for a user to disambiguate them when trying to determine the Y value of a point on the main data line.
4. Is there a way to display a short legend string for each NumericSeries line, for example on the right side of the chart? Otherwise, how are legends typically constructed and displayed? I tried setting the Label property of the series, but it doesn't do anything.
I have been playing around with the FillSceneGraph event and reading some of the articles you mentioned in order to add the vertical lines in the chart. According to your documentation this event is fired twice, so you have to ignore the first instance by checking the axis values. However, in my case, the event is only being called once, and the axis values are always null. I also tried adding a chart.Refresh() call, but that didn't help.
This issue may also be related to another problem I am having - when the data requires me to create a second chart, the chart is blank except for the titles on the top and bottom (see the attached graphic). This is despite all of the chart-related objects being newly constructed in all cases, so there should be no interference.
Here is my setup and event logic:
chart = new UltraChart(); chart.ChartType = chartType; chart.Name = title; chart.FillSceneGraph += new Infragistics.UltraChart.Shared.Events.FillSceneGraphEventHandler(OnChart_FillSceneGraph);
private void OnChart_FillSceneGraph(object sender, FillSceneGraphEventArgs e) { if (sender is UltraChart) { UltraChart chart = (UltraChart)sender; IAdvanceAxis xAxis = (IAdvanceAxis)e.Grid["X"]; IAdvanceAxis yAxis = (IAdvanceAxis)e.Grid["Y"]; if (xAxis == null || yAxis == null) return; int yMin = (int)yAxis.MapMinimum; int yMax = (int)yAxis.MapMaximum; foreach (NumericSeries series in chart.CompositeChart.ChartLayers[0].Series) { if (series.Key == _labelValue) { int searchValue = 0; for (int index = 0; index < series.Points.Count; index++) { NumericDataPoint point = series.Points[index]; if (UtilityHelper.ToInteger(point.Label) > searchValue) { int xValue = (int)xAxis.Map(index); Line line = new Line(new Point(xValue, yMin), new Point(xValue, yMax)); line.PE.Fill = System.Drawing.Color.Gray; line.PE.StrokeWidth = 1; line.lineStyle = new LineStyle(LineCapStyle.NoAnchor, LineCapStyle.NoAnchor, LineDrawStyle.DashDot); e.SceneGraph.Add(line); searchValue++; } } break; } } } }
I have updated and attached the sample project to better illustrate all of the above issues:
1. Adding vertical lines with the FillSceneGraph event.
2. The second chart is blank.
3. The extra horizontal line.
In respects to the vertical lines of the FillSceneGraph, your Axis are coming up null because you are using the code for a LineChart, not a CompositeChart with a LineChart layer. CompositeCharts you need to get the IAdvanceAxis differently. http://help.infragistics.com/Help/Doc/WinForms/2013.1/CLR4.0/html/Chart_Access_Axis_Inside_FillSceneGraph_Event_of_a_Composite_Chart.htmlIAdvanceAxis xAxis = (IAdvanceAxis)chart.CompositeChart.ChartLayers[0].ChartLayer.Grid["X"];IAdvanceAxis yAxis = (IAdvanceAxis)chart.CompositeChart.ChartLayers[0].ChartLayer.Grid["Y"];As to why your second, and all subsequent charts are appearing to be blank. That is because the ChartArea.Bounds you are specifying should be relative to the chart positioning. You are specifying them with coordinates relative to the form. So the first one is painting correctly because your Left and Top are 0,0. But after the first one you are effectively positioning your ChartAreas outside the bounds of the Chart's that they are in. Lastly the extra horizontal line is the ChartArea.Border. If you set the ChartArea.Border.Thickness = 0 or the ChartArea.Border.Color = Color.Transparent, it will go away.
Hope that helps,
Excellent! I got everything working - below is an example of a chart from the app.
Just one question from before that I forgot to repeat: when you mouse over a point, the control will display the value at that point, which is a very nice feature. However, if the tow are move lines are close together, it may be difficult for the user to select the line and point that he wants to display. Is there any way of disabling the mouse-over event for a NumericSeries?
One other issue that I had asked before, and forgot to revisit:
I would like to have a short legend string on the right side of the chart for each flat horizontal line (e.g., "Avg") Is that possible, and if so, how do I do it?
You can create a simple legend using the CompositeLegend class and adding to the Chart via something like:
CompositeLegend legend = new CompositeLegend();legend.ChartLayers.Add(chartLayer);chart.CompositeChart.Legends.Add(legend);
You can then position it via the Bounds. Our installed samples browser in the Legacy samples has an example of it. You can also see it statically online here:https://www.infragistics.com/samples/windows-forms/chart/composite-chart-legends
If you are talking about putting just a text string next to the line. You can use the FillSceneGraph to do that, Find the line and add a Text primitive to the left of it would be my guess on doing it that way.
As to removing the DataItem highlighting for the average lines markers, handle the DataItemOver event with something like:private void Chart_DataItemOver(object sender, ChartDataEventArgs e){ if (e.Primitive is DataPoint) { DataPoint pt = (DataPoint)e.Primitive; switch (pt.Series.Key) { case _labelMin: case _labelMax: case _labelAverage: case _labelLCL: case _labelUCL: pt.Caps = PCaps.None; break; default: break; } } }
Thanks for the help. The mouse-over code works fine, but I am having an issue with the legend labels...
I am trying to position the labels on the right-hand side of the chart, as shown in the attached image, and am using the FillSceneGraph event to do it (code is shown below). However, I can't get the text to show up. What am I doing wrong?
private void OnChart_FillSceneGraph(object sender, FillSceneGraphEventArgs e) { if (sender is UltraChart) { UltraChart chart = (UltraChart)sender; IAdvanceAxis xAxis = (IAdvanceAxis)chart.CompositeChart.ChartLayers[0].ChartLayer.Grid["X"]; IAdvanceAxis yAxis = (IAdvanceAxis)chart.CompositeChart.ChartLayers[0].ChartLayer.Grid["Y"]; if (xAxis == null || yAxis == null) return; int yMin = (int)yAxis.MapMinimum; int yMax = (int)yAxis.MapMaximum; foreach (NumericSeries series in chart.CompositeChart.ChartLayers[0].Series) { if (series.Key == _labelValue) { int searchValue = 0; for (int index = 0; index < series.Points.Count; index++) { NumericDataPoint point = series.Points[index]; if (UtilityHelper.ToInteger(point.Label) > searchValue) { int xValue = (int)xAxis.Map(index); Line line = new Line(new Point(xValue, yMin), new Point(xValue, yMax)); line.PE.Fill = System.Drawing.Color.Gray; line.PE.StrokeWidth = 1; line.lineStyle = new LineStyle(LineCapStyle.NoAnchor, LineCapStyle.NoAnchor, LineDrawStyle.DashDot); e.SceneGraph.Add(line); searchValue++; } } break; } else { int xValue = (int)xAxis.Map(series.Points.Count + 5); int yValue = (int)xAxis.Map(series.Points[series.Points.Count - 1].Value); Text text = new Text(); text.PE.Fill = System.Drawing.Color.Black; text.bounds = new Rectangle(xValue, yValue, 40, 20); text.SetTextString(series.Label); e.SceneGraph.Add(text); } } } }
The primary issue here is how you are computing the xValue and the yValue. First the Map function gives you a relative pixel location of a value in the axes. Where you are computing your xValue. You last value is a series.Points.Count - 1. But you are supplying it series.Points.Count +5. For the xAxis the value is the number of categories, so you are going out the width of 6 categories beyond the edge of your line chart. My guess is you intended something more like:
int xValue = (int)xAxis.Map(series.Points.Count -1 ) + 5;
Which instead goes 5 pixels past the location of your last category value.
Similarly for your yValue, you are mapping it using the xAxis instead of the yAxis, so you are getting completely wrong values. First you would want to use the yAxis, second, this is going to get you the top edge, so you may want to adjust it based on 1/2 your desired height in pixels. Something like:
int yValue = (int)yAxis.Map(series.Points[series.Points.Count - 1].Value) - 10;