Hello I am working with the composite chart. It is the column and line chart wich are populated in this way
public ctlColumnChart(DataProfile dataProfile, LayoutParams layoutParams) { InitializeComponent(); }
private void ctlColumnChart_Load(object sender, EventArgs e) { //comboChart this.ultraChart1.ChartType = ChartType.Composite;
ChartArea histogramArea = new ChartArea(); ChartArea lineArea = new ChartArea(); this.ultraChart1.CompositeChart.ChartAreas.Add(histogramArea); this.ultraChart1.CompositeChart.ChartAreas.Add(lineArea);
AxisItem axisYhistogram = new AxisItem(); axisYhistogram.Extent = 20; axisYhistogram.DataType = AxisDataType.Numeric; axisYhistogram.Labels.ItemFormatString = "<DATA_VALUE:0.##>"; axisYhistogram.OrientationType = AxisNumber.Y_Axis; axisYhistogram.Labels.HorizontalAlign = StringAlignment.Far; axisYhistogram.LineColor = Color.Silver;
histogramArea.Axes.Add(axisYhistogram);
AxisItem axisXhistogram = new AxisItem(); axisXhistogram.Extent = 20; axisXhistogram.DataType = AxisDataType.String; axisXhistogram.Labels.Orientation = TextOrientation.VerticalLeftFacing; axisXhistogram.Labels.ItemFormatString = "<ITEM_LABEL>"; axisXhistogram.OrientationType = AxisNumber.X_Axis; axisXhistogram.SetLabelAxisType = SetLabelAxisType.GroupBySeries; axisXhistogram.LineColor = Color.Silver; axisXhistogram.Labels.Orientation = TextOrientation.Custom; axisXhistogram.Labels.OrientationAngle = 315;
histogramArea.Axes.Add(axisXhistogram);
AxisItem axisYnormalDistribution = new AxisItem(); axisYnormalDistribution.Extent = 20; axisYnormalDistribution.DataType = AxisDataType.Numeric; axisYnormalDistribution.Labels.ItemFormatString = "<DATA_VALUE:##.##>"; axisYnormalDistribution.OrientationType = AxisNumber.Y_Axis; axisYnormalDistribution.Visible = false; axisYnormalDistribution.LineColor = Color.Silver; axisYnormalDistribution.MajorGridLines.Visible = false; axisYnormalDistribution.MinorGridLines.Visible = false;
lineArea.Axes.Add(axisYnormalDistribution);
AxisItem axisXnormalDistribution = new AxisItem(); axisXnormalDistribution.Extent = 20; axisXnormalDistribution.DataType = AxisDataType.String; axisXnormalDistribution.Labels.Orientation = TextOrientation.VerticalLeftFacing; axisXnormalDistribution.Labels.ItemFormatString = "<ITEM_LABEL>"; axisXnormalDistribution.Labels.Visible = false; axisXnormalDistribution.OrientationType = AxisNumber.X_Axis; axisXnormalDistribution.SetLabelAxisType = SetLabelAxisType.ContinuousData; axisXnormalDistribution.LineColor = Color.Silver; axisXnormalDistribution.MajorGridLines.Visible = false; axisXnormalDistribution.MinorGridLines.Visible = false; axisXnormalDistribution.Margin.Near.MarginType = LocationType.Pixels; axisXnormalDistribution.Margin.Near.Value = 20; lineArea.Axes.Add(axisXnormalDistribution);
ChartLayerAppearance myColumnLayer = new ChartLayerAppearance(); myColumnLayer.ChartType = ChartType.ColumnChart; myColumnLayer.SwapRowsAndColumns = true; myColumnLayer.ChartArea = histogramArea;
ChartLayerAppearance myLineLayer = new ChartLayerAppearance(); myLineLayer.ChartType = ChartType.LineChart; myLineLayer.ChartArea = lineArea;
NumericSeries histogramSeries = new NumericSeries(); histogramSeries.DataBind(GetHistogramData(), "Value", "Month"); histogramSeries.PEs.Add(new PaintElement(Color.DimGray)); myColumnLayer.Series.Add(histogramSeries); ultraChart1.CompositeChart.Series.Add(histogramSeries);
NumericSeries normalDestributionSeries = new NumericSeries(); normalDestributionSeries.DataBind(GetNormalDestributionData(), "Cumm Plane", "Month"); normalDestributionSeries.PEs.Add(new PaintElement(Color.Red)); myLineLayer.Series.Add(normalDestributionSeries); ultraChart1.CompositeChart.Series.Add(normalDestributionSeries);
for (int i = 0; i < GetHistogramData().Rows.Count; i++) { Override colorOverride = new Override(); colorOverride.Column = -2; colorOverride.Row = i; colorOverride.PE = new PaintElement(Color.LightSlateGray); this.ultraChart1.Override.Add(colorOverride); }
ColumnChartAppearance appearance = new ColumnChartAppearance(); appearance.SeriesSpacing = 0; myColumnLayer.ChartTypeAppearance = appearance;
myColumnLayer.AxisX = axisXhistogram; myColumnLayer.AxisY = axisYhistogram; this.ultraChart1.CompositeChart.ChartLayers.Add(myColumnLayer);
myLineLayer.AxisX = axisXnormalDistribution; myLineLayer.AxisY = axisYnormalDistribution; this.ultraChart1.CompositeChart.ChartLayers.Add(myLineLayer);
//for (int i = 0; i < GetHistogramData().Rows.Count; i++) //{ // Override colorOverrideline = new Override(); // colorOverrideline.Column = -2; // colorOverrideline.Row = i; // colorOverrideline.PE = new PaintElement(Color.Red); // myLineLayer.ChartComponent.Override.Add(colorOverrideline); //}
ultraChart1.Axis.X.RangeMin = 0; }
private DataTable GetHistogramData() { DataTable lineDt = new DataTable(); lineDt.Columns.Add("Month"); lineDt.Columns.Add("Value", typeof(decimal));
lineDt.Rows.Add("Apr-10", 1.039381); lineDt.Rows.Add("May-10", 1.531703); lineDt.Rows.Add("Jun-10", 2.166947); lineDt.Rows.Add("Jul-10", 2.943036); lineDt.Rows.Add("Aug-10", 3.837218); lineDt.Rows.Add("Sep-10", 4.802984); lineDt.Rows.Add("Oct-10", 5.771378); lineDt.Rows.Add("Nov-10", 6.657660); lineDt.Rows.Add("Dec-10", 7.372884);
return lineDt; }
private DataTable GetNormalDestributionData() { DataTable lineDt = new DataTable(); lineDt.Columns.Add("Month"); lineDt.Columns.Add("Cumm Plane", typeof(decimal));
lineDt.Rows.Add("Apr-10", 1.039381); lineDt.Rows.Add("May-10", 1.531703); lineDt.Rows.Add("Jun-10", 2.166947); lineDt.Rows.Add("Jul-10", 2.943036); lineDt.Rows.Add("Aug-10", 3.837218); lineDt.Rows.Add("Sep-10", 4.802984); lineDt.Rows.Add("Oct-10", 5.771378); lineDt.Rows.Add("Nov-10", 6.657660); lineDt.Rows.Add("Dec-10", 7.372884); lineDt.Rows.Add("Jan-11", 7.838389); lineDt.Rows.Add("Feb-11", 8.000000); lineDt.Rows.Add("Mar-11", 7.838389); lineDt.Rows.Add("Apr-11", 7.372884); lineDt.Rows.Add("May-11", 6.657660); lineDt.Rows.Add("Jun-11", 5.771378); lineDt.Rows.Add("Jul-11", 4.802984); lineDt.Rows.Add("Aug-11", 3.837218); lineDt.Rows.Add("Sep-11", 2.943036); lineDt.Rows.Add("Nov-11", 2.166947); lineDt.Rows.Add("Dec-11", 1.531703);
private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e) { //if (e.Grid.Count == 0) return;
foreach (Primitive p in e.SceneGraph) { Box bar = p as Box; if (bar != null) { bar.PE.Stroke = Color.LightGray; } }
List<Text> textPrims = e.SceneGraph.OfType<Text>().ToList(); var axisX = e.Grid["X"] as IAdvanceAxis;
if (axisX != null) { var mapRange = axisX.MapRange; var totalRange = (double)axisX.TotalRange;
int maxYvalue = textPrims.First().bounds.Location.Y; foreach (Text text in textPrims) { if (maxYvalue < text.bounds.Location.Y && !String.IsNullOrEmpty(text.GetTextString())) { maxYvalue = text.bounds.Location.Y; } }
foreach (Text text in textPrims) { SetLabelAxis xAxis = e.Grid["X"] as SetLabelAxis;
if (xAxis == null) return;
var labels = new List<string>();
for (int i = 0; i < xAxis.ChartData.GetColumnCount(); i++) { labels.Add(xAxis.ChartData.GetColumnLabel(i).ToString()); }
if (labels.Contains(text.GetTextString()) && text.bounds.Location.Y == maxYvalue) { //text.bounds.Offset(0, 0); //text.bounds.Offset((int)(mapRange / totalRange / 2), 0); text.bounds.Offset((int)((mapRange / totalRange / 3) - 5), (int)((mapRange / totalRange / 3) * -1) - 2); //text.bounds.Offset((int)(10), -10); } } } }
1) The problem is with the Override object here
for (int i = 0; i < GetHistogramData().Rows.Count; i++){Override colorOverride = new Override();colorOverride.Column = -2;colorOverride.Row = i;colorOverride.PE = new PaintElement(Color.LightSlateGray);this.ultraChart1.Override.Add(colorOverride);}
what I want is that Line chart to be red collor and Column chart to be LightSlateGray. But when I use override for
colorOverride.Column = 0;
colorOverride.Row = 0;
it colors first column of column chart and whole line chart in the same color. So when I get Override through the foreach loop all columns in the column chart (it is desirable) and whole line chart (not desirable) have the same color, colors are merged and it is impossible to see the line when columns are on the background.
Is there a way to set different color for the line?
I was trying to do something like this but it didn't helped
for (int i = 0; i < GetHistogramData().Rows.Count; i++){Override colorOverrideline = new Override();colorOverrideline.Column = -2;colorOverrideline.Row = i;colorOverrideline.PE = new PaintElement(Color.Red);myLineLayer.ChartComponent.Override.Add(colorOverrideline);}
It colors whole control anyway
I also checked ZeroAlignData property via designer. BTW where can I find this property in the code?
2) Also while using column chart in ultraChart1_FillSceneGraph event I was able to get var axisX = e.Grid["X"] as IAdvanceAxis; but now when I use composite chart I get null here.
The same thing with labels angle. When I was using column chart I was able to set Axis.X.Labels.Orientation = Custom and than set angle of labels. Using composite chart this property takes no effect.
Can you advice something?
Thanks!
Hi Oleksandr,
Thank you for contacting Infragistics Developer Support.
1) When I am running the provided code the chart appears with a red line and a gray columns. Isn’t that the desired result? Also probably in this case it would be better if you add the PaintElement that you want to use for the series to the series itself. You can use the following code to do that:
histogramSeries.PEs.Add(new PaintElement(Color.LightSlateGray, Color.LightSlateGray, GradientStyle.None)); //this will make the columns gray
and then:
normalDestributionSeries.PEs.Add(new PaintElement(Color.Red));//this will make the line red
This way you won’t have to use the Override object.
2) As for the axes, the composite chart doesn’t use the default axes and that is why the Grid is empty. You need to use the Grid property of the chart layer itself:
var axisX = ultraChart1.CompositeChart.ChartLayers[0].ChartLayer.Grid["X"] as IAdvanceAxis;
Keep in mind that in the FillSceneGraph you need to make sure that the layers are created as the first time the event fires, this code will result in exception. For more information on how to get the axes for composite chart, please visit this link:
http://help.infragistics.com/Help/Doc/WinForms/2014.1/CLR4.0/html/Chart_Access_Axis_Inside_FillSceneGraph_Event_of_a_Composite_Chart.html
Please let me know if you have any additional questions.
Heloo Dimitar,
the solution with color and moving labels worked fine for me, thanks a lot!
1) But I am still having troubles with rotating X axis labels for this chart.
The code which I use for rotation is:
AxisItem axisXhistogram = new AxisItem(); axisXhistogram.Extent = 50; axisXhistogram.DataType = AxisDataType.String; axisXhistogram.Labels.ItemFormatString = "<ITEM_LABEL>"; axisXhistogram.OrientationType = AxisNumber.X_Axis; axisXhistogram.SetLabelAxisType = SetLabelAxisType.GroupBySeries; axisXhistogram.LineColor = Color.Silver; axisXhistogram.Labels.Orientation = TextOrientation.Custom; axisXhistogram.Labels.OrientationAngle = 315; axisXhistogram.Labels.Layout.Behavior = AxisLabelLayoutBehaviors.UseCollection; histogramArea.Axes.Add(axisXhistogram);
but what I see is just horizontal aligned labels.
2) Also the labels on X and Y axis can be quite long and in result they get truncated. Is there a way to show tooltips for labels on MouseMove event?
3) Similar question for Bar Chart. When I get the mouse on some bar I see tooltip which shows value of the bar from X axis but is there a way to show some custom tooltip foe each bar? For example value from Y axis.
Thanks a lot for help!
Thank you for the reply.
This is happening, because you are using SwapRowsAndColumns. So the labels that are displayed can’t be modified by axis.Labels. You need to use axis.Labels.SeriesLabels. Then you will be able to set Orientation and OrientationAngle, along with the other label properties:
axisXhistogram.Labels.SeriesLabels.Orientation = TextOrientation.Custom;
axisXhistogram.Labels.SeriesLabels.OrientationAngle = 315;
As for the tooltips you can get all the text primitives in the FillSceneGraph event and then set their Caps property to PCaps.HitTest | PCaps.Tooltip. This will enable the tooltips for them. In order to show their text in the tooltip you need to use the IRenderLabel interface, which allows you to customize the chart’s labels and tooltips. In it create a string property and return it from the ToString method of the interface if it is not equal to String.Empty. After that in the mouse move event, check if the mouse is over a text primitive and if it is, set the property for the IRenderLabel interface to the text of the primitive. If it isn’t reset the property to String.Empty.
For the barchart set the Tooltips.FormatString property to “”:
ultraChart1.Tooltips.FormatString = "";
I have attached a sample demonstrating the custom tooltips.
Hello Dimitar, Thanks a lot for your help. Everything you suggested worked just fine! The only thing I still didn't manage to do is to populate data labels on column chart in the composite chart.
I was trying to do something like this:
var text = new ChartTextAppearance();
//text.ItemFormatString = "<DATA_VALUE:#0>"; text.Row = 0; text.Column = -2; text.Visible = true;
ultraChart1.ColumnChart.ChartText.Add(text); ultraChart1.ColumnChart.ChartText[0].ItemFormatString = "444555";
What I am trying to do is to show custom values for each column (not tooltips but labels). But line chart don't suppose to show such labels.
When using the composite chart, the chart text appearance objects must be added to the respective layer directly, instead of to the ColumnChart property:
((ColumnChartAppearance)myColumnLayer.ChartTypeAppearance).ChartText.Add(text);
Hello again, Dimitar.
Have few more question.
1) I am trying to show tooltips for all labels for Bar chart as I did for Composite chart. With the code like this:
private void ultraBarChart_MouseMove(object sender, MouseEventArgs e) { ChartLayerCollection layers = new ChartLayerCollection(); layers.Add(barChart.BarChart.ChartComponent); foreach (ChartLayerAppearance layer in layers) { bool success = false; if (layer.ChartLayer != null) { var text = layer.ChartLayer.ChartCore.GetChartPrimitiveFromPoint(e.Location) as Text; if (text != null) { labels.Tooltip = text.GetTextString(); success = true; } } if (!success) { labels.Tooltip = String.Empty; } }
}
But I have troubles adding layer layers.Add(barChart.BarChart.ChartComponent);
2) Also after solution that you provided for the tooltips for every label in composite chart. For each column want to show the Y axis value but it shows X axis labels on tooltip.
1) When using non-composite charts you can get the layer itself by using:
var layer = ultraChart1.Layer["Default"]as ChartLayer;
Then you can use:
var text = layer.ChartCore.GetChartPrimitiveFromPoint(e.Location) as Text;
and the rest of the code should be similar.
2) In order to show the column valuse for the Composite chart you can change the ToString() method for the IRenderLabel interface to this:
if (!tooltip.Equals( String.Empty))
{
return tooltip;
else if (!context["DATA_ROW"].ToString().Equals(String.Empty))
double retVal = (double)context["DATA_VALUE"];
return retVal.ToString("###.###");
else if (!context["SERIES_LABEL"].ToString().Equals(String.Empty))
return context["SERIES_LABEL"].ToString();
else
return context["ITEM_LABEL"].ToString();
All I have done here is to check if the data row is not empty and return the DATA_VALUE if that is the case.