DataTable Column align to Winform Chart legend - c#

i would like to align the datatable column to MS WinForm chart control legend in x axis like in excel as in the attached image (The tested result of exporting to Excel by using c# and Microsoft.Office.Interop.Excel)
My question is that is there any options/features which MS chart control supports by default to display the chart legend together with datatable as in excel? My users prefer to view in GUI (Winform) instead of exporting to excel.
I have been search through in MSDN as much as I could but still could not find it.
Are there other alternative solutions for this problem?
Table Column Align to MS Chart X-Axis Legend:

Yes and no.
No, there are no options/features that will display the data in a table in the way you show.
But yes, you can write code to achieve that.
I see two options:
You can create a custom legend with cells to hold the table data. See here for a rather similar example!
You can nest the DataGridView, styled to look as you wish, to sit in the chart.
The hard problem in both ways is to make the table align with the data points both initially and also when the chart is being resized.
The code in the link is not doing much, if anything, in this respect.
The 2nd option would have to use the Pre- or PostPaint event anyway to achieve proper positioning, so at least some level of alignment should happen.
Here is an example screenshot:
As you can see I didn't put much effort in styling the DGV. I neither calculated to height not did I add a column to show the Rows/Series colors..
The most interesting code is in the PrePaint event where I
reserve space for the nested DGV
calculate the left and width for the DGV
Here is my code:
private void chart1_PrePaint(object sender, ChartPaintEventArgs e)
{
ca1.Position.Height = 60; // percent of chart!
L1.Position.Y = 90; // percent of chart!
dataGridView1.Parent = chart1;
int y = (int) ca1.AxisY.ValueToPixelPosition(ca1.AxisY.PositionToValue(65));
int x1 = (int) ca1.AxisX.ValueToPixelPosition(ca1.AxisX.Minimum);
int x2 = (int) ca1.AxisX.ValueToPixelPosition(ca1.AxisX.Maximum);
dataGridView1.Top = y;
dataGridView1.Left = x1;
dataGridView1.Width = x2 - x1;
}
L1 is the Legend and ca1 is the ChartArea. This is really just a quick and dirty example that you can code for it but it will take some effort..
Depeding on how flexible and dynamic you want it to work you will have to add (maybe quite a lot) more code..

Related

Control visual styles of individual gridlines

I have a c# RangeBar chart with about 25 labels on the AxisX. Depending on my live data, some of these labels have visible data points in the chart. Typically about 3/4 of the 25 labels don't have any data points. All horizontal gridlines are enabled, which makes the chart a bit cluttered. Especially for data points that are further away on the AxisY, it's difficult to distinguish at a glance to what label on the AxisX they belong.
My idea is to differentiate the AxisX labels that have visible data points either by giving their gridline a different color, a different style, or to completely remove gridlines of AxisX labels that have no corresponding data points. Is this even possible? Because all controllable properties and documentation I have found so far is regarding gridline styles of the entire chart.
Btw: Only showing AxisX labels that have data points is not an option.
Thanks in advance.
To reduce clutter you could use the axis.Interval property.
But each line will still have the same style, either of major or of the minor lines.
You could add VerticalLineAnnotations for selected points or try StripLines. Both can be styled freely.
Here is an example of a normal line chart, with lines randomly added to a few points:
The same result can be achieved by either Annotations or Striplines. The blue lines are StripLine and the red ones Annotations. Here are two functions to add a colored line to a DataPoint:
void AddStripLine(Chart chart, ChartArea ca, DataPoint dp, Color col)
{
Axis ax = ca.AxisX;
StripLine sl = new StripLine();
sl.BorderColor = col;
sl.IntervalOffset = dp.XValue;
sl.Interval = 0;
sl.StripWidth = 0;
sl.BorderWidth = 1;
ax.StripLines.Add(sl);
}
If you look very closely you'll see that the only visual difference is that the former are below, the latter above all other chart elements.
void AddAnnotation(Chart chart, ChartArea ca, DataPoint dp, Color col)
{
Axis ay = ca.AxisY;
VerticalLineAnnotation vl = new VerticalLineAnnotation();
vl.LineColor = col;
vl.AnchorDataPoint = dp;
vl.IsInfinitive = true;
vl.LineWidth = 1;
vl.Height = ay.Maximum - ay.Minimum;
vl.ClipToChartArea = ca.Name;
chart.Annotations.Add(vl);
}
For Bar charts use HorizontalLineAnnotations and anchor to the correct axis...
Using Annotatons is in fact the more natural way, since each is an individual object. StripLines are too, but are repeated at intervals . To avoid visible repetiton each needs to have suitable offsets and intervals to be determined for each. But it isn't hard to do either way.
Also note that the both types of lines lines are anchored to their DataPoints and will move with them e.g. when chart is resized..

How to make sure endlabels are always visible on c# chart x axis

I have created a chart in the image below and I need to insert in addition to the existing labels, the end labels on the extreme left and right of the x-axis. There are numerous datapoints and therefore I cannot set the interval to 1 for the labels as they'll clutter the axis. I have already tried setting the property
chartHistory.ChartAreas[0].AxisX.LabelStyle.IsEndLabelVisible = true;
but it doesn't seem to work. How can I achieve this?
You may try:
chartHistory.ChartAreas[0].AxisX.IsMarginVisible = true;
chartHistory.ChartAreas[0].AxisX.LabelStyle.IsEndLabelVisible = true;
Or probably you will have to add the labels yourself,
you can either use DataPoint.AxisLabel:
chartHistory.Series[0].Points[0].AxisLabel = "5/4/2010";
or more flexibly:
chartHistory.Series[0].Points[0].AxisLabel =
System.DateTime.FromOADate(chartHistory.Series[0].Points[0].XValue).ToShortDateString();
(and the same for the last point in series)
or you can add a custom label to the AxisX control:
chartHistory.ChartAreas[0].AxisX.CustomLabels.Add(0, 20, "5/4/2010");
See also this answer and this answer.

How to display a chart in C# that has no data points?

I'm making a candlestick chart in C# for a bitcoin trading helper. When the form loads, the chart is just an empty white space because there are no data points initially. Is there any way to display the grid lines and the axes when there are no data points? Thank you!
EDIT: A data point is added ~1 minute after loading, so aesthetically I think it would look better to have the empty grid lines and axes than to simply hide the chart altogether.
This is all I've added to the load method:
chart1.Titles.Add("Candlestick Chart");
//chart grid lines colors
chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.Gray;
I think you can add empty point for the Chart series data points
chart3.Series[0].Points.Add();
chart3.Series[0].Points[0].IsEmpty = true;
check this: https://www.syncfusion.com/kb/73/how-do-i-set-emptypoint-for-the-chart-series-data-points

How to control winform mschart legend text alignment c#?

How does one set the alignment of text within a chart legend object? I've tried using:
myChartName.Legends["mySeriesName"].Alignment = stringAlignment.Near
With no effect. I've also tried to create custom legend items, again resulting in no effect. Text is ALWAYS centered (along with the series marker) in the legend "box". The only text I have been able to align is the title, but I don't need titles in my application.
My research to date says the legend object is basically a table with (by default) two cells. If that is the case there should be a way to access those cells and manipulate them as table cells. So, what gives? Why can't I access the text alignment properties of the legend object? Clearly, there is something I'm missing, but for the life of me I can't seem to figure this out. Quite frustrating.
Problem solved. The CustomItem approach wasn't working either, so I tried using the LegendCellColumn Class.
I changed the LegendStyle from Column to Row, then added two CellColumns, one for the series symbol and one for the legend text. Set the alignment, margins, and column widths (that turned out to be the trick), and voila; a legend that looks like I want. Here's the code for anyone with a similar issue.
chartSel.Legends[ySeries.Name].CellColumns.Add(new LegendCellColumn("", LegendCellColumnType.SeriesSymbol, ""));
chartSel.Legends[ySeries.Name].CellColumns[0].Alignment = ContentAlignment.TopLeft;
chartSel.Legends[ySeries.Name].CellColumns[0].Margins = new System.Windows.Forms.DataVisualization.Charting.Margins(0, 0, 1, 1);
chartSel.Legends[ySeries.Name].CellColumns[0].MinimumWidth = 250;
chartSel.Legends[ySeries.Name].CellColumns[0].MaximumWidth = 250;
chartSel.Legends[ySeries.Name].CellColumns.Add(new LegendCellColumn("", LegendCellColumnType.Text, ySeries.Name));
chartSel.Legends[ySeries.Name].CellColumns[1].Alignment = ContentAlignment.MiddleLeft;
chartSel.Legends[ySeries.Name].CellColumns[1].Margins = new System.Windows.Forms.DataVisualization.Charting.Margins(0, 0, 1, 1);
chartSel.Legends[ySeries.Name].CellColumns[1].MinimumWidth = 1500;
chartSel.Legends[ySeries.Name].CellColumns[1].MaximumWidth = 1500;
It's probably not the most efficient way to do it, but it works. Technically, the legend symbol and text are still centered in the object, but because I'm forcing the widths of the two columns it has the appearance of being left-justified.
Hopefully, this may help another newbie like me avoid days of consternation.
My understanding is that Legend alignment relates to the Docking property, not really how the text is aligned within the legend. So setting Alignment to Near means positioning the legend box near the Docking direction.
It is quite hard to explain this textually. The MS Chart Samples have a subsection named Chart features -> Legends -> Style and Auto Positioning which will help you play with those two properties and understand how they are meant to work.
For inner legend alignment, you may need to use Legend.CustomItems and define LegendCell individually.
chart.Legends["Default"].CustomItems.Clear();
chart.Legends["Default"].CustomItems.Add(new LegendItem("LegendItem", Color.Red, ""));
chart.Legends["Default"].CustomItems[0].Cells.Add(new LegendCell(LegendCellType.Text, "My text", ContentAlignment.MiddleLeft));
This is described inside the Chart features -> Legends -> Legend Cells section of the samples.
While continuing to try to figure this out I stumbled on this tidbit of info from the following MSDN library page:
http://msdn.microsoft.com/en-us/library/dd456711(v=vs.100).aspx
"NOTE: You cannot adjust the individual legend items and cells in the Chart.Legends collection. To adjust them, use custom legend items."
So, back to the CustomItem route. I've got this code gleaned from several sources (including you, Dominique, thanks):
chartSel.Legends.Add(ySeries.Name);
chartSel.Series[ySeries.Name].IsVisibleInLegend = false;
chartSel.Legends[ySeries.Name].CustomItems.Clear();
LegendItem li = new LegendItem();
li.ImageStyle = LegendImageStyle.Line;
li.Cells.Add(LegendCellType.SeriesSymbol, "", ContentAlignment.TopLeft);
li.Cells[0].BackColor = Color.CornflowerBlue; //color is only to see the cell bounds
li.Cells.Add(LegendCellType.Text, ySeries.Name, ContentAlignment.TopLeft);
li.Cells[1].BackColor = Color.Aquamarine; //color is only to see the cell bounds
chartSel.Legends[ySeries.Name].CustomItems.Add(li);
From what I can find it should work, but it doesn't. It results in a legend object with two cells; the first is empty and the second has left-justified text. I tried to post an image of it, but the system says I'm not yet worthy.
Why there is no line for the series symbol is also a mystery, but that's another problem to solve. The text justification issue is my main concern at the moment. It looks like the text within the cells is left-justified as desired, but the cells themselves are centered in the legend object; not what I wanted. I want those cells to be left-justified in the object too, so the first cell is against the left edge of the legend object.
Ideas?

how to change the direction of X-axis label in ms charts

Hi I am using Ms chart control in winforms application for displaying values according to dates
I need to change the x-axis label values(Dates) direction horizantal to vertical
I have searched so many properties but i did not find any solution for this.
Any one help me on this problem
Many Thanks ....
As I understand your question - you are asking how to rotate the chart label to display vertically.
You can rotate the x-axis label as follows:
chart1.ChartAreas[0].AxisX.LabelStyle.Angle = -90;
This assumes you have associated your series with the first chart area, which is the default without modification when using the Winforms designer.
The following images shows how the chart would look before the code above is applied, the second image shows how it appears after the code is applied.
Let me know if this is not what you are trying to do and I will post an updated answer.
Before rotation
After Rotation
Edit: Another answer added after my initial post mentions in certain situations it may be important to set chartArea1.AxisX.IsLabelAutoFit = false;
If you have not already done so, get the chart samples from microsoft:
http://archive.msdn.microsoft.com/mschart
Then check the section on Labels
Chart Features > Labels
To answer your question directly, set the angle in LabelStyle, and don't forget to disable autofit
chartArea1.AxisX.IsLabelAutoFit = false;
chartArea1.AxisX.LabelStyle.Angle = 90;

Categories