How do I get series data to display in bar chart legend - c#

I have a Windows Forms Application that displays a graph from data stored in a database. I am able to get the data to display in a bar graph or pie graph. But the legend in the bar graph only displays "Series1", the name of the series. The legend of the pie chart displays a correct legend with the series data. I've searched MSDN and found several articles on adding a legend but they all have the same results.
Here is my bar chart code:
string[] xvals = new string[dt.Rows.Count];
int[] yvals = new int[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
xvals[i] = dt.Rows[i]["XValues"].ToString();
yvals[i] = Convert.ToInt32(dt.Rows[i]["YValues"].ToString());
}
Chart barChart = new Chart();
ChartArea chartArea = new ChartArea();
barChart.ChartAreas.Add(chartArea);
barChart.Dock = DockStyle.Fill;
barChart.BackColor = Color.Transparent;
barChart.Palette = ChartColorPalette.Fire;
barChart.ChartAreas[0].BackColor = Color.Transparent;
barChart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
barChart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
Series series1 = new Series
{ Name = "Series1", IsVisibleInLegend = true, ChartType = SeriesChartType.Bar };
series1.ChartType = SeriesChartType.Column;
barChart.Series.Add(series1);
for (int i = 0; i < dt.Rows.Count; i++)
{
series1.Points.AddXY(dt.Rows[i]["XValues"].ToString(),
Convert.ToInt32(dt.Rows[i]["YValues"].ToString()));
var p1 = series1.Points[i];
p1.Color = Color.FromArgb((byte)r.Next(90, 255), (byte)r.Next(90, 255), 160);
}
barChart.Legends.Add(new Legend("Legend1"));
barChart.Legends["Legend1"].BackColor = Color.Transparent;
barChart.Series["Series1"].Legend = "Legend1";
series1.IsVisibleInLegend = true;
gbo1.Controls.Add(barChart);
Here is my pie chart code:
string[] xvals = new string[dt.Rows.Count];
int[] yvals = new int[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
xvals[i] = dt.Rows[i]["XValues"].ToString();
yvals[i] = Convert.ToInt32(dt.Rows[i]["YValues"].ToString());
}
Chart pieChart = new Chart();
ChartArea chartArea = new ChartArea();
chartArea.Name = "PieChartArea";
pieChart.ChartAreas.Add(chartArea);
pieChart.Dock = DockStyle.Fill;
pieChart.Location = new Point(0, 50);
pieChart.Palette = ChartColorPalette.Fire;
pieChart.BackColor = Color.Transparent;
pieChart.ChartAreas[0].BackColor = Color.Transparent;
Series series2 = new Series
{ Name = "Series2", IsVisibleInLegend = true, ChartType = SeriesChartType.Pie };
pieChart.Series.Add(series2);
for (int i = 0; i < dt.Rows.Count; i++)
{
series2.Points.Add((int)dt.Rows[i]["YValues"]);
var p2 = series2.Points[i];
p2.Color = Color.FromArgb((byte)r.Next(90, 255), (byte)r.Next(90, 255), 160);
p2.LegendText = dt.Rows[i]["XValues"].ToString();
}
pieChart.Legends.Add(new Legend("Legend2"));
pieChart.Legends["Legend2"].BackColor = Color.Transparent;
pieChart.Series["Series2"].Legend = "Legend2";
series2.IsVisibleInLegend = true;
gboReport1.Controls.Add(pieChart);
What am I missing? Please help.
Here is the output of the bar chart:
Bar Chart with bad Legend
Here is the output of the pie chart:
Pie Chart with good Legend

