Plot Area Gradient in MS Chart - c#

I'm currently working with MS Chart for the first Time, and i want my C# Programm to draw a grey to white gradient under my graph, just like this (on the left is the current version, on the right what I want to do):
EDIT: Thank you Dmitry for including the Image from my Link :)
The only gradient Option I found for MS Chart so far is the Background.
This is my basic configuration of the chart so far:
chart.Series.Add(MsChartHelper.CreateSeries(chartData, SeriesChartType.Line));
chart.ChartAreas.Add(MsChartHelper.CreateChartArea());
chart.Series[0].BorderWidth = 1;
chart.Series[0].BorderColor = fnBlue;
chart.Series[0].Font = new System.Drawing.Font("Verdana", 7F, System.Drawing.FontStyle.Regular);
chart.ChartAreas[0].AxisY.Minimum = 92;
chart.ChartAreas[0].AxisY.Maximum = 96;
chart.ChartAreas[0].AxisY.Interval = 1;
chart.ChartAreas[0].AxisY.LabelStyle.Font = new System.Drawing.Font("Verdana", 7F, System.Drawing.FontStyle.Regular);
chart.ChartAreas[0].AxisX.LabelStyle.Font = new System.Drawing.Font("Verdana", 7F, System.Drawing.FontStyle.Regular);
chart.ChartAreas[0].AxisX.Interval = 36;
chart.ChartAreas[0].AxisX.IntervalType = DateTimeIntervalType.Days;
chart.ChartAreas[0].AxisX.IsInterlaced = true;
chart.ChartAreas[0].AxisX.InterlacedColor = fnGray;
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
DataPoint min = chart.Series[0].Points.FindMinByValue();
min.MarkerStyle = MarkerStyle.None;
min.IsValueShownAsLabel = true;
DataPoint max = chart.Series[0].Points.FindMaxByValue();
max.MarkerStyle = MarkerStyle.None;
max.IsValueShownAsLabel = true;

Ok, finally I figured out, how to achieve this. So if someone has the same Issue for some reason, this is how you do it:
Your Charttype hast to be Area
chart.Series.Add(MsChartHelper.CreateSeries(chartPlotData, SeriesChartType.Area));
After this, you can add a gradient and set a border color:
chart.Series[0].BackGradientStyle = GradientStyle.TopBottom;
chart.Series[0].Color = Color.FromArgb(125, 110, 110, 110);
chart.Series[0].BackSecondaryColor = Color.FromArgb(0, 255, 255, 255);
chart.Series[0].BorderColor = System.Drawing.ColorTranslator.FromHtml("#AA3131");
chart.Series[0].BorderDashStyle = ChartDashStyle.Solid;
chart.Series[0].BorderWidth = 1;
I hope this helps :)

Related

How Do I Get The Scale of The Secondary Axis to be Based on My Series Values?

