Stripline label - c#

Currently, I have been doing a project on graphs on windows form. Now I have something to ask.
Is there by any chance a way to move the Stripeline label out of my chart and not have it in the chart to something like this What I expect it to be and also make my stripeline tinner because it is too thick
till date what i do
What I expect it to be
This is my stripline code in case you need it
StripLine stripLine1 = new StripLine();
stripLine1.StripWidth = 0.01;
stripLine1.BorderColor = System.Drawing.Color.Blue;
stripLine1.BorderWidth = 0;
stripLine1.BorderDashStyle = ChartDashStyle.Solid;
stripLine1.IntervalOffset = Convert.ToDouble(textBox7.Text);
stripLine1.BackColor = System.Drawing.Color.Blue;
stripLine1.Text = "x̅";
chart1.ChartAreas[0].AxisY.StripLines.Add(stripLine1);

No, StripLines are drawn inside their ChartArea only.
There are at least two options:
You can display their Text outside of it by coding a PaintXXX event, maybe like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
ChartArea ca = chart1.ChartAreas[0];
Axis ax = ca.AxisX;
Axis ay = ca.AxisY;
Graphics g = e.ChartGraphics.Graphics;
foreach (StripLine sl in ay.StripLines)
{
double v = (sl.Interval != double.NaN ? sl.Interval : 0) + sl.IntervalOffset;
TextRenderer.DrawText(g, sl.Text, sl.Font, new Point(
(int)ax.ValueToPixelPosition(ax.Maximum),
(int)ay.ValueToPixelPosition(v)),Color.Black);
}
}
Fine-tuning the position, maybe by honoring the TextAlignment properties is up to you..
Note that this will now display the text twice; a simple solution it to make the original label transparent:
YourStripLine.ForeColor = Color.Transparent;
Also note that drawn graphics will not get exported if you serialize the chart.
An alternative would be to set the secondary y-axis and add the labels as CustomLabels. On second thought, I think this is preferrable, at least if you don't need the secondary y-axis.
Here I do it for one stripline:
Axis ay2 = chart1.ChartAreas[0].AxisY2;
ay2.Enabled = AxisEnabled.True;
ay2.LineColor = Color.Transparent;
CustomLabel cl = new CustomLabel();
cl.Text = stripLine.Text;
double v = (stripLine.Interval != double.NaN ? stripLine.Interval : 0)
+ stripLine.IntervalOffset;
cl.FromPosition = v - 0.001;
cl.ToPosition = v + 0.001;
ay2.CustomLabels.Add(cl);
You here also will want to make the original text transparent.

Related

How to draw vertical line on mschart that fills graph but isn't infinite?

I am trying to draw a vertical line that is anchored to a point. I tried to use the height of my Y axis which is fixed to draw the line, but it wasn't centered correctly. So right now I have an infinite line, but that I want is the line to just fill the graph like so
VerticalLineAnnotation lineannot = new VerticalLineAnnotation();
lineannot.AnchorDataPoint = chart.Series[item].Points.Last();
lineannot.LineColor = Color.Red;
lineannot.Width = 3;
lineannot.Visible = true;
lineannot.IsInfinitive = true;
chart.Annotations.Add(lineannot);
IsInfinitive is complemented by ClipToChartArea; you can set the line to be clipped to a ChartArea like this:
lineannot.ClipToChartArea = chart.ChartAreas[item].Name;
assuming item is the right area name or index..
Note that ClipToChartArea takes the name of the chart area!
This is the simplest way to do it.
It is also possible to control an annotation's position and size directly:
// Note that directly after adding points this will return NaN:
double maxDataPoint = chart1.ChartAreas[0].AxisY.Maximum;
double minDataPoint = chart1.ChartAreas[0].AxisY.Minimum;
LineAnnotation annotation2 = new LineAnnotation();
annotation2.IsSizeAlwaysRelative = false;
annotation2.AxisX = chart1.ChartAreas[0].AxisX;
annotation2.AxisY = chart1.ChartAreas[0].AxisY;
annotation2.AnchorY = minDataPoint;
annotation2.Height = maxDataPoint - minDataPoint;;
annotation2.Width = 0;
annotation2.LineWidth = 2;
annotation2.StartCap = LineAnchorCapStyle.None;
annotation2.EndCap = LineAnchorCapStyle.None;
annotation2.AnchorX = 21; // <- your point
annotation2.LineColor = Color.Pink; // <- your color
chart1.Annotations.Add(annotation2);

Show offset of StripLine as a label on the Y-Axis

I have this chart in my WinForms application:
and I need to show the reference number of the red line (in this case "37")
When I tried to add a CustomLabel to the Y Axis, all the other numbers disappeared.
I tried changing the RowIndex of the label to 2, but here's the result:
it only shows an inverted "3" instead of a straight "37"
Here's what I need:
how can I do this?
You can use a TextAnnotation to show a data value :
ChartArea ca = chart1.ChartAreas[0];
TextAnnotation ta = new TextAnnotation();
DataPoint dp0 = Series2.Points[0]; // pick a datapoint!
ta.Text = dp0.YValues[0] + "";
ta.ForeColor = dp0.Color;
ta.AxisY = ca.AxisY;
ta.Y = dp0.YValues[0];
ta.X = 5; // pick a value that fits with your y-axis!
ta.Alignment = ContentAlignment.MiddleLeft;
chart1.Annotations.Add(ta);