That is how Bar and Pie charts are designed to work.
All ChartTypes except Pie charts display the Series.Names or the SeriesTexts in their Legend.
Only Pie charts, which only have one Series anyway will display the DataPoint.YValues[0].
If you really want to display datapoint data in your Legend you can do that, but of course it will look crowded if you add more than a few data points..
This is an example of how you can add hide the regular Legend and add a new one which displays the data values:
chart1.ApplyPaletteColors();
chart1.Legends[0].Enabled = false;
Legend L2 = new Legend();
chart1.Legends.Add(L2);
L2.Docking = Docking.Right;
foreach (DataPoint dp in yourSeries.Points)
{
LegendItem LI = new LegendItem(dp.YValues[0].ToString("0.##"), dp.Color, "");
LI.BorderWidth = 0;
L2.CustomItems.Add(LI);
}
If you want to you can also add those items to the regular Legend; simply create a reference to it and use the code above:
Legend L1 = chart1.Legends[0];
Note that you can't delete the original items from the original Legend, though!

Related

How to add labels both inside and outside chart

I want to add labels both inside and outside of a pie chart.
I have tried adding values to it, it works either inside or outside.
I want to display both VALX and VALY on my chart
How can I do this?
I want my chart to appear like this.
XmlNodeList xnList = xml.SelectNodes("/Report/Parameters/Parameter");
var chart = new Chart();
chart.Height = 600;
chart.Width = 900;
ArrayList xAxisData = new ArrayList();
ArrayList yAxisData = new ArrayList();
string title = "Motility";
chart.Titles.Add(title);
var chartArea1 = new ChartArea();
chart.ChartAreas.Add(chartArea1);
chart.ChartAreas[0].AlignmentStyle = AreaAlignmentStyles.All;
Series series1;
xAxisData.Clear();
yAxisData.Clear();
string seriesName1 = " ";
byte ColorIndex = 0;
series1 = new Series();
seriesName1 = "Pie Chart";
series1.Name = seriesName1;
series1.ChartType = SeriesChartType.Pie;
chart.Series.Add(series1);
chart.ChartAreas[0].Area3DStyle.Enable3D = true;
chart.ChartAreas[0].Area3DStyle.Inclination = 40;
chart.ChartAreas[0].BorderColor = Color.Black;
chart.ChartAreas[0].Area3DStyle.WallWidth = 20;
chart.Series[seriesName1]["3DLabelLineSize"] = "30";
chart.Series[seriesName1].IsVisibleInLegend = false;
foreach (KeyValuePair<string, ReportParameter> pair in T_NewChart.parameters)
{
chart.Series[seriesName1].Points.AddXY((pair.Value.Name), pair.Value.Values[0]));
if (ColorIndex == 0)
{
chart.Series[seriesName1].Points[0].Color = Color.Green;
chart.Series[seriesName1].Label = "#VALX";
chart.Series[seriesName1]["PieLabelStyle"] = "Outside";
chart.Series[seriesName1].BorderColor = Color.Black;
chart.Series[seriesName1].Points[0].Label = "Total";
chart.Series[0].Font = new System.Drawing.Font("Arial", 15F);
}
else if (ColorIndex == 1)
{
chart.Series[seriesName1].Points[1].Color = Color.Yellow;
chart.Series[seriesName1].Points[1].Label = "Non";
}
else if (ColorIndex == 2)
{
chart.Series[seriesName1].Points[2].Color = Color.Red;
chart.Series[seriesName1].Points[2].Label = "Few";
}
ColorIndex++;
}
chart.SaveImage("C:\\NewPie_chart.png", ChartImageFormat.Png);
I can only display the "Name", but I want to display the "Name" (VALX) outside the chart and the "Value" (VALY) inside the chart.

Zoom in multiple Areas and Axis Y