I'm using System.Web.UI.DataVisualization. Charting to create charts in MVC.
I have a chart displaying values in a StackedColumn100 SeriesChartType with the corresponding y-axis values on the primary y-axis on the left side.
Since it is a 100% stacked column series, the primary y-axis is scaled from 0 to 100.
I have then added a secondary series in the form of a Line SeriesChartType tied to a secondary axis (on the right side). I would like this axis to adjust its scale based on the values in the series but it doesn't. No matter what the highest value of this series is, the secondary y-axis also has a scale between 0 to 100.
If I manually set the maximum value for the secondary y-axis the following way:
chart.ChartAreas[0].AxisY2.Maximum = 20;. It works but I don't want to do that since the maximum value can differ greatly based on the search criteria used.
I have really tried to find a solution for this but I can't. According to the documentation and samples it seems that the scale should be based on the series values but I don't get it to work that way. Any help would be greatly appreciated!
Below is a stand alone test function that recreates the problem. I call the function from my view with the following line:
<p><img src="#Url.Action("CreateChart_TestSecondaryAxis")" /> </p>
public FileResult CreateChart_TestSecondaryAxis()
{
System.Web.UI.DataVisualization.Charting.Chart chart = new System.Web.UI.DataVisualization.Charting.Chart();
chart.Width = 800;
chart.Height = 400;
chart.BackColor = Color.FromArgb(211, 223, 240);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackSecondaryColor = Color.White;
chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 1;
chart.Palette = ChartColorPalette.BrightPastel;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
ChartArea chartArea = new ChartArea();
chartArea.Name = "TestSecondaryAxis";
chartArea.BackColor = Color.Transparent;
chartArea.AxisX.IsLabelAutoFit = false;
chartArea.AxisY.IsLabelAutoFit = false;
chartArea.AxisX.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LabelStyle.Font =
new Font("Verdana,Arial,Helvetica,sans-serif",
8F, FontStyle.Regular);
chartArea.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
chartArea.AxisX.Title = "Airport";
chartArea.AxisY.Title = "LandingConf";
chartArea.AxisY.TextOrientation = TextOrientation.Rotated270;
chartArea.AxisX.LabelStyle.IsEndLabelVisible = true;
chart.ChartAreas.Add(chartArea);
Series seriesPrimaryAxisConf3 = new Series();
seriesPrimaryAxisConf3.Name = "Conf 3";
seriesPrimaryAxisConf3.IsValueShownAsLabel = false;
seriesPrimaryAxisConf3.Color = Color.Blue;
seriesPrimaryAxisConf3.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConf3.BorderWidth = 2;
seriesPrimaryAxisConf3.ChartArea = "TestSecondaryAxis";
DataPoint point;
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesPrimaryAxisConf3.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConf3);
Series seriesPrimaryAxisConfFull = new Series();
seriesPrimaryAxisConfFull.Name = "Conf Full";
seriesPrimaryAxisConfFull.IsValueShownAsLabel = false;
seriesPrimaryAxisConfFull.Color = Color.Red;
seriesPrimaryAxisConfFull.ChartType = SeriesChartType.StackedColumn100;
seriesPrimaryAxisConfFull.BorderWidth = 2;
seriesPrimaryAxisConfFull.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { 11-i };
seriesPrimaryAxisConfFull.Points.Add(point);
}
chart.Series.Add(seriesPrimaryAxisConfFull);
Series seriesSecondaryAxisNoOfFlights = new Series();
seriesSecondaryAxisNoOfFlights.Name = "NoOfFLights";
seriesSecondaryAxisNoOfFlights.IsValueShownAsLabel = false;
seriesSecondaryAxisNoOfFlights.Color = Color.Red;
seriesSecondaryAxisNoOfFlights.ChartType = SeriesChartType.Line;
seriesSecondaryAxisNoOfFlights.BorderWidth = 2;
seriesSecondaryAxisNoOfFlights.ChartArea = "TestSecondaryAxis";
for (int i = 1; i < 11; i++)
{
point = new DataPoint();
point.AxisLabel = "Airport" + i.ToString();
point.YValues = new double[] { i };
seriesSecondaryAxisNoOfFlights.Points.Add(point);
}
chart.Series.Add(seriesSecondaryAxisNoOfFlights);
chart.Series["NoOfFLights"].YAxisType = AxisType.Secondary;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.LineColor = Color.Transparent;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorGrid.Enabled = false;
chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorTickMark.Enabled = false;
MemoryStream ms = new MemoryStream();
chart.SaveImage(ms);
return File(ms.GetBuffer(), #"image/png");
}
MSChart is a nice control but unfortunately Microsoft has always failed to properly document it.
And with the latest changes at MSDN things have gone from bad to worse, so I can't actually point to the rules that go for the various ChartTypes.
In your case I deduct this (rather wacky) rule:
To attach a non 100%-series to an indepently scaled secondary y-axis
it must be the first series but the stacked series still must be added
first.
So, if you want to get a result like this:
..you need to adapt the code. Here are the changes and additions needed..:
First we have to insert the line series at the front but do that after the stack100 series have beeen added..:
chart.Series.Insert(0, seriesSecondaryAxisNoOfFlights); // instead of adding it
Next we need to owner-draw the line as it would get burried under the columns otherwise.
Code the PostPaint event like this:
private void Chart_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart; //*
Series s = chart.Series[0]; // make sure to pick the right one!
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY2; // !!
var pts = s.Points.Select(x =>
new PointF((float)ax.ValueToPixelPosition(x.XValue),
(float)ay.ValueToPixelPosition(x.YValues[0])));
using (Pen pen = new Pen(s.Color, s.BorderWidth))
e.ChartGraphics.Graphics.DrawLines(pen, pts.ToArray());
}
For this to work the series need valid x-values. So add this line:
point.XValue = i; // set both x and y-values!
I also added a few nudges to the axis positioning:
ChartArea ca = chart.ChartAreas["TestSecondaryAxis"];
ca.AxisY.Maximum = 100;
ca.AxisX.Minimum = 0.5;
ca.AxisX.IntervalOffset = 0.5;

