.NET Chart Control - Place bar label outside and left? - c#

My question is pretty straightforward, but I have a feeling the answer is a little more involved:
I'm trying to get the labels on this chart set up such that the first date will be to the left of the bar and the last date will be to the right:
Each bar is actually made of a point representing the whole timespan (drawn as a border with white inside color) and a point representing the % completed (drawn as the solid fill in those borders).
What I've got accomplished so far is done using Point CustomProperties:
Chart1.Series[s].Points[0].Label = gsvPhaseList[0].EndDate.Value.ToString("M/dd");
Chart1.Series[s].Points[0].SetCustomProperty("BarLabelStyle", "Outside");
Chart1.Series[s].Points[1].Label = gsvPhaseList[0].StartDate.Value.ToString("M/dd");
Chart1.Series[s].Points[1].SetCustomProperty("BarLabelStyle", "Left");
My problem is that there doesn't seem to be a way to say "Left & Outside".
My next step is to add a hook to the Paint event on the chart so I can actually get the label's position and shift to the left (I hope), but I wanted to make sure there wasn't something simple I'm missing first. Any ideas?

Your Chart displays RangeBars. You can fake the Outside-Left position by adding one extra DataPoint to the left of each Point.
You need to make it wide enough to hold the Label and you should keep it a little bit to the left of the real point, so the Label won't touch the side.
Make its Color = Color.Transparent and your Labels will show to the left and right.
Here is a piece of code that does the adornment for all Series in a Chart:
// just a few test data in Series S1 & S2..
S1.Points.AddXY(1, 13, 14.5); // the dummy point
S1.Points.AddXY(1, 15,22);
S2.Points.AddXY(1, 7,8.5); // 2nd dummy
S2.Points.AddXY(1, 9,13);
// set the labels
foreach (Series S in chart1.Series)
for (int i = 0; i < S.Points.Count; i+=2 )
{
DataPoint pt0 = S.Points[i];
DataPoint pt1 = S.Points[i + 1];
pt0.Color = Color.Transparent;
pt0.SetCustomProperty("BarLabelStyle", "Right");
pt0.Label = pt1.YValues[0] + " ";
pt1.SetCustomProperty("BarLabelStyle", "Outside");
pt1.Label = " " + pt1.YValues[1];
}
You could write code to actually add those extra label points automatically, too..

Related

How to change the color of the DataPoint label based on the chart bar size?

I added a new chart control (System.Windows.Forms.DataVisualiation.Charting) with ChartType Bar.
As requirement the label text must be white and into the bar value. Therefore I set the BarLabelStyle=Right in the CustomProperties of the DataPoint objects and the LabelForeColor to White.
See the below images.
The label in the 2nd gray bar is correctly shown.
The first bar instead is too small and the white text is shown out on the right side but is not visible.
However, when the bar is too short, the label text is positioned outside the bar and the text cannot be seen using white color.
Is there a way to check when the label text is drawn outside the bar value so that I can change the color (e.g. black)?
Thanks.
Unfortunately MCChart has almost no capacities wrt to dynamic expressions.
To work around you can either..:
Code the ForeColor depending on the y-value your DataPoints has. Either right when you add them or in a function that loops over all points, whenever you call it.. - Depending on the Font, the axis range and the label text this could be some threshold number you have to determine.
Example:
int p = yourSeries.Points.AddXY(...);
yourSeries.Points[p].LabelForeColor = yourSeries.Points[p].YValues[0] < threshold ?
Color.Black : Color.White;
Or you can cheat a little ;-)
You can set the LabelBackColor to have the same color as the Series, i.e. the bar itself. Here is is how to do that:
To access the Series.Color we have to call:
chart.ApplyPaletteColors();
Now we can set
yourSeries.LabelForeColor = Color.White;
yourSeries.LabelBackColor = yourSeries.Color;
Example:
Update:
Since you can't use the cheat you will have to set the colors.
The challenge is to know just how much space each label's text needs compared to how much space the bars have. The former can be measured (TextRenderer.MeasureString()) and the latter can be extracted from the y-axis (Axis.ValueToPixelPosition()).
Here is a function to do that; it is a little more complicated than I had hoped for, mostly because it tries to be generic..
void LabelColors(Chart chart, ChartArea ca, Series s)
{
if (chart.Series.Count <= 0 || chart.Series[0].Points.Count <= 0) return;
Axis ay = ca.AxisY;
// get the maximum & minimum values
double maxyv = ay.Maximum;
if (maxyv == double.NaN) maxyv = s.Points.Max(v => v.YValues[0]);
double minyv = s.Points.Min(v => v.YValues[0]);
// get the pixel positions of the minimum
int y0x = (int)ay.ValueToPixelPosition(0);
for (int i = 0; i < s.Points.Count; i++)
{
DataPoint dp = s.Points[i];
// pixel position of the bar right
int vx = (int)ay.ValueToPixelPosition(dp.YValues[0]);
// now we knowe the bar's width
int barWidth = vx - y0x;
// find out what the label text actauly is
string t = dp.LabelFormat != "" ?
String.Format(dp.LabelFormat, dp.YValues[0]) : dp.YValues[0].ToString();
string text = dp.Label != "" ? dp.Label : t;
// measure the (formatted) text
SizeF rect = TextRenderer.MeasureText(text, dp.Font);
Console.WriteLine(text);
dp.LabelForeColor = barWidth < rect.Width ? Color.Black : Color.White;
}
}
I may have overcomplicated the way to get at the text that should show; you certainly can decide if you can simplify for your case.
Note: You must call this function..
whenever your data may have changed
only after the axes of the chart have finished their layout (!)
The former point is obvious, the latter isn't. It means that you can't call the function right after adding your points! Instead you must do it at some later place or else the axis function needed to get the bar size will not work.
MSDN says it can only happen in a PaintXXX event; I found that all mouse events also work and then some..
To be save I'll put it in the PostPaint event:
private void chart_PostPaint(object sender, ChartPaintEventArgs e)
{
LabelColors(chart, chart.ChartAreas[0], chart.Series[0]);
}