I have a project with multiple AxisY, with 3 series and and each series has its axisY associated. When I zoom, I have achieved that all the series have zoom but the scale of the axisYof the secondary axisY doesn't change, only that of the main series changes.
Original Chart:
Chart with zoom applied:
I have create the new axisY secondary with the code of microsoft (Project "Windows Forms Samples Environment for Microsoft Chart Control"):
public void CreateYAxis(Chart chart, ChartArea area, Series series, float axisOffset, float labelsSize)
{
// Create new chart area for original series
ChartArea areaSeries = chart.ChartAreas.Add("ChartArea_" + series.Name);
areaSeries.BackColor = Color.Transparent;
areaSeries.BorderColor = Color.Transparent;
areaSeries.Position.FromRectangleF(area.Position.ToRectangleF());
areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF());
areaSeries.AxisX.MajorGrid.Enabled = false;
areaSeries.AxisX.MajorTickMark.Enabled = false;
areaSeries.AxisX.LabelStyle.Enabled = false;
areaSeries.AxisY.MajorGrid.Enabled = false;
areaSeries.AxisY.MajorTickMark.Enabled = false;
areaSeries.AxisY.LabelStyle.Enabled = false;
areaSeries.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero;
series.ChartArea = areaSeries.Name;
// Create new chart area for axis
ChartArea areaAxis = chart.ChartAreas.Add("AxisY_" + series.ChartArea);
areaAxis.BackColor = Color.Transparent;
areaAxis.BorderColor = Color.Transparent;
areaAxis.Position.FromRectangleF(chart.ChartAreas[series.ChartArea].Position.ToRectangleF());
areaAxis.InnerPlotPosition.FromRectangleF(chart.ChartAreas[series.ChartArea].InnerPlotPosition.ToRectangleF());
// Create a copy of specified series
Series seriesCopy = chart.Series.Add(series.Name + "_Copy");
seriesCopy.ChartType = series.ChartType;
foreach(DataPoint point in series.Points)
{
seriesCopy.Points.AddXY(point.XValue, point.YValues[0]);
}
// Hide copied series
seriesCopy.IsVisibleInLegend = false;
seriesCopy.Color = Color.Transparent;
seriesCopy.BorderColor = Color.Transparent;
seriesCopy.ChartArea = areaAxis.Name;
// Disable drid lines & tickmarks
areaAxis.AxisX.LineWidth = 0;
areaAxis.AxisX.MajorGrid.Enabled = false;
areaAxis.AxisX.MajorTickMark.Enabled = false;
areaAxis.AxisX.LabelStyle.Enabled = false;
areaAxis.AxisY.MajorGrid.Enabled = false;
areaAxis.AxisY.IsStartedFromZero = area.AxisY.IsStartedFromZero;
areaAxis.AxisY.LabelStyle.Font = area.AxisY.LabelStyle.Font;
// Adjust area position
areaAxis.Position.X -= axisOffset;
areaAxis.InnerPlotPosition.X += labelsSize;
}
UPDATE--------------------------------:
I have this news:
Now, the 3 axis update his scale but it comes out together, How to separate them?
The code is here:
chart1.ChartAreas[2].AlignmentOrientation = AreaAlignmentOrientations.All;
chart1.ChartAreas[2].AlignmentStyle = AreaAlignmentStyles.All;
chart1.ChartAreas[2].AlignWithChartArea = "ChartArea1";
chart1.ChartAreas[4].AlignmentOrientation = AreaAlignmentOrientations.All;
chart1.ChartAreas[4].AlignmentStyle = AreaAlignmentStyles.All;
chart1.ChartAreas[4].AlignWithChartArea = "ChartArea1";

MS chart candlestick How to set tail colors