How to change the MS Charts label font size in C#?

I have created few MS charts. Below code extracted from my application. It is working fine. but I want to increase the font size of label. How can I change the font size of label ?
Thanks.
Series MIN = Chart2.Series.Add("Minimum");
MIN.Points.DataBindXY(listVersion, MIN_list[j]);
MIN.ChartType = SeriesChartType.Line;
MIN.Color = Color.Red;
MIN.BorderWidth = 3;
MIN.IsValueShownAsLabel = true;
MIN.LabelBackColor = System.Drawing.Color.Red;
MIN.LabelForeColor = System.Drawing.Color.White;
You can change the Font individually for each DataPoint:
MIN.Points[0].Font = new System.Drawing.Font("Consolas", 10f);
MIN.Points[1].Font = new System.Drawing.Font("Consolas", 12f);
MIN.Points[2].Font = new System.Drawing.Font("Consolas", 14f);
Or you can change the Font for all Labels of your series:
MIN.Font = new System.Drawing.Font("Times", 16f);
Chart2.ChartAreas.["yourChartArea"].AxisY.LabelAutoFitStyle = LabelAutoFitStyles.None;
Chart2.ChartAreas.["yourChartArea"].AxisX.LabelStyle.Font
= new System.Drawing.Font("Trebuchet MS", 2.25F, System.Drawing.FontStyle.Bold);

Add annotations in MS chart (e.g. (10, 20) (20, 39) etc) and horizontal Scroll Bar

I want to add text(say, annotations) in MS chart(winforms) like (10, 20) , (30, 40) where I already have a scroll bar.
I can able to draw strings(graphics.drawstring) in Chart, but on scrolling the horizontal scroll bar, the text which I have drawn remains static and immovable.
On scrolling the scrollbar, the text which I have drawn also should move along with my horizontal scrolling.
My code follows:
chart2.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart2.BorderlineColor = System.Drawing.Color.FromArgb(26, 59, 105);
chart2.BorderlineWidth = 3;
chart2.BackColor = Color.White;
chart2.ChartAreas.Add("chtArea");
chart2.ChartAreas[0].AxisX.Title = "Category Name";
chart2.ChartAreas[0].AxisX.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].AxisY.Title = "UnitPrice";
chart2.ChartAreas[0].AxisY.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].BorderDashStyle = ChartDashStyle.Solid;
chart2.ChartAreas[0].BorderWidth = 2;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.Enabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserEnabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserSelectionEnabled = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Zoomable = false;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.IsPositionedInside = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Size = 20;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Seconds;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 1;
chart2.Legends.Add("UnitPrice");
chart2.Series.Add("UnitPrice");
chart2.Series[0].ChartType = SeriesChartType.Line;
Random rand = new Random();
var valuesArray = Enumerable.Range(0, 500).Select(x => rand.Next(0, 100)).ToArray();
for (int i = 0; i < 500; i++)
{
chart2.Series["UnitPrice"].Points.AddXY(i+10, valuesArray[i]);
}
I tried TextAnnotaions, Line annotations, etc Nothing helped me.
Then I tried drawing dynamic labels inside MS chart also. Labels remain immovable while scrolling horizontal scroll bar.
This code works perfectly in your machine also.
Sounds a lot as if you want to add TextAnnotations.
If you want them to stick with your data points you should anchor them to the points they shall stay with.
Here are a few examples:
// directly anchored to a point
TextAnnotation TA1 = new TextAnnotation();
TA1.Text = "DataPoint 222";
TA1.SetAnchor(chart2.Series["UnitPrice"].Points[222]);
chart2.Annotations.Add(TA1);
// anchored to a point but shifted down
TextAnnotation TA2 = new TextAnnotation();
TA2.Text = "DataPoint 111";
TA2.AnchorDataPoint = chart2.Series["UnitPrice"].Points[111];
TA2.AnchorY = 0;
chart2.Annotations.Add(TA2);
// this one is not anchored on a point:
TextAnnotation TA3 = new TextAnnotation();
TA3.Text = "At 50% width BC";
TA3.AnchorX = 50; // 50% of chart width
TA3.AnchorY = 20; // 20% of chart height, from top!
TA3.Alignment = ContentAlignment.BottomCenter; // try a few!
chart2.Annotations.Add(TA3);
By default they either anchor to DataPoints or are positioned in % of the chart size.
It is also possible to set the positions according to pixel coordinates, but for this you need to calculate the positions each time the chart changes its view!
See here for an example how to transform chart data positions to chart control coordinates and vice versa.. (Not really recommended, though)