Combine BarChart and PointChart

i got a Little "Problem", i want to create a Chart looking like this:
So basically
Series 1 = Normal bar Chart. Color green if it Ends before the "time max" (series2) Series 2 = just a DataPoint / Marker on top of series 1 items.
I am struggling with this though...
my Code:
chart_TimeChart.Series.Clear();
string series_timeneeded = "Time Needed";
chart_TimeChart.Series.Add(series_timeneeded);
chart_TimeChart.Series[series_timeneeded]["PixelPointWidth"] = "5";
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Size = 10;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.IsPositionedInside = true;
chart_TimeChart.ChartAreas[0].AxisY.ScrollBar.Enabled = true;
chart_TimeChart.Series[series_timeneeded].BorderWidth = 2;
chart_TimeChart.Series[series_timeneeded].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_timeneeded].YValueType = ChartValueType.Time;
chart_TimeChart.ChartAreas[0].AxisY.LabelStyle.Format = "HH:mm:ss";
chart_TimeChart.Series[series_timeneeded].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
chart_TimeChart.Series[series_timeneeded].Points.AddXY("item"+ " " + (i + 1).ToString(), DateTime.Now.Add(Timespans[i]));
}
chart_TimeChart.Series.Add(series_FinishTime);
chart_TimeChart.Series[series_FinishTime].ChartType = SeriesChartType.StackedBar;
chart_TimeChart.Series[series_FinishTime].BorderWidth = 0;
chart_TimeChart.Series[series_FinishTime].MarkerSize = 15;
chart_TimeChart.Series[series_FinishTime].MarkerStyle = MarkerStyle.Square;
chart_TimeChart.Series[series_FinishTime].MarkerColor = Color.Black;
chart_TimeChart.Series[series_FinishTime].YValueType = ChartValueType.DateTime;
chart_TimeChart.Series[series_FinishTime].XValueType = ChartValueType.String;
for (int i = 0; i < MaxNumber; i++)
{
DateTime YPosition = GetFinishTime(i);
chart_TimeChart.Series[series_FinishTime].Points.AddXY("item"+ " " +(i+1).ToString(), YPosition);
}
but this only Displays the 2nd series on top of the first one but the first one isnt visible anymore. The Maker of series 2 isnt shown but instead the bar is (eventhough i made borderwidth to 0). In my opinion/thinking i just have to make the "bar" of series 2 invisible and just Show the marker Points for series 2.
Any ideas?
Update:
string seriesname = Name+ i.ToString();
chart_TimeChart.Series.Add(seriesname);
chart_TimeChart.Series[seriesname].SetCustomProperty("DrawSideBySide", "false");
chart_TimeChart.Series[seriesname].SetCustomProperty("StackedGroupName", seriesname);
chart_TimeChart.Series[seriesname].ChartType = SeriesChartType.StackedBar; //Y and X are exchanged
chart_TimeChart.Series[seriesname].YValueType = ChartValueType.Time;
chart_TimeChart.ChartAreas[0].AxisY.LabelStyle.Format = "HH:mm:ss";
chart_TimeChart.Series[seriesname].XValueType = ChartValueType.String;
DateTime TimeNeeded = DateTime.Now.Add(List_AllLiniengroupsTimespans[k][i]);
DateTime TimeMax = GetFinishTime(k, i);
TimeSpan TimeDifference = TimeNeeded - TimeMax;
if (TimeNeeded > TimeMax) //All good
{
chart_TimeChart.Series[seriesname].Points.AddXY(seriesname, TimeNeeded); //Time till finish
chart_TimeChart.Series[seriesname].Points[0].Color = Color.Blue;
chart_TimeChart.Series[seriesname].Points[0].SetCustomProperty("StackedGroupName", seriesname);
chart_TimeChart.Series[seriesname].Points.AddXY(seriesname, TimeNeeded.Add(TimeDifference)); //time left
chart_TimeChart.Series[seriesname].Points[1].Color = Color.Red;
chart_TimeChart.Series[seriesname].Points[1].SetCustomProperty("StackedGroupName", seriesname);
}
else if (TimeMax > TimeNeeded) //wont make it in time
{
chart_TimeChart.Series[seriesname].Points.AddXY(seriesname, TimeNeeded); //time till still okay
chart_TimeChart.Series[seriesname].Points[0].Color = Color.Blue;
chart_TimeChart.Series[seriesname].Points[0].SetCustomProperty("StackedGroupName", seriesname);
chart_TimeChart.Series[seriesname].Points.AddXY(seriesname, TimeNeeded.Add(TimeDifference)); //Time that is too much
chart_TimeChart.Series[seriesname].Points[1].Color = Color.Green;
chart_TimeChart.Series[seriesname].Points[1].SetCustomProperty("StackedGroupName", seriesname);
}
else if (TimeMax == TimeNeeded) //fits exactly
{
chart_TimeChart.Series[seriesname].Points.AddXY(seriesname, TimeNeeded);
chart_TimeChart.Series[seriesname].Points[0].Color = Color.DarkOrange;
chart_TimeChart.Series[seriesname].Points[0].SetCustomProperty("StackedGroupName", seriesname);
}
the Code will be displayed as:
but i want it to look like this:
!! See the update below !!
If you really want to create a StackedBar chart, your chart has two issues:
If you want to stack datapoints they need to have meaningful x-values; without them how can it know what to stack on each other?
You add strings, which look fine but simply don't work. That is because the DataPoint.XValue field is double and when you add string into it it is set to 0 !! Your string is copied to the Label but otherwise lost.
So you need to come up with a suitable numeric value you use for the x-values..
And you also need to group the series you want to stack. For this there is a special property called StackedGroupName which serves to group those series that shall be stacked.
Here is how you can use it:
yourSeries1.SetCustomProperty("StackedGroupName", "Group1");
For a full example see this post !
It also shows one way of setting the Labels with string values of your choice..
This is the way to go for real StackedBar charts. Your workaround may or may not work. You could try to make the colors transparent or equal to the chart's backcolor; but it won't be more than a hack, imo.
Update
I guess I have misread the question. From what I see you do not really want to create a stacked chart.
Instead you struggle with these issues:
displaying bars at the same y-spot
making some bars invisible
displaying a vertical line as a marker
Let's tackle each:
Some column types including all Bars, Columns and then some have a little known special property called DrawSideBySide.
By default is is set to Auto, which will work like True. This is usually fine as we don't want bars to sit upon each other, effectively hiding all or part of the overlaid points.
But here we do want them to share the same y-position, so we need to set the property to false for at least one Series; the others (on Auto) will follow..:
You can do it either like this:
aSeries["DrawSideBySide"] = "false";
or like this:
aSeries.SetCustomProperty("DrawSideBySide", "false");
Next we hide the overlaid Series; this is simple:
aSeries.Color = Color.Transparent;
The last issue is displaying a line marker. There is no such MarkerStyle, so we need to use a custom style. For this we need to create a suitable bitmap and add it as a NamedImage to the chart's Images collection.
This sounds more complicated than it is; however the MarkerImage will not be scaled, so we need to created suitable sizes whenever we resize the Chart or add/remove points. I will ignore this complication for now..
int pointCount = 10;
Bitmap bmp = new Bitmap(2, chart.ClientSize.Height / pointCount - 5);
using (Graphics g = Graphics.FromImage(bmp)) g.Clear(Color.Black);
NamedImage marker = new NamedImage("marker", bmp);
chart.Images.Clear(); // quick & dirty
chart.Images.Add(marker);
Here is the result:
A few notes:
I would recommend to use variables for all chart elements you refer to repeatedly instead of using indexed references all the time. Less code, easier to read, a lot easier to maintain, and probably better performance.
Since your code called for the visible datapoints to be either red or green the Legend will not show a good representation. See here for an example of drawing a multi-colored legend item..
I used the chart height; this is not really recommended as there may be Titles or Legends or even more ChartAreas; instead you should use the height of the ChartArea, or even more precise, the height of the InnerPlotPosition. You would need to convert those from percentages to pixels. Not too hard, see below or see here
or here for more examples!
The markers should be adapted from the Resize and probably from the AxisViewChanged events. Putting it in a nice function to call (e.g. void setMarkerImage(Chart chart, Series s, string name, int width, Color c)) is always a good idea.
If you need to adapt the size of the marker image repeatedly, you may want to write better code for clearing the old one; this should include disposing of the Bitmap that was used before..
Here is an example:
var oldni = chart.Images.FindByName("marker");
if (oldni != null)
{
oldni.Image.Dispose();
chart.Images.Remove(oldni);
oldni.Dispose();
}
In some situations one needs to nudge the Chart to update some of its properties; RecalculateAxesScale is one such nudge.
Example for calculating a suitable marker height:
ChartArea ca = chart.ChartAreas[0];
ca.RecalculateAxesScale();
float cah = ca.Position.Height;
float iph = ca.InnerPlotPosition.Height;
float h = chart3.ClientSize.Height * cah / 100f * iph / 100f;
int mh = (int)(h / s.Points.Count);
Final note: The original answer stressed the importance of using meaningful x-values. Strings are useless! This was important for stacking bars; but it is equally important now, when we want bars to sit at the same vertical positions! Adding the x-values as strings is again resulting in nonsense..
(Since we have Bars the x-values go along the vertical axis and vice versa..)