I am currently developing a candlestick chart with mschart in visual C#.
I have now created two charts and created the charts as follows
Question 1. View the Candlestick Chart at the top. I would like to apply the tail color of each rod as red or blue.
Question 2. View the bar chart at the bottom. I would like to apply Red or Blue color to this chart. I want to apply the same color to the top of the Candlestick chart. How can I do it ?
[source]
DataTable table_ChartData = new DataTable();
table_ChartData.Columns.Add("Id");
table_ChartData.Columns.Add("Open");
table_ChartData.Columns.Add("Close");
table_ChartData.Columns.Add("High");
table_ChartData.Columns.Add("Low");
table_ChartData.Columns.Add("Day");
dataGridView1.DataSource = table_ChartData;
chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.LineWidth = 1;
chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.LineWidth = 1;
chart1.ChartAreas["ChartArea1"].AxisY.Maximum = max;
chart1.ChartAreas["ChartArea1"].AxisY.Minimum = min;
chart1.ChartAreas["ChartArea1"].AxisX.LabelAutoFitStyle = LabelAutoFitStyles.WordWrap;
chart1.ChartAreas["ChartArea1"].AxisX.IsLabelAutoFit = true;
chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Enabled = true;
chart1.Series["Candle"].XValueMember = "Day";
chart1.Series["Candle"].YValueMembers = "High,Low,Open,Close,Volume";
chart1.Series["Candle"].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Date;
chart1.Series["Candle"].CustomProperties = "PriceDownColor=Blue,PriceUpColor=Red";
chart1.Series["Candle"]["OpenCloseStyle"] = "Triangle";
chart1.Series["Candle"]["ShowOpenClose"] = "Both";
chart1.DataSource = table_ChartData;
chart1.DataBind();
////////////////////////////////////////////////////////////
chart2.ChartAreas["ChartArea1"].AxisX.MajorGrid.LineWidth = 1;
chart2.ChartAreas["ChartArea1"].AxisY.MajorGrid.LineWidth = 1;
chart2.ChartAreas["ChartArea1"].AxisY.Maximum = v_max + (v_max / 10);
chart2.ChartAreas["ChartArea1"].AxisY.Minimum = v_min / 2;
chart2.ChartAreas["ChartArea1"].AxisX.LabelAutoFitStyle = LabelAutoFitStyles.WordWrap;
chart2.ChartAreas["ChartArea1"].AxisX.IsLabelAutoFit = true;
chart2.ChartAreas["ChartArea1"].AxisX.LabelStyle.Enabled = true;
chart2.Series["Bar"].XValueMember = "Day";
chart2.Series["Bar"].YValueMembers = "Volume";
chart2.Series["Bar"].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Date;
chart2.Series["Bar"].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
chart2.DataSource = table_ChartData;
chart2.DataBind();
In a Candlestick Chart there are CustomProperties to automatiaclly set the colors of the boxes, depending on the trend:
someSeries.SetCustomProperty("PriceUpColor", "Green");
someSeries.SetCustomProperty("PriceDownColor", "Red");
Unfortunately there is no way to set the colors of the lines that connect the high- and low-values.
But, unless you have messed with other Custom attributes and if the x-values are meaningful, you can easily draw those lines, and by drawing the top and the bottom part separately you can also use different colors.
Here is an example:
private void chart6_PostPaint(object sender, ChartPaintEventArgs e)
{
ChartArea ca = chart6.ChartAreas[0];
Series s = chart6.Series[0];
Pen hiPen = Pens.Green;
Pen loPen = Pens.Red;
if (e.ChartElement == s)
foreach (DataPoint dp in s.Points)
{
float x = (float)ca.AxisX.ValueToPixelPosition(dp.XValue);
float y_hi = (float)ca.AxisY.ValueToPixelPosition(dp.YValues[0]);
float y_low = (float)ca.AxisY.ValueToPixelPosition(dp.YValues[1]);
float y_open = (float)ca.AxisY.ValueToPixelPosition(dp.YValues[2]);
float y_close = (float)ca.AxisY.ValueToPixelPosition(dp.YValues[3]);
e.ChartGraphics.Graphics.DrawLine(hiPen, x, y_low, x, Math.Min(y_close, y_open));
e.ChartGraphics.Graphics.DrawLine(loPen, x, y_hi, x, Math.Max(y_close, y_open));
}
}
To set Colors for the 2nd Chart's points you need to loop over the points as there Colors cannot be set in binding.
The code is simple:
void SetColors(Series candles, Series columns)
{
for (int i = 0; i < candles.Points.Count; i++)
{
DataPoint dp = candles.Points[i];
columns.Points[i].Color =
dp.YValues[2] > dp.YValues[3] ? Color.Red : Color.Green;
}
}
Call it after binding!
Result:
Note that to avoid seeing the original lines shine through we set the BorderWidth to 0:
someSeries.BorderWidth = 0;
Simple way:
priceSerie.Points[index].Color = Color.Blue;
// priceSerie.Points[index].BorderColor = Color.Magenta;