How can the UltraChart of Infragistics do even better?

I need to convince my management that we can do very nice plots using infragistics, up to know this is what I have:
In order have that here is my code :
//Set the chart titles
ChartPureAlpha.TitleTop.Text = TickerName;
//Set Chart legend
this.ChartPureAlpha.Legend.Visible = true;
this.ChartPureAlpha.Legend.Location = LegendLocation.Right;
this.ChartPureAlpha.Legend.Margins.Left = 5;
this.ChartPureAlpha.Legend.Margins.Right = 10;
this.ChartPureAlpha.Legend.Margins.Top = 15;
this.ChartPureAlpha.Legend.Margins.Bottom = 90;
this.ChartPureAlpha.Legend.SpanPercentage = 15;
this.ChartPureAlpha.LineChart.TreatDateTimeAsString = false;
this.ChartPureAlpha.ChartType = ChartType.ScatterChart;
this.ChartPureAlpha.ScatterChart.ConnectWithLines = true;
//ChartPureAlpha.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
this.ChartPureAlpha.Axis.X.Labels.ItemFormatString = "<ITEM_LABEL:dd-MM-yyyy>";
this.ChartPureAlpha.Axis.X.Labels.SeriesLabels.Font = new System.Drawing.Font("Verdana", 25);
this.ChartPureAlpha.Axis.X.Labels.SeriesLabels.Visible = true;
this.ChartPureAlpha.Axis.X.Labels.SeriesLabels.OrientationAngle = 315;
//ChartPureAlpha.Axis.X.TickmarkInterval = 1;
//ChartPureAlpha.Axis.X.TickmarkIntervalType = AxisIntervalType.Days;
//ChartPureAlpha.Axis.X.TickmarkStyle = AxisTickStyle.DataInterval;
// axis label
//ChartPureAlpha.TitleBottom.Text = "Date";
//ChartPureAlpha.TitleBottom.HorizontalAlign = StringAlignment.Center;
//ChartPureAlpha.TitleLeft.Text = "Raw Alpha)";
//ChartPureAlpha.TitleLeft.HorizontalAlign = StringAlignment.Center;
// Create and add series
ChartPureAlpha.Series.Add(dowjones);
I want to know how to :
reduce marker size
have the whole date (not truncated)
change the label font
After a few looking through the official 2011.2 infragistics help i found some issues for you:
reduce marker size: use the IconSize Property (Auto, Large, Medium, Small)
change the label font:this.ultraChart1.TitleTop.Font = new Font("Arial", 12, FontStyle.Bold | FontStyle.Underline, GraphicsUnit.Point);
have the whole date (not truncated): If the label is "My Text" and the Date is 5/10/2005 it would format the label as follows: "<ITEM_LABEL><DATA_VALUE:MMM-dd-yyyy>" = MyText May 10, 2005
hope that helps
Infragistics is already trying quite hard to advertise their charts, so why don't you just reuse their marketing material ?

How can I avoid that ZedGraph relabels my YAxis, dividing by 1000?