MSChart axis CustomLabel angle at RowIndex > 0

Using VisualStudio WindowsForms Form. Creating Chart control in designer.
I'm trying to add some customLabels on charts Axis along WITH the default labels.
To do so I add customLabels with RowIndex property =1. Thus I see default labels AND my customLabels.
Now the problem is that while the default labels are rotated correctly my custom labels are not.
The Axis property LabelStyle.Angle affects only labels that are in RowIndex = 0, i.e. default labels.
And if I put customLabels at RowIndex=0 - all default labels will disappear.
What I see:
What I want to see:
I see no way to do that, really. The reason is probably that the developers decided there simply cannot be enough space for horizontal labels, once you start putting them in one or more extra rows..
Here is a workaround: Make those CustomLabels all transparent and draw them as you like in a xxxPaint event.
Here is an example:
I prepared the CustomLabels :
CustomLabel cl = new CustomLabel();
cl.ForeColor = Color.Transparent;
cl.RowIndex = 1;
...
And I code the drawing like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Axis ay = chart1.ChartAreas[0].AxisY;
foreach (var cl in ay.CustomLabels)
{
if (cl.RowIndex == 1)
{
double vy = (cl.ToPosition + cl.FromPosition) / 2d;
int y = (int)ay.ValueToPixelPosition(vy);
e.ChartGraphics.Graphics.DrawString(cl.Text,
cl.Axis.TitleFont, Brushes.DarkRed, 0, y);
}
}
}
Do use a Font and Brush of your own liking. Here is the result:
Note that you may need to create more space to the left by tweaking the ChartArea.Position or the ChartArea.InnerPlotPosition, both of which are in 100% and, as usual, default to 'auto'.
For even more rows you need to change the check to cl.RowIndex < 0 and find a nice x position value for the DrawString.