Mark the regions over the zed graph

Currently I am using ZedGraph to display my curve. I want to mark the particular regions of the curve over the ZedGraph control and label it like follows.
Note: I need different type of markings in the X and Y axis based on the text size.
Thanks for your help in advance.
You have two options,
1) Use BoxObject to draw at a specific region as follows
and you can use the source code as follows:
private void Form1_Load(object sender, EventArgs e)
{
// Create an instance of Graph Pane
GraphPane myPane = zedGraphControl1.GraphPane;
// Build a PointPairList with points based on Sine wave
PointPairList list = new PointPairList();
for (double i = 0; i < 36; i++)
{
double x = i * 10.0 + 50.0;
double y = Math.Sin(i * Math.PI / 15.0) * 16.0;
list.Add(x, y);
}
// Hide the legend
myPane.Legend.IsVisible = false;
// Add a curve
LineItem curve = myPane.AddCurve("label", list, Color.Red, SymbolType.Circle);
curve.Line.Width = 1.5F;
curve.Symbol.Fill = new Fill(Color.White);
curve.Symbol.Size = 5;
// Make the XAxis start with the first label at 50
myPane.XAxis.Scale.BaseTic = 50;
// Fill the axis background with a gradient
myPane.Chart.Fill = new Fill(Color.White, Color.SteelBlue, 45.0F);
// Draw Region 1
drawRegion(list[0].X, list[10].X,"Positive Cycle");
// Calculate the Axis Scale Ranges
zedGraphControl1.AxisChange();
// Refresh to paint the graph components
Refresh();
}
private void drawRegion(double xMin, double xMax, string regName)
{
GraphPane pane = zedGraphControl1.GraphPane;
BoxObj box = new BoxObj(xMin,20, xMax, 40.0, Color.Empty, Color.LightSteelBlue);// Color.FromArgb(225, 245, 225));
box.Location.CoordinateFrame = CoordType.AxisXYScale;
box.Location.AlignH = AlignH.Left;
box.Location.AlignV = AlignV.Top;
// place the box behind the axis items, so the grid is drawn on top of it
box.ZOrder = ZOrder.E_BehindCurves;//.D_BehindAxis;//.E_BehindAxis;
pane.GraphObjList.Add(box);
// Add Region text inside the box
TextObj myText = new TextObj(regName, 160, -15);
myText.Location.CoordinateFrame = CoordType.AxisXYScale;
myText.Location.AlignH = AlignH.Right;
myText.Location.AlignV = AlignV.Center;
myText.FontSpec.IsItalic = true;
myText.FontSpec.IsBold = false;
myText.FontSpec.FontColor = Color.Red;
myText.FontSpec.Fill.IsVisible = false;
myText.FontSpec.Border.IsVisible = false;
pane.GraphObjList.Add(myText);
zedGraphControl1.Refresh();
}
2) This is a bit difficult but do-able, Draw individual vertical lines discussed here: 1, 2 and add the required text etc.
I suggest you to use the option 1, which is lot easier than 2 !

winform mschart hittest not finding legend

I have a charting application that has an overlay function which reassigns the 'from' chart series to the 'to' chart using this code :
chTo.Series.Add(chFrom.Series[s]); //Reassign series to new chart
chTo.Legends.Add(chFrom.Legends[s]); //Reassign legend to new chart
Works great. However, I am trying to implement tooltips for the legends and am running into an issue where only the first legend in the chart will show tooltips. When I do a hittest only the first legend is recognized. All subsequent legends, while visible on the chart, aren't 'seen' to the hittest method. I'm thinking this is why the tooltips aren't showing as there is no object to trigger the mouseover event for the tooltip.
I have been unable to find a way to 'expand' the legend area (as detected by the hittest method) to make this work.
Does anyone have any ideas? Thanks!
Responding to King King --
The original legend is created in the same method as the chart thus:
//Create the series legend
chartSel.Series[ySeries.Name].ChartArea = "ChartArea1";
chartSel.Legends.Remove(chartSel.Legends.FindByName("Legend1"));
chartSel.Legends.Add(ySeries.Name);
chartSel.Legends[0].Name = ySeries.Name;
//Format the series legend
chartSel.Legends[ySeries.Name].Docking = Docking.Right;
chartSel.Legends[ySeries.Name].DockedToChartArea = "ChartArea1";
chartSel.Legends[ySeries.Name].Alignment = StringAlignment.Near;
chartSel.Legends[ySeries.Name].IsDockedInsideChartArea = false;
chartSel.Legends[ySeries.Name].LegendStyle = LegendStyle.Table; //.Row;
chartSel.Legends[ySeries.Name].TableStyle = LegendTableStyle.Tall;
chartSel.Legends[ySeries.Name].IsEquallySpacedItems = false;
chartSel.Legends[ySeries.Name].Font = new Font("Segoe UI", 7, FontStyle.Bold);
//chartSel.Legends[ySeries.Name].TextWrapThreshold = 17; // 19;
chartSel.Legends[ySeries.Name].Position.Auto = false;
chartSel.Legends[ySeries.Name].Position.X = 80;
chartSel.Legends[ySeries.Name].Position.Y = 2;
chartSel.Legends[ySeries.Name].Position.Width = 18;
chartSel.Legends[ySeries.Name].Position.Height = 12;
//Format series data point value cell
chartSel.Legends[ySeries.Name].CellColumns.Add(new LegendCellColumn("", LegendCellColumnType.Text, ""));
chartSel.Legends[ySeries.Name].CellColumns[0].Alignment = ContentAlignment.MiddleLeft; //.TopLeft;
chartSel.Legends[ySeries.Name].CellColumns[0].Margins = new System.Windows.Forms.DataVisualization.Charting.Margins(10, 10, 1, 1);
chartSel.Legends[ySeries.Name].CellColumns[0].MinimumWidth = 500;
chartSel.Legends[ySeries.Name].CellColumns[0].MaximumWidth = 500;
chartSel.Legends[ySeries.Name].CellColumns[0].BackColor = Color.FromArgb(120, chartSel.Series[ySeries.Name].Color);
//Format legend cell spacer
chartSel.Legends[ySeries.Name].CellColumns.Add(new LegendCellColumn("", LegendCellColumnType.Text, ""));
chartSel.Legends[ySeries.Name].CellColumns[1].Alignment = ContentAlignment.TopLeft;
chartSel.Legends[ySeries.Name].CellColumns[1].Margins = new System.Windows.Forms.DataVisualization.Charting.Margins(0, 0, 0, 0);
chartSel.Legends[ySeries.Name].CellColumns[1].MinimumWidth = 25;
chartSel.Legends[ySeries.Name].CellColumns[1].MaximumWidth = 25;
chartSel.Legends[ySeries.Name].CellColumns[1].BackColor = Color.Black;
//Format series title cell
chartSel.Legends[ySeries.Name].CellColumns.Add(new LegendCellColumn("", LegendCellColumnType.Text, ySeries.Name));
chartSel.Legends[ySeries.Name].CellColumns[2].Alignment = ContentAlignment.MiddleLeft;
chartSel.Legends[ySeries.Name].CellColumns[2].Margins = new System.Windows.Forms.DataVisualization.Charting.Margins(0, 0, 1, 1);
chartSel.Legends[ySeries.Name].CellColumns[2].MinimumWidth = 1475; //1500;
chartSel.Legends[ySeries.Name].CellColumns[2].MaximumWidth = 1475; //1500;
chartSel.Legends[ySeries.Name].CellColumns[2].ToolTip = ySeries.Name;
After the series and legends have been reassigned (using the code in my original post) I then set the legend values based on the cursor position located by the following hittest in response to a mouse-down event:
pt = activePanel.PointToClient(Control.MousePosition);
ch = activePanel.GetChildAtPoint(pt) as Chart;
if (ch != null)
{
HitTestResult ht = ch.HitTest(e.X, e.Y, false);
if (ht.ChartElementType == ChartElementType.PlottingArea)
{
SetLegendValueText(ht, ch);
}
}
private void SetLegendValueText(HitTestResult ht, Chart ch)
{
//Get the datapoint 'x' index value
int dpIndex = 0;
if (ht != null)
{
switch (ht.ChartElementType)
{
case ChartElementType.DataPoint: //Cursor is on a series line
DataPoint dp = ht.Object as DataPoint;
if (dp != null)
{
dpIndex = ht.PointIndex;
}
break;
case ChartElementType.PlottingArea: //Cursor is somewhere in the plot area of the chart
dpIndex = (int)ht.ChartArea.CursorX.Position;
break;
}
}
//Set legend value and legend tooltip
for (int x = 0; x < ch.Legends.Count; x++) //foreach (Series s in ch.Series)
{
if (dpIndex > 0)
{
ch.Legends[x].Name = "Legend_" + x;
ch.Legends[x].CellColumns[0].Text = ch.Series[x].Points[dpIndex - 1].YValues[0].ToString();
ch.Legends[x].CellColumns[0].ToolTip = ch.Legends[x].CellColumns[0].Text;
}
}
}
So, I end up with the legends looking the way I want them, but the tooltips only show for the first legend item. I've tried to do custom items as well. With them I get the tooltips, but I lose the formatting. This has been driving me crazy for weeks (off and on) and I would really like to move on to other issues. Clearly (to me anyway), I am not doing something right simply because I don't know everything there is to know about the charts, and the MSChart Samples are of very limited benefit.
I'd be most grateful if I could be pointed in the right direction.

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