I am creating a C# visual studio forms application that uses zedgraph to chart the data that the program collects but I am running into the following issue when plotting the data:
My y-axis values are usually in the 100,000+ range so when zed graph plots the value it labels the y-axis labels with stuff like 0, 10, 15, 20, 25 and then on the y-axis label it will append "(10^3)" to the title and will plot the values accordingly. What I want to do is have it label the y-axis either with values like 0, 10,000, 15,000, 20,000 etc or 0, 10k, 15k, 20k and so on and not have it adjust the y-axis title.
I tried setting YAxis.Scale.MajorStep = double.Parse("10000"); but the only effect that has is to add a ton of more tick lines on the y-axis but no other effect. Here is my code that graphs the data:
private void createGraph()
{
GraphPane myPane = zdc_graph.GraphPane;
myPane.CurveList.Clear();
myPane.GraphObjList.Clear();
myPane.Title.Text = this.monitoredHost.hostName + "\nWorkState[" +
this.monitoredHost.currentWorkState + "]";
myPane.XAxis.Title.Text = "";
myPane.YAxis.Title.Text = "OPS Per Second";
myPane.YAxis.Scale.FontSpec.FontColor = Color.Blue;
myPane.YAxis.Title.FontSpec.FontColor = Color.Blue;
myPane.YAxis.Scale.MaxAuto = true;
myPane.Y2Axis.Title.Text = "Reading";
myPane.Y2Axis.IsVisible = true;
myPane.Y2Axis.Scale.FontSpec.FontColor = Color.Red;
myPane.Y2Axis.Title.FontSpec.FontColor = Color.Red;
myPane.XAxis.Type = AxisType.Date;
myPane.XAxis.Scale.Format = "T";
myPane.XAxis.Scale.MajorUnit = DateUnit.Second;
myPane.YAxis.Scale.Min = 0;
myPane.YAxis.Scale.MajorStep = double.Parse("10000");
myPane.Y2Axis.Scale.Min = 0;
LineItem kpiCurve = myPane.AddCurve("OPS Per Second",
this.monitoredHost.graphKpiList,
Color.Blue,SymbolType.Circle);
LineItem pwrCurve = myPane.AddCurve("Reading",
this.monitoredHost.graphPwrList, Color.Red,
SymbolType.Circle);
kpiCurve.Line.Width = 2.0F;
kpiCurve.Symbol.Size = 4.0F;
kpiCurve.Symbol.Fill = new Fill(Color.White);
pwrCurve.Line.Width = 2.0F;
pwrCurve.Symbol.Size = 4.0F;
pwrCurve.Symbol.Fill = new Fill(Color.White);
pwrCurve.IsY2Axis = true;
myPane.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 210), -45F);
zdc_graph.AxisChange();
zdc_graph.Refresh();
}
I hope this makes sense. Thanks for the help.
ZedGraph is attempting to detect magnitude and simplify the graph. You can turn this off with the following:
myPane.YAxis.Scale.MagAuto = false;
This will result in y-axis labels like 100000.
If you want to format the label with a separator comma like 100,000:
myPane.YAxis.Scale.Format = "#,#";
Finally, if you prefer to show 100k, you'll need to subscribe to the ScaleFormatEvent and return your own format, like this:
myPane.YAxis.ScaleFormatEvent += new Axis.ScaleFormatHandler(YAxis_ScaleFormatEvent);
string YAxis_ScaleFormatEvent(GraphPane pane, Axis axis, double val, int index)
{
return String.Format("{0}k", val / 1000);
}
I am having similar problem. So applying your method it works on the application but i also want to print out the graph in a PDF file (using MigraDoc) but it does work.
public Bitmap printGraphPane()
{
ZedGraphControl graph = new ZedGraphControl();
GraphPane newGP = myPane.GraphPane;
//newGP.YAxis.Scale.Mag = 0;
//newGP.YAxis.Scale.Format = "#";
//newGP.YAxis.ScaleFormatEvent += new Axis.ScaleFormatHandler(YAxis_ScaleFormatEvent);
Bitmap bit = new Bitmap(newGraph.Width, newGraph.Height);
newGraph.ClientSize = bit.Size;
newGraph.DrawToBitmap(bit, new Rectangle(0, 0, newGraph.Width, newGraph.Height));
return bit;
}

Categories

Resources