itextsharp table chart legends beneath bars

Can someone explain me how I can create chart like this one using itextsharp library.
As you can see here, this chart has attached table with legends to its bottom side. And each bar has year attached to it. I want to create something like that.
Second picture. This is what i have so far. I don't have year attached to each bar, and my legends are not beneath each bar like in top graph. If someone could guide me how to create identical graph like one on top i would be grateful. Thanks in advance!
How can I turn those labels to be displayed horizontally, and put those legends beneath years in table like one in picture number 1.
// Chart Centers By Year
var chartCentersByYear = new Chart
{
Width = 1000,
Height = 450,
RenderType = RenderType.ImageTag,
AntiAliasing = AntiAliasingStyles.Graphics,
TextAntiAliasingQuality = TextAntiAliasingQuality.High
};
chartCentersByYear.Titles.Add("Centers By Year");
chartCentersByYear.Titles[0].Font = new Font("Arial", 16f);
chartCentersByYear.Titles[0].Alignment = System.Drawing.ContentAlignment.TopLeft;
chartCentersByYear.ChartAreas.Add("");
chartCentersByYear.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chartCentersByYear.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chartCentersByYear.Series.Add("Count");
chartCentersByYear.Series.Add("Cases");
chartCentersByYear.Series[0].ChartType = SeriesChartType.Column; //Pie
chartCentersByYear.Series[1].ChartType = SeriesChartType.StepLine; //StepLine
chartCentersByYear.Series[1].BorderDashStyle = ChartDashStyle.DashDot;
chartCentersByYear.Series[1].BorderWidth = 3;
chartCentersByYear.Series[0].Color = Color.Brown;
chartCentersByYear.Legends.Add("1");
chartCentersByYear.Legends.Add("2");
chartCentersByYear.Legends[0].HeaderSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[0].HeaderSeparatorColor = Color.Black;
chartCentersByYear.Legends[0].ItemColumnSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[0].ItemColumnSeparatorColor = Color.Black;
chartCentersByYear.Legends[1].HeaderSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[1].HeaderSeparatorColor = Color.Black;
chartCentersByYear.Legends[1].ItemColumnSeparator = LegendSeparatorStyle.Line;
chartCentersByYear.Legends[1].ItemColumnSeparatorColor = Color.Black;
//For the Legend
LegendCellColumn firstColumn = new LegendCellColumn();
firstColumn.ColumnType = LegendCellColumnType.SeriesSymbol;
firstColumn.HeaderBackColor = Color.WhiteSmoke;
chartCentersByYear.Legends[0].CellColumns.Add(firstColumn);
chartCentersByYear.Legends[1].CellColumns.Add(firstColumn);
LegendCellColumn secondColumn = new LegendCellColumn();
secondColumn.ColumnType = LegendCellColumnType.Text;
secondColumn.Text = "#LEGENDTEXT";
secondColumn.HeaderBackColor = Color.WhiteSmoke;
LegendItem newItemCount = new LegendItem();
newItemCount.Cells.Add(LegendCellType.Text, "Count", System.Drawing.ContentAlignment.MiddleCenter);
newItemCount.BorderWidth = 1;
newItemCount.BorderDashStyle = ChartDashStyle.Solid;
LegendItem newItemCases = new LegendItem();
newItemCases.Cells.Add(LegendCellType.Text, "Cases", System.Drawing.ContentAlignment.MiddleCenter);
newItemCases.BorderWidth = 1;
newItemCases.BorderDashStyle = ChartDashStyle.Solid;
// Getting data from a stored procedure
var totalCentersByYearResult = new Repository().GetTotalCentersByYear();
foreach (IGD_spInternationalReportCenterWithTots1_Result item in totalCentersByYearResult)
{
// For Series
chartCentersByYear.Series[0].Points.AddXY(item.YearEcmo, item.Count);
chartCentersByYear.Series[1].Points.AddY(item.Cases);
// For Legend
newItemCount.Cells.Add(LegendCellType.Text, item.Count.ToString(), System.Drawing.ContentAlignment.MiddleCenter);
newItemCases.Cells.Add(LegendCellType.Text, item.Cases.ToString(), System.Drawing.ContentAlignment.MiddleCenter);
}
chartCentersByYear.Legends[0].CustomItems.Add(newItemCount);
chartCentersByYear.Legends[0].CustomItems.Add(newItemCases);
chartCentersByYear.Legends[0].Docking = Docking.Bottom;
chartCentersByYear.Legends[1].Docking = Docking.Bottom; //Top
chartCentersByYear.Series[0].YAxisType = AxisType.Primary;
chartCentersByYear.Series[1].YAxisType = AxisType.Secondary;
//For two coordinate systems
chartCentersByYear.ChartAreas[0].AxisY2.LineColor = Color.Transparent;
chartCentersByYear.ChartAreas[0].AxisY2.MajorGrid.Enabled = false;
chartCentersByYear.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chartCentersByYear.ChartAreas[0].AxisY2.IsStartedFromZero = chartCentersByYear.ChartAreas[0].AxisY.IsStartedFromZero;
using (var chartimage = new MemoryStream())
{
chartCentersByYear.SaveImage(chartimage, ChartImageFormat.Png);
Byte[] newChart = chartimage.GetBuffer(); //return chartimage.GetBuffer();
var image = Image.GetInstance(newChart); //Image.GetInstance(Chart());
image.ScalePercent(50f);
image.SetAbsolutePosition(document.LeftMargin + 40, document.BottomMargin + 100);
document.Add(image);
}

What are the arrows on my mschart

Hello guys i have a MSChart and i have some arrows on chart exactly where the series are overlapping i would like to know at least what are they and maybe how can i get them out.
The chart is generated with two methods:
private void DesignChart()
{
// Create Chart Area
ChartArea chartArea1 = new ChartArea();
// Add Chart Area to the Chart
chart1.ChartAreas.Add(chartArea1);
chart1.Legends.Add(new Legend());
// chart1.ChartAreas[0].AxisX.LabelStyle.Format={"00:00:00"};
chart1.Location = new Point(14, 494);
chart1.Size = new Size(982, 224);
this.Controls.Add(chart1);
((System.ComponentModel.ISupportInitialize)(chart1)).EndInit();
}
private void SetGraph(){
.........
for (int i = 0; i < chart1.Series.Count; i++)
{
chart1.Series[i].XValueMember = "Date";
chart1.Series[i].YValueMembers = "Value";
chart1.Series[i].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[i].XValueType = ChartValueType.Time;
chart1.Series[i].ChartType = SeriesChartType.Line;
chart1.Series[i].MarkerStyle = MarkerStyle.Star10;
chart1.Series[i].MarkerSize = 8;
chart1.Series[i].MarkerColor = chart1.Series[0].BorderColor;
chart1.Series[i].BorderWidth = 3;
chart1.Series[i].IsValueShownAsLabel = true;
chart1.Series[i].ToolTip = "#VALY => #AXISLABEL";
}
chart1.ChartAreas[0].AxisX.IsMarginVisible = true;
}
Picture link Photo of the chart
Thanks
I believe it happens because of this line:
chart1.Series[i].IsValueShownAsLabel = true;
If the data points are close together/overlap, chart control uses the arrow to point to the reference point so you don't get confused -- or something like that. Try setting this line to false and see if the arrows disappear. Not sure there is any other way to override the arrow display.
Is it possible the 'arrows' are actually the result of this line?
chart1.Series[i].MarkerStyle = MarkerStyle.Star10;

Categories