I have a Chart with three ChartAreas. The first chart area, chartarea1 plots data from series1, chartarea2 plots series2. But then I'd like chartarea3 to plot series1 and series2. All my searches return ways of plotting multiple Series on a ChartArea and I don't have a problem with that, what I want to do is plot a Series on multiple ChartAreas. Is there a way to do this? The Series["item"].ChartArea property only sets one ChartArea.
This is my attempt, I tried creating series3 and series4 and assigned them series1 and series2 respectively, but it's not working (I suspect because they are reference-types and it doesn't actually clone series1 and series2 which I feel like I am going to have to do).
ChartArea chartarea1 = new ChartArea();
chartarea1.Name = "chartarea1";
chart1.ChartAreas.Add(chartarea1);
Series series1 = new Series();
series1.Name = "series1";
series1.ChartType = SeriesChartType.Line;
chart1.Series.Add(series1);
chart1.Series["series1"].ChartArea = "chartarea1";
chart1.Series["series1"].Points.DataBindY(someArray1);
ChartArea chartarea2 = new ChartArea();
chartarea2.Name = "chartarea2";
chart1.ChartAreas.Add(chartarea2);
Series series2 = new Series();
series2.Name = "series2";
series2.ChartType = SeriesChartType.Line;
chart1.Series.Add(series2);
chart1.Series["series2"].ChartArea = "chartarea2";
chart1.Series["series2"].Points.DataBindY(someArray2);
ChartArea chartarea3 = new ChartArea();
chartarea3.Name = "chartarea3";
chart1.ChartAreas.Add(chartarea3);
Series series3 = series1;
Series series4 = series2;
series3.Name = "series3";
series4.Name = "series4";
chart1.Series["series3"].ChartArea = "chartarea3";
chart1.Series["series4"].ChartArea = "chartarea3";
chart1.Invalidate();
As of now, when I exclude the code involving chartarea3, series3 and series4, it plots as I would expect: two line graphs, first showing the data from someArray1 and the second below, which shows the data from someArray2. But if I include the the rest of the code, then the form shows a large blank space where chartarea1 and chartarea2 are supposed to be, then chartarea3 below with sommeArray1 and sommeArray2 plotted.
Thanks in advance.
Related
Good day nobbles of programming,
I have a question. I made a code to create chart with datagridview as data source with chartarea1.
Chart chart1 = new Chart();
chart1.Size = new System.Drawing.Size(1024, 768);
ChartArea chartArea1 = new ChartArea();
chartArea1.AxisX.MajorGrid.LineColor = Color.LightGray;
chartArea1.AxisY.MajorGrid.LineColor = Color.LightGray;
chartArea1.AxisX.LabelStyle.Font = new Font("Consolas", 8);
chartArea1.AxisY.LabelStyle.Font = new Font("Consolas", 8);
chartArea1.AxisX.IntervalType = DateTimeIntervalType.Months;
chartArea1.AxisX.Interval = 1;
chart1.ChartAreas.Add(chartArea1);
chart1.Series.Add(new Series());
chart1.Series[0].XValueMember = dataGridView1.Columns[0].DataPropertyName;
chart1.Series[0].YValueMembers = dataGridView1.Columns[1].DataPropertyName;
chart1.DataSource = dataGridView1.DataSource;
chart1.Series[0].ChartType = SeriesChartType.Line;
Now i want to create second chartarea within chart1 with same XValueMember but different YValueMember from different datagridview, for example datagridview2. Is it possible to do it?
Thanks in advance.
Ok, so i tried this:
Chart chart1 = new Chart();
ChartArea chartArea1 = new ChartArea();
Series series1 = new Series();
chart1.DataSource = dataGridView1.DataSource;
chartArea1 = chart1.ChartAreas.Add("ca1");
chartArea1.AxisX.MajorGrid.LineColor = Color.LightGray;
chartArea1.AxisY.MajorGrid.LineColor = Color.LightGray;
chartArea1.AxisX.LabelStyle.Font = new Font("Consolas", 8);
chartArea1.AxisY.LabelStyle.Font = new Font("Consolas", 8);
chartArea1.AxisX.IntervalType = DateTimeIntervalType.Months;
chartArea1.AxisX.Interval = 1;
series1 = chart1.Series.Add("s1");
series1.Points.DataBindXY(dataGridView1.Columns[0].DataPropertyName, dataGridView1.Columns[1].DataPropertyName);
series1.ChartType = SeriesChartType.Line;
chart1.SaveImage("chart.png", ChartImageFormat.Png);
Now getting this error:
Y values cannot be data bound to the string object.
Parameter name: yValues
You should not bind to the whole Chart then but to the Series.Points !
There are many way to use Chart DataBinding
You also should control the Name of each Series and of the ChartAreas; this matters when you want/need to associate the 2nd series with the 2nd chartarea.
The preferred/recommended way to add a ChartArea or a Series is like so:
chartArea1 = chart1.ChartAreas.Add("ca1"); // or any other, more useful name
Series series1 = chart1.Series.Add("s1"); // dito
The association is done like this:
series1.ChartArea = "ca1"; // note the string!!
To bind only one series use..
series1.Points.DataBindXY()
..or some other overload from the table in the link at the top.
I write simple chart web application with this code:
Series Series1 = new Series();
Series Series2 = new Series();
Series1.ChartType = SeriesChartType.Column;
Series1.ChartType = SeriesChartType.Column;
Series1.Points.Add(30);
Series2.Points.Add(40);
Chart1.Series.Add(Series1);
Chart1.Series.Add(Series2);
that code out put is this:
but i want show to user two columns difference and show me some thing this:
how can i write code for that purpose?thanks.
If i am not wrong you are looking for stack type graph, you need to add third series to indicate difference , try following
Series Series1 = new Series();
Series Series2 = new Series();
Series Series3 = new Series();
Series1.ChartType = SeriesChartType.Column;
Series2.ChartType = SeriesChartType.StackedColumn;
Series3.ChartType = SeriesChartType.StackedColumn;
int series1Data=30;
int series2Data=40;
int series3Data=series2Data-series1Data;
series2Data=series1Data;
Series1.Points.Add(series1Data);
Series2.Points.Add(series2Data);
Series3.Points.Add(series3Data);
Chart1.Series.Add(Series1);
Chart1.Series.Add(Series2);
Chart1.Series.Add(Series3);
I cannot seem to get my individual subcharts (contained within my single chart object) to host individual legends for their respective data series. I would like to know if this is possible and, if so, what I can adjust in my code to achieve this effect.
Thanks for your help
Code is as follows:
chart_MyChart.Legends.Clear();
ChartArea chartArea_MyData = new ChartArea("My Data");
ChartArea chartArea_YourData = new ChartArea("Your Data");
ChartArea chartArea_OtherData = new ChartArea("Other Data");
chart_MyChart.ChartAreas.Clear();
chart_MyChart.ChartAreas.Add(chartArea_MyData);
chart_MyChart.ChartAreas.Add(chartArea_YourData);
chart_MyChart.ChartAreas.Add(chartArea_OtherData);
/* Chart Area: My Data */
Series series01 = this.chart_MyChart.Series.Add("My first series");
series01.ChartArea = chartArea_MyData.Name;
Series series02 = this.chart_MyChart.Series.Add("My second series");
series02.ChartArea = chartArea_MyData.Name;
Legend legend01 = new Legend(series01.Name);
Legend legend02 = new Legend(series02.Name);
legend01.DockedToChartArea = chartArea_MyData.Name;
legend02.DockedToChartArea = chartArea_MyData.Name;
chart_MyChart.Legends.Add(legend01);
chart_MyChart.Legends.Add(legend02);
/* Chart Area: Your Data */
Series series03 = this.chart_MyChart.Series.Add("Your first series");
series03.ChartArea = chartArea_YourData.Name;
Series series04 = this.chart_MyChart.Series.Add("Your second series");
series04.ChartArea = chartArea_YourData.Name;
Legend legend03 = new Legend(series03.Name);
Legend legend04 = new Legend(series04.Name);
legend03.DockedToChartArea = chartArea_YourData.Name;
legend04.DockedToChartArea = chartArea_YourData.Name;
chart_MyChart.Legends.Add(legend03);
chart_MyChart.Legends.Add(legend04);
/* Chart Area: Other Data */
Series series05 = this.chart_MyChart.Series.Add("Other series");
series05.ChartArea = chartArea_OtherData.Name;
Legend legend05 = new Legend(series05.Name);
legend05.DockedToChartArea = chartArea_OtherData.Name;
chart_MyChart.Legends.Add(legend05);
foreach(Legend legend in chart_MyChart.Legends)
{
legend.IsDockedInsideChartArea = true;
}
foreach(widget myWidget in some.widget)
{
series01.Points.AddXY(widget.timeStamp, widget.data1);
series02.Points.AddXY(widget.timeStamp, widget.data2);
series03.Points.AddXY(widget.timeStamp, widget.data3);
series04.Points.AddXY(widget.timeStamp, widget.data4);
series05.Points.AddXY(widget.timeStamp, widget.data5);
}
At first glance you seem to be missing the association between the series and the Legend this is from the WebSamples project that you can download here, it really helps to see a full source examples.
In the MultiLegends section, the code looks like this:
// Add a second legend
Legend secondLegend = new Legend("Second");
secondLegend.BackColor = Color.FromArgb(((System.Byte)(220)), ((System.Byte)(255)), ((System.Byte)(255)), ((System.Byte)(255)));
secondLegend.BorderColor = Color.Gray;
secondLegend.Font = this.Chart1.Legends["Default"].Font;
this.Chart1.Legends.Add(secondLegend);
// Associate Series 2 with the second legend
this.Chart1.Series["Series 2"].Legend = "Second";
The only thing that I didn't see in your code is that last line of association.
I need to plot 4 series data to MSChart using column or bar type. Can I plot those 4 series so that the data is overlapped instead of being stacked.
I just found there is a ChartGroup.Overlap property for office Excel.
How can I do it in MSChart? If not, what chart control can do this? Any info will be much appreciated.
C# chart has properties for each series. The "column" chart type has property especially for that overlapping problem
chart_1.Series["col_name"].CustomProperties = "DrawSideBySide=False";
Not sure if this is the ideal solution but if you create two ChartAreas in a chart and then just plot one on top of the other you can overlap series. This requires a lot of fiddling around with positions, sizes, axis etc to get them to line up so requires a bit of effort but produces the following
Chart _chart = new Chart();
TabPage2.Controls.Add(_chart);
_chart.Location = new Point(469, 37);
_chart.Name = "chart1";
_chart.Size = new Size(448, 260);
DataTable dt1 = new DataTable();
dt1.Columns.Add("XVals", typeof(string));
dt1.Columns.Add("YVals1", typeof(int));
dt1.Columns.Add("YVals2", typeof(int));
foreach (string c in "ABCDEF".ToCharArray()) {
dt1.Rows.Add(c, Convert.ToInt32(Math.Ceiling(VBMath.Rnd() * 20)), Convert.ToInt32(Math.Ceiling(VBMath.Rnd() * 20)));
}
ChartArea firstArea = _chart.ChartAreas.Add("First Area");
Series seriesFirst = _chart.Series.Add("First Series");
seriesFirst.ChartType = SeriesChartType.Column;
ChartArea secondArea = _chart.ChartAreas.Add("Second Area");
secondArea.BackColor = Color.Transparent;
secondArea.AlignmentOrientation = AreaAlignmentOrientations.All;
secondArea.AlignmentStyle = AreaAlignmentStyles.All;
secondArea.AlignWithChartArea = firstArea.Name;
secondArea.AxisY.LabelStyle.Enabled = false;
secondArea.AxisX.LabelStyle.Enabled = false;
Series seriesSecond = _chart.Series.Add("Second Series");
seriesSecond.ChartType = SeriesChartType.Column;
seriesSecond.ChartArea = secondArea.Name;
_chart.DataSource = dt1;
seriesFirst.Points.DataBind(dt1.DefaultView, "XVals", "YVals1", null);
seriesSecond.Points.DataBind(dt1.DefaultView, "XVals", "YVals2", null);
//Aligning the Y axis of the two chart areas
//I am assuming here the x values for both series are similar and dont need to be altered
//If using bar chart then x axis would be modifed not the y axis
secondArea.AxisY = firstArea.AxisY;
// *** Set locational values here for your first chart area***
int heightAboveChartArea = 20;
int heightBelowChartArea = 20;
int axisLabelHeight = 40;
int widthLeftOfChartArea = 20;
int widthRightOfChartArea = 20;
int heightPerBar = 20;
int numberOfPoints = _chart.Series(0).Points.Count;
// *** The following code should not normally be modified ***
_chart.ChartAreas(0).Position.X = widthLeftOfChartArea / _chart.Width * 100;
_chart.ChartAreas(0).Position.Width = 100 - (widthRightOfChartArea / _chart.Width * 100) - _chart.ChartAreas(0).Position.X;
_chart.ChartAreas(0).Position.Y = (heightAboveChartArea / _chart.Height * 100);
_chart.ChartAreas(0).Position.Height = 100 - (heightBelowChartArea / _chart.Height * 100) - _chart.ChartAreas(0).Position.Y;
My chart looks all jacked up. For one, there are too many labels along the x axis. For two, it is getting x axis info as a DateTime object. In this case, I would like to have the time of day shown.
So how can I make there be less labels and have the content of the labels be a time instead of a date?
http://i1120.photobucket.com/albums/l493/powerfulcrunch/chart.png
private void drawMinuteGraph(string data)
{
Chart chart = new Chart();
Series series = new Series("default");
series.ChartType = SeriesChartType.Line;
chart.Series.Add(series);
ChartArea chartArea = new ChartArea();
chart.ChartAreas.Add(chartArea);
Axis x = new Axis(chartArea, AxisName.X);
x.LineWidth = 90;
Axis y = new Axis(chartArea, AxisName.Y);
Data[] _data = data.getHistory("History", data);
List<DateTime> dates = new List<DateTime>();
List<double> values = new List<double>();
foreach (Data __data in _data)
{
dates.Add(__data.timestamp);
values.Add(__data.value);
}
chart.Height = 150;
chart.Width = 150;
chart.Series["default"].Points.DataBindXY(dates, values);
flowLayoutPanel.Controls.Add(chart);
}
Use Axis.LabelStyle.Format property.
Format Strings: http://msdn.microsoft.com/en-us/library/az4se3k1.aspx
Read this for how to set intervals
Custom Label Intervals