Hi,
I'm using a composite chart in my application and adding a composite Legend to chart in the fillscenegraph event. However the problem is that the legend items are not getting displayed initially and when I resize the chart or change the window layout, then the legend becomes visible.
My chart control is on top of a user control which is added to a windows form.Also, find attached the screen shot of the same.
Please find below the sample code for adding the legend:
void
m_Chart_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e) {
if (tempCollection.Count > 0){
e.SceneGraph.AddRange(tempCollection.ToArray());
foreach (Primitive prim in tempCollection)
{
UpdatePrimitives(prim,primitveRangeMap[prim]);
}
if (m_Parent.DisplayLegend)
AddLegend();
private void AddLegend(){
if (m_HistLayerAppearance != null){
if (this.m_Chart.CompositeChart.Legends.Count < 1)
CompositeLegend myLegend = new CompositeLegend();
myLegend.ChartLayers.Add(m_HistLayerAppearance);
myLegend.Bounds =
new Rectangle(75, 2, 20, 10);
myLegend.BoundsMeasureType = MeasureType.Percentage;
myLegend.PE.ElementType =
PaintElementType.SolidFill;
myLegend.PE.Fill =
Color.White;
myLegend.PE.FillStopColor =
myLegend.Border.CornerRadius = 5;
myLegend.Border.Thickness = 1;
myLegend.LabelStyle.FontColor =
Color.Black;
myLegend.LabelStyle.FontSizeBestFit =
true;
myLegend.LabelStyle.WrapText =
this.m_Chart.CompositeChart.Legends.Add(myLegend);
Regards,
Uday
Sorry, but I'm not entirely sure what you're trying to accomplish and why you're using FillSceneGraph event to do it. First, let me advise against setting properties on your chart instance inside FillSceneGraph. Doing so will likely cause the chart to repaint and FillSceneGraph will be called repeatedly from within itself. Use FillSceneGraph to add shapes (primitives) directly onto the scenegraph only. I would suggest a different approach, but i'm not sure what your goal is.
Max,
Thanks for your reply. I am just trying to add a composite legend to my chart and make it customizable(like user can change the location and font style etc from a dialog).
The problem is that the legend items are not getting displayed initially(as shown in the screen shots attached). I am actually adding the legend in the method where I create the histogram series but it still doesnt show. hence, I tried to add it in the fillscenegraph event. Please find below the piece of code where I'm creating the histogram series and adding it to the composite chart. I dont understand where am I going wrong.
protected void UpdateChart() { try { ISeries[] allSeries = CreateHistogramSeries();
if (m_ChartArea == null) { m_ChartArea = new ChartArea(); m_ChartArea.Key = "chartArea1"; m_Chart.CompositeChart.ChartAreas.Add(m_ChartArea); }
if ((m_AxisX_Value == null) || (m_AxisY_Value == null)) { m_AxisX_Label = CreateAxisX_Label(); m_ChartArea.Axes.Add(m_AxisX_Label); m_AxisX_Value = CreateAxisX_Value(); m_ChartArea.Axes.Add(m_AxisX_Value); m_AxisY_Value = CreateAxisY_Value(); m_ChartArea.Axes.Add(m_AxisY_Value); }
if (m_HistLayerAppearance == null) { m_HistLayerAppearance = new ChartLayerAppearance(); m_HistLayerAppearance.Key = "chartLayer1"; m_HistLayerAppearance.AxisXKey = "AxisX_Label"; m_HistLayerAppearance.AxisYKey = "AxisY_Value"; m_HistLayerAppearance.ChartAreaKey = "chartArea1"; m_HistLayerAppearance.ChartType = ChartType.StackColumnChart;
m_HistLayerAppearance.Series.AddRange(allSeries); m_Chart.CompositeChart.ChartLayers.Add(m_HistLayerAppearance); } else { m_HistLayerAppearance.Series.Clear(); m_HistLayerAppearance.Series.AddRange(allSeries); }
if (m_AxisLayerAppearance == null) { m_AxisLayerAppearance = new ChartLayerAppearance(); m_AxisLayerAppearance.Key = "chartLayer2"; m_AxisLayerAppearance.AxisXKey = "AxisX_Value"; m_AxisLayerAppearance.AxisYKey = "AxisY_Value"; m_AxisLayerAppearance.ChartAreaKey = "chartArea1"; m_AxisLayerAppearance.ChartType = ChartType.LineChart;
m_Chart.CompositeChart.ChartLayers.Add(m_AxisLayerAppearance); }
if (m_Parent.DisplayLegend) AddLegend(); m_Chart.Tooltips.Display = TooltipDisplay.MouseClick; m_Chart.InvalidateLayers(); } catch (Exception ex) { PetrelLogger.ErrorBox(ex.StackTrace); } }
private void AddLegend() { if (m_HistLayerAppearance != null) { if (this.m_Chart.CompositeChart.Legends.Count < 1) { CompositeLegend myLegend = new CompositeLegend(); myLegend.ChartLayers.Add(m_HistLayerAppearance); myLegend.Bounds = new Rectangle(75, 2, 20, 10); myLegend.BoundsMeasureType = MeasureType.Percentage; myLegend.PE.ElementType = PaintElementType.SolidFill; myLegend.PE.Fill = Color.White; myLegend.PE.FillStopColor = Color.White; myLegend.Border.CornerRadius = 5; myLegend.Border.Thickness = 1; myLegend.LabelStyle.FontColor = Color.Black; myLegend.LabelStyle.FontSizeBestFit = true; myLegend.LabelStyle.WrapText = true; this.m_Chart.CompositeChart.Legends.Add(myLegend); } } }
I guess i missed the title of this post. Histogram and Treemap charts weren't designed to be composite charts, because they are meant to function as stand alone charts. Unfortunately, this means it won't be possible to effectively create a composite legend and add it to the chart. I would suggest going the non-composite chart route and creating the legend entirely from chart primitives in FillSceneGraph.
never mind i got it to work
before:
s1.Points.Add(new NumericDataPoint(0,"", true));
after:
s1.Points.Add(new NumericDataPoint(0,"", false));
This does not work...Check my code
//Step 1:define chart type
this.ucIterationBasedMetrics.ChartType = ChartType.Composite;
//Step 2: define chart Area(skipped since not using composite chart)
ChartArea ca = new ChartArea();
this.ucIterationBasedMetrics.CompositeChart.ChartAreas.Add(ca);
//Step 3:Define all axes
//for defects
AxisItem XaxisForStack = new AxisItem(this.ucIterationBasedMetrics,AxisNumber.X_Axis);
XaxisForStack.DataType = AxisDataType.String;
XaxisForStack.SetLabelAxisType = Infragistics.UltraChart.Core.Layers.SetLabelAxisType.GroupBySeries;
//XaxisForStack.TickmarkStyle = AxisTickStyle.DataInterval;
XaxisForStack.Labels.SeriesLabels.Format = AxisSeriesLabelFormat.Custom;
XaxisForStack.Labels.SeriesLabels.FormatString = "<EVERY_THIRD_X>";//"<ITEM_LABEL>";
//XaxisForStack.Labels.Orientation = TextOrientation.VerticalRightFacing;
//XaxisForStack.Labels.HorizontalAlign = System.Drawing.StringAlignment.Near;
//XaxisForStack.Labels.VerticalAlign = System.Drawing.StringAlignment.Center;
//XaxisDefects.Visible = false;
ca.Axes.Add(XaxisForStack);
AxisItem YaxisForStack = new AxisItem(this.ucIterationBasedMetrics, AxisNumber.Y_Axis);
YaxisForStack.axisNumber = AxisNumber.Y_Axis;
YaxisForStack.DataType = AxisDataType.Numeric;
YaxisForStack.TickmarkStyle = AxisTickStyle.Smart;
YaxisForStack.TickmarkInterval = 1;
YaxisForStack.Labels.ItemFormatString = "<DATA_VALUE:0.#>";
ca.Axes.Add(YaxisForStack);
//for the Acctual work
AxisItem XaxisActual = new AxisItem(this.ucIterationBasedMetrics,AxisNumber.X_Axis);
XaxisActual.DataType = AxisDataType.String;
XaxisActual.SetLabelAxisType = Infragistics.UltraChart.Core.Layers.SetLabelAxisType.ContinuousData;
XaxisActual.TickmarkStyle = AxisTickStyle.Smart;
XaxisActual.Labels.ItemFormatString = "<ITEM_LABEL>";
XaxisActual.Visible = false;
XaxisActual.TickmarkInterval = 1;
ca.Axes.Add(XaxisActual);
AxisItem YaxisActual = new AxisItem(this.ucIterationBasedMetrics, AxisNumber.Y2_Axis);
//YaxisActual.axisNumber = AxisNumber.Y_Axis;
YaxisActual.DataType = AxisDataType.Numeric;
YaxisActual.SetLabelAxisType = Infragistics.UltraChart.Core.Layers.SetLabelAxisType.ContinuousData;
YaxisActual.Labels.HorizontalAlign = System.Drawing.StringAlignment.Near;
YaxisActual.Labels.VerticalAlign = System.Drawing.StringAlignment.Center;
YaxisActual.TickmarkStyle = AxisTickStyle.Smart;
YaxisActual.TickmarkInterval = 1;
YaxisActual.Labels.ItemFormatString = "<DATA_VALUE:0.#>";
ca.Axes.Add(YaxisActual);
this.ucIterationBasedMetrics.Axis.X.Labels.ItemFormat = Infragistics.UltraChart.Shared.Styles.AxisItemLabelFormat.Custom;
this.ucIterationBasedMetrics.Axis.X.Labels.ItemFormatString = "<EVERY_THIRD_X>";
//Step4: Initialize series
NumericSeries seriesOpenEW = this.getNumericSeriesForIterationChart("OPEN_EW", METINDEX_EWCOL_INDEX, ChartType.StackColumnChart,"Open EngWork");
NumericSeries seriesClosedEW = this.getNumericSeriesForIterationChart("CLOSED_EW", METINDEX_EWCOL_INDEX, ChartType.StackColumnChart, "Closed EngWork");
NumericSeries seriesOpenDef = this.getNumericSeriesForIterationChart("OPEN_DEFECTS", METINDEX_DEFECTCOL_INDEX, ChartType.StackColumnChart, "Open Defects");
NumericSeries seriesClosedDef = this.getNumericSeriesForIterationChart("CLOSED_DEFECTS", METINDEX_DEFECTCOL_INDEX, ChartType.StackColumnChart, "Closed Defects");
NumericSeries seriesCumActualDef = this.getNumericSeriesForIterationChart("CUM_ACTUAL_EW", METINDEX_EWCOL_INDEX, ChartType.LineChart, "Cumulative Actual EngWork Remaining");
//set series colors
seriesClosedEW.PEs.Add(new PaintElement(Color.Green));
seriesClosedDef.PEs.Add(new PaintElement(Color.Orange));
seriesOpenDef.PEs.Add(new PaintElement(Color.OrangeRed));
seriesOpenEW.PEs.Add(new PaintElement(Color.Yellow));
seriesCumActualDef.PEs.Add(new PaintElement(Color.Blue));
//add series for each iteration
//Step 5: Define Chart Layer appearance
//defects
ChartLayerAppearance stackColumnLayerAppearance = new ChartLayerAppearance();
stackColumnLayerAppearance.AxisX = XaxisForStack;
stackColumnLayerAppearance.AxisY = YaxisForStack;
stackColumnLayerAppearance.ChartArea = ca;
stackColumnLayerAppearance.ChartType = ChartType.StackColumnChart;
stackColumnLayerAppearance.SwapRowsAndColumns = true;
stackColumnLayerAppearance.Series.Add(seriesClosedEW);
stackColumnLayerAppearance.Series.Add(seriesOpenEW);
stackColumnLayerAppearance.Series.Add(seriesClosedDef);
stackColumnLayerAppearance.Series.Add(seriesOpenDef);
ChartLayerAppearance lineActualLayerAppearance = new ChartLayerAppearance();
lineActualLayerAppearance.AxisX = XaxisActual;
lineActualLayerAppearance.AxisY = YaxisActual;
lineActualLayerAppearance.ChartArea = ca;
lineActualLayerAppearance.ChartType = ChartType.LineChart;
((LineChartAppearance)lineActualLayerAppearance.ChartTypeAppearance).NullHandling = NullHandling.DontPlot;
ucIterationBasedMetrics.LineChart.DrawStyle = Infragistics.UltraChart.Shared.Styles.LineDrawStyle.Dash;
lineActualLayerAppearance.Series.Add(seriesCumActualDef);
//Step 6: Add the the layers to the composite chart
this.ucIterationBasedMetrics.CompositeChart.ChartLayers.Add(stackColumnLayerAppearance);
this.ucIterationBasedMetrics.CompositeChart.ChartLayers.Add(lineActualLayerAppearance);
//Step 7: Legends
myLegend.ChartLayers.Add(stackColumnLayerAppearance);
myLegend.ChartLayers.Add(lineActualLayerAppearance);
myLegend.Bounds = new System.Drawing.Rectangle(0, 75, 100, 25);
myLegend.PE.ElementType = PaintElementType.Gradient;
myLegend.PE.FillGradientStyle = GradientStyle.ForwardDiagonal;
myLegend.PE.Fill = Color.White;
myLegend.Border.Color = Color.Black;
myLegend.PE.FillStopColor = Color.Transparent;
myLegend.Border.CornerRadius = 10;
this.ucIterationBasedMetrics.CompositeChart.Legends.Add(myLegend);
private NumericSeries getNumericSeriesForIterationChart(string metricColumnName, int metricIndex, ChartType ct, string seriesLabel)
NumericSeries s1 = new NumericSeries();
//add 0,0
if (ct != ChartType.LineChart)//skip adding first point for the line chart
int numPoints = this.iDS.Iterations.Rows.Count * 3;
foreach(IterationDS.IterationsRow iRow in this.iDS.Iterations.Rows)
{//add 3 points on xAxis for each iteration number of points = number of stackbars needed +1
for (int j = 1; j <= 3; j++)
if (j == metricIndex)
{//add a valid data point only for the asked metric column for others input 0 metric index help group(stack) needed metrics together
string labelColumn = "";
if (metricIndex == METINDEX_EWCOL_INDEX)
labelColumn = iRow.ITERATION_NAME;
s1.Points.Add(new NumericDataPoint(double.Parse((iRow[metricColumnName].ToString() == null || iRow[metricColumnName].ToString() == "") ? "0" : iRow[metricColumnName].ToString()), labelColumn, false));
s1.Label = iRow.ITERATION_NAME;
else
if (ct != ChartType.LineChart)
s1.Points.Add(new NumericDataPoint(0, "", false));
if (this.iDS.Iterations.Rows.IndexOf(iRow) == this.iDS.Iterations.Rows.Count - 1 && j == 2)
s1.Label = seriesLabel;
return s1;
I haven't been able to reproduce the problem with a 2 layer composite chart.
Try the following code and see if it works for you:
private void Form_Load(object sender, EventArgs e){ultraChart1.ChartType = ChartType.Composite;
ChartArea area = new ChartArea();ultraChart1.CompositeChart.ChartAreas.Add(area);
AxisItem xAxis = new AxisItem();xAxis.axisNumber = AxisNumber.X_Axis;xAxis.DataType = AxisDataType.String;xAxis.SetLabelAxisType = SetLabelAxisType.GroupBySeries;area.Axes.Add(xAxis);
AxisItem lineXAxis = new AxisItem();lineXAxis.axisNumber = AxisNumber.X_Axis;lineXAxis.DataType = AxisDataType.String;lineXAxis.SetLabelAxisType = SetLabelAxisType.ContinuousData;area.Axes.Add(lineXAxis);
AxisItem yAxis = new AxisItem();yAxis.axisNumber = AxisNumber.Y_Axis;yAxis.DataType = AxisDataType.Numeric;area.Axes.Add(yAxis);
NumericSeries series1 = new NumericSeries();series1.Points.Add(new NumericDataPoint(5, "pt1", false));series1.Points.Add(new NumericDataPoint(6, "pt2", false));series1.Points.Add(new NumericDataPoint(7, "pt3", false));series1.Label="series1";
NumericSeries series2 = new NumericSeries();series2.Points.Add(new NumericDataPoint(1, "pt4", false));series2.Points.Add(new NumericDataPoint(3, "pt5", false));series2.Points.Add(new NumericDataPoint(2, "pt6", false));series2.Label = "series2";
ultraChart1.CompositeChart.Series.Add(series1);ultraChart1.CompositeChart.Series.Add(series2);
ChartLayerAppearance layer = new ChartLayerAppearance();layer.AxisX = xAxis;layer.AxisY = yAxis;layer.ChartArea = area;layer.ChartType = ChartType.StackColumnChart;layer.Series.Add(series1);layer.Series.Add(series2);
ultraChart1.CompositeChart.ChartLayers.Add(layer);
ChartLayerAppearance lineLayer = new ChartLayerAppearance();lineLayer.AxisX = lineXAxis;lineLayer.AxisY = yAxis;lineLayer.ChartArea = area;lineLayer.ChartType = ChartType.LineChart;lineLayer.Series.Add(series1);
ultraChart1.CompositeChart.ChartLayers.Add(lineLayer);
CompositeLegend legend = new CompositeLegend();legend.Bounds = new Rectangle(0, 0, 70, 150);legend.ChartLayers.Add(layer);legend.ChartLayers.Add(lineLayer);
ultraChart1.CompositeChart.Legends.Add(legend);
I am using a composite chart with two layers. First layer contains a Stacked column chart which I am computing to display in the form of a histogram. The second layer consists of a line chart to for displaying the axes. i'm adding a composite legend to the layer containing the column chart as shown in the code above. The problem I'm facing is that the legend items do not get displayed initially when the chart is displayed but on resizing the window, it gets displayed properly as shown in the attached screenshot. Any pointers on what is going wrong or should I be creating the legend using rimitives as suggested by you.