Chart repositions itself to overlap text in a weird manner

Here is my code:
public Form1()
{
InitializeComponent();
// Data arrays.
string[] seriesArray = { "Cats", "Dogs" };
int[] pointsArray = { 1, 2 };
// Set palette.
this.chart1.Palette = ChartColorPalette.SeaGreen;
// Set title.
this.chart1.Titles.Add("Pets");
// Add series.
for (int i = 0; i < seriesArray.Length; i++)
{
// Add series.
Series series = this.chart1.Series.Add(seriesArray[i]);
// Add point.
series.Points.Add(pointsArray[i]);
}
}
private void button1_Click(object sender, EventArgs e)
{
chart1.Titles[0].Position.Y = chart1.Titles[0].Position.Y + 1;
}
The problem i face is when i change the Location of the Title Pets is that the Chart redraws itself in a different way. I want to understand why does this happen and is there a way to work around this - since it brings the text on top of the chart and this happens only at the first time.
Here is what i mean:
How does adding 1 make such a huge difference in the chart?
Try with DockingOffset instead of Position.Y
private void button1_Click(object sender, EventArgs e)
{
chart1.Titles[0].DockingOffset = chart1.Titles[0].DockingOffset + 1;
}
The problem with 'Position.Y' is that it starts with "auto" position, so the first time you add 1 to it, the compiler assign a value, redraws and then add 1.
How does adding 1 make such a huge difference in the chart?
First that's because many or most ChartElements are positioned by percentages.
Some are by Values, given in doubles, other in pixels, but most are in percentages of their respective containers.
Or, initially set to auto and recalculated whenever necessary.
So if your ChartArea has a height of 80% and the Chart's Clientsize is 500pixels the ChartArea's height calculates to 400 pixels.
I don't know to what percentage the Title.Position.Height has been calculated in your chart, but if it is, say 4% then adding 1 makes it 5%, bringing it down from 20px to y=25px.
But wait, the difference you observe is a lot more than that! In fact the by far larger difference is the Height & Top of the ChartArea! Why is that?
Secondly, by messing with the Chart's Title's Position you have taken it out of the elements to consider when auto-calculating the available spaces, and with the Title 'gone' from that calculation, there suddenly is a lot more vertical space for the ChartArea. So is grows and even happens to overlap the Title.
How can you prevent that? Well you can prevent the changes from the calculation by taking the automatic out, maybe like this:
RectangleF r = chart1.ChartAreas[0].Position.ToRectangleF();
chart1.ChartAreas[0].Position = new ElementPosition(r.X, r.Y, r.Width, r.Height);
Note that the other elements may be affected as well. So the Legend will also use the freed space at the top and move up.. (You can see that in your screenshot.) And since the spaces are no longer calculated automatically you will have to take care of some more issues, when some elements grow and need more space, like the axis labels or a Legend..
By the way, to restore a ChartElement.Position to Auto you need to set the values to double.NaN.

Working with zedgraph XDate values to set Major|MinorStep and BaseTic values for x-axis

I am trying to control the value labels for my zedgraph's x-axis. Before, the labels would "fly around" and not really stay put on the axis. They might move left or right on the axis and pop in and out of existence based on the data. Like in the picture below
I first tried to draw the labels myself when I finally found good documentation for the zedgraph library. There I found the [AXIS].Scale options of MajorStep MinorStep and BaseTic. Which if set correctly should cause the labels to stay in place and just change value as the data is added.
The issue I am running into though is that my x-axis scale is in XDate units. Which means I cannot do the simple math I was hoping to. So I have since figured a way that I think I can find the values I need using TimeSpan and DateTime. Below curMaxX and curMinX are XDate values of the current minimum and maximum x-axis values (curMinX should basically be DateTime.Now because this data is realtime)
// Setup
TimeSpan scaleDist = curMaxX.DateTime.Subtract(curMinX.DateTime);
TimeSpan major = new TimeSpan(scaleDist.Ticks / 5);
TimeSpan minor = new TimeSpan(major.Ticks / 5);
TimeSpan baseT = new TimeSpan(curMinX.DateTime.Ticks + major.Ticks);
// Setting the values
myPane.XAxis.Scale.MajorStep = new XDate(new DateTime(major.Ticks));
myPane.XAxis.Scale.MinorStep = new XDate(new DateTime(minor.Ticks));
myPane.XAxis.Scale.BaseTic = new XDate(new DateTime(baseT.Ticks));
// Print statement of the values
SDist: 00:00:10
Major: 00:00:02
Minor: 00:00:00.4000000
BaseT: 735382.07:32:34
BaseTAsDateTime: 5/30/2014 7:32:34 AM
CurMinX: 5/30/2014 7:32:32 AM
Though setting the values as such still does not achieve what I want. With this code my x-axis comes out looking like so
It is somewhat closer to what I am looking for but still off. Only a single major tic is shown, and no minor tics. I am not sure what other ways there might be to specify the values.
For the major and minor step documentation it says
For Date axes, this value is defined in units of Major/MinorUnit.
Which my MajorUnit is minutes and the MinorUnit is seconds, but I pass them a XDate value which specifies both minutes and seconds. Also, setting the values as fractions of a whole (so if I want MajorStep to be 2 seconds I'd set it as (2/60)), causes nothing to show up.
Any ideas/suggestions?
Well, I determined that it was a waste of time to try and use the default zedgraph tics, steps, etc. So I made my own method to do so based on the data currently on the graph.
After I posted this I realized trying to figure out the tics was a lost cause so I looked for other ways to do it. I was going to add text beside each point showing its values, but it became very cluttered, then I realized I can just draw the text at the bottom of the graph which is what I wanted all along. I also added a little label on the right showing the current value.
A little bit o code
private void setPointLabels()
{
// All hail the almighty pane.
GraphPane myPane = theGraph.GraphPane;
// Give us some room to draw labels
myPane.Margin.Right = 50;
myPane.Margin.Bottom = 20;
// Dont show the default stuff
myPane.XAxis.Scale.IsVisible = false;
myPane.XAxis.MajorTic.IsAllTics = false;
myPane.XAxis.MinorTic.IsAllTics = false;
// Remove the old labels
myPane.GraphObjList.Clear();
// Get the curve showing our data
LineItem myCurve = (LineItem)myPane.CurveList[0];
// Show a voltage value on the far right
PointPair pt = myCurve.Points[myCurve.Points.Count - 1];
TextObj text = new TextObj(" " + pt.Y.ToString("f2"), pt.X, pt.Y, CoordType.AxisXYScale, AlignH.Left, AlignV.Center);
text.ZOrder = ZOrder.A_InFront;
text.FontSpec.Border.IsVisible = false;
text.FontSpec.Fill.IsVisible = false;
myPane.GraphObjList.Add(text);
// Determine a hardcoded yOffset for the labels
double yOffset = -1.2;
// Determine if we need to fix the center label
int fixVal = 1;
if (xScaleSec == 10)
fixVal = 0;
// Loop over each point in the curve
for (int i = 0; i < myCurve.Points.Count; i++)
{
if (i == 0 ||
i == (myCurve.Points.Count/4) ||
i == ((myCurve.Points.Count/2)-fixVal) ||
i == ((3*myCurve.Points.Count)/4) ||
i == myCurve.Points.Count-1)
{
PointPair aPt = myCurve.Points[i];
// Add a text object just below the x-axis showing the point's x-value
XDate xVal = new XDate(aPt.X);
TextObj label = new TextObj(xVal.ToString("hh:mm.ss"), aPt.X, myPane.YAxis.Scale.Min + yOffset, CoordType.AxisXYScale, AlignH.Center, AlignV.Center);
label.ZOrder = ZOrder.A_InFront;
label.FontSpec.Fill.IsVisible = false;
label.FontSpec.Border.IsVisible = false;
myPane.GraphObjList.Add(label);
// Add a line object on the x-axis representing a tic mark
LineObj aTic = new LineObj(aPt.X, myPane.YAxis.Scale.Min - (yOffset / 4), aPt.X, myPane.YAxis.Scale.Min + (yOffset / 4));
myPane.GraphObjList.Add(aTic);
}
}
}

Categories