WinForms, MS chart, adding series from a numericUpDown - c#

I have a numericUpDown control which should ,based on the input, draw a straight line on my chart. The input should be only for the Y axis of my chart.
I can see the Tpoint added to Legend but the line is not drawn. What am I missing? I've already looked at the samples for Microsoft Chart Controls and still didn't figure out what's wrong.
private void numericSeries_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
int s = (int)numericSeries.Value;
Series series = chart2.Series.Add("Tpoint" + (chart2.Series.Count).ToString());
series.ChartArea = "ChartArea1";
series.ChartType = SeriesChartType.FastLine;
series.BorderWidth = 1;
series.Color = Color.Blue;
series.Points.AddY(s);
}
}
EDIT Unfortunately i cant upload pictures.
http://i58.tinypic.com/25aqe4m.jpg
2.EDIT - the chart in the picture is a real time chart which represents PWM values from a DC motor (Y value) vs Datetime (X value). The line i want to draw should represent the Setpoint (reference) value i'm trying to achive.
My X axis
chart2.ChartAreas[0].AxisX.Minimum = chart2.Series[0].Points[0].XValue;
chart2.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(chart2.Series[0].Points[0].XValue).AddSeconds(15).ToOADate();

Related

How can I make a gannt chart with overlapping points in winforms

There is a time interval like 8:00-17:00.In this time interval happens a task several times for example 9:00-9:20 , 11:00-12:00, 13:00-13:20.I want to make a chart in winforms to show when the task happens like this. So can I do this with DEV gannt chart? Or is there any Control I can use to make it?
I want to do this in winforms.
This is quite easy with MSChart and the ChartType RangeBar.
Here is an example:
To get this result you need to
Add an MSChart control from the data toolbox
Add the using clause: using System.Windows.Forms.DataVisualization.Charting;
Then you can style the chart..
..and maybe set a size limit
Here is the code for setting it up:
void setUpGantt(Chart chart)
{
chart.Series.Clear();
Series s = chart.Series.Add("gantt");
s.ChartType = SeriesChartType.RangeBar;
s.YValueType = ChartValueType.DateTime;
s.AxisLabel = "";
s.IsVisibleInLegend = false;
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY;
ax.MajorGrid.Enabled = false;
ax.MajorTickMark.Enabled = false;
ax.LabelStyle.Format = " ";
ax.Enabled = AxisEnabled.False;
ay.LabelStyle.Format = "HH:mm";
ay.MajorGrid.Enabled = false;
ay.MajorTickMark.Enabled = false;
ay.LineColor = chart.BackColor;
limitGantt(chart, "8:00", "17:00");
}
void limitGantt(Chart chart, string start, string end)
{
Axis ax = chart.ChartAreas[0].AxisX;
ax.Minimum = 0.5; // we have only one slot
ax.Maximum = 1.5; // the bar is centered on its value (1)
Axis ay = chart.ChartAreas[0].AxisY;
ay.Minimum = fromTimeString(start).ToOADate(); // we exclude all times..
ay.Maximum = fromTimeString(end).ToOADate(); // ..outside a given range
}
Note that I used time strings for convenience. Of course you can change to using DateTimes directly. For the conversion of a time string to a DateTime of the current day this function is used:
DateTime fromTimeString(string time)
{
var p = time.Split(':');
int sec = p.Length == 3 ? Convert.ToInt16(p[2]) : 0;
TimeSpan t = new TimeSpan(Convert.ToInt16(p[0]), Convert.ToInt16(p[1]), sec);
return DateTime.Today.Add(t);
}
Note that all the code is lacking any checks!
To add a task this method is used:
void addGanttTask(Series s, string start, string end, Color c, int slot )
{
DateTime start_ = fromTimeString(start);
DateTime end_ = fromTimeString(end);
int pt = s.Points.AddXY(slot, start_, end_);
s.Points[pt].Color = c;
}
Note that it contains both a Series and a 'slot'. The slots are used for the x-values, which in your case all are the same. But one can easily image a more comples planner with several bars for several resources, like various rooms or teams..
The Series parameter would allow to overlay a second series like you can see in this nice example from MSDN..
Here is how I filled the chart:
setUpGantt(chart1);
Series s = chart1.Series[0];
addGanttTask(s, "8:00", "17:00", Color.LimeGreen, 1);
addGanttTask(s, "9:00", "9:20", Color.DarkSlateBlue, 1);
addGanttTask(s, "11:00", "12:00", Color.DarkSlateBlue, 1);
addGanttTask(s, "13:00", "13:20", Color.DarkSlateBlue, 1);
Note that different ranges may overlap and might hide each other. In our example the green bar is added first and the others lie on top. In the MSDN example you see how the yellow bars are narrower to keep the bars under them visible. They belong to a 2nd series.
To change the bars' widths use
series.SetCustomProperty("PixelPointWidth", "15");
Here is an example with DevExpress.XtraCharts.ChartControl and ViewType RangeBar
First add a DevExpress.XtraCharts.ChartControl to the form.
Here is How I fill the chart
rangeBarChart.Series.Clear();
// Create two range bar series.
Series series1 = new Series("Task1", ViewType.RangeBar);
Series series2 = new Series("Task2", ViewType.RangeBar);
series1.CrosshairLabelPattern = "{S}:{V1:HH:mm}--{V2:HH:mm}";
series2.CrosshairLabelPattern = "{S}:{V1:HH:mm}--{V2:HH:mm}";
//Add values to series
series1.ValueScaleType = ScaleType.DateTime;
series2.ValueScaleType = ScaleType.DateTime;
series1.Points.Add(new SeriesPoint("A", Convert.ToDateTime("2019-08-24 8:00"), Convert.ToDateTime("2019-08-24 17:00")));
series2.Points.Add(new SeriesPoint("A", Convert.ToDateTime("2019-08-24 9:00"), Convert.ToDateTime("2019-08-24 10:00")));
series2.Points.Add(new SeriesPoint("A", Convert.ToDateTime("2019-08-24 13:00"), Convert.ToDateTime("2019-08-24 14:00")));
// Add both series to the chart.
rangeBarChart.Series.AddRange(new Series[] { series1, series2 });
((XYDiagram)rangeBarChart.Diagram).Rotated = true;
The result shows like this:

Scrolling/Moving MS chart area to highlighted datapoint when in zoom state

In windows form, I am displaying data in MS Chart from Datagridview.
When selecting an row in the datagridview, I am highlighting the corresponding datapoint in the chart with different color.
When chart is in zoom state , if a datapoint is highlighted newly and if it is not in the visible state, I have to scroll/move the chart to highlighted datapoint.
chart.ChartAreas.Add("LineGraphHistory");
chart.ChartAreas["LineGraphHistory"].AxisX.Title = "X Axis";
chart.ChartAreas["LineGraphHistory"].AxisX.MajorGrid.LineColor = System.Drawing.Color.Black;
chart.ChartAreas["LineGraphHistory"].AxisX.MajorGrid.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
chart.ChartAreas["LineGraphHistory"].AxisY.Title = "Y Axis";
chart.ChartAreas["LineGraphHistory"].AxisY.MajorGrid.LineColor = Color.Black;
chart.ChartAreas["LineGraphHistory"].AxisY.MajorGrid.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
chart.ChartAreas["LineGraphHistory"].BackColor = Color.White;
chart.ChartAreas["LineGraphHistory"].CursorX.IsUserEnabled = true;
chart.ChartAreas["LineGraphHistory"].CursorX.IsUserSelectionEnabled = true;
chart.ChartAreas["LineGraphHistory"].CursorX.Interval = 0;
chart.ChartAreas["LineGraphHistory"].AxisX.ScaleView.Zoomable = true;
chart.ChartAreas["LineGraphHistory"].AxisX.ScrollBar.Enabled = true;
chart.Legends.Add("Legend");
chart.Legends["Legend"].BorderColor = Color.Tomato;
chart.DataSource = CSVDataTable;
chart.ChartAreas["LineGraphHistory"].AxisX.IntervalType = DateTimeIntervalType.Seconds;
chart.ChartAreas["LineGraphHistory"].AxisX.LabelStyle.Format ="dd-MM-yyyy\n hh:mm:ss"; ;
chart.Series[s].XValueType =ChartValueType.DateTime ;
chart.DataBind();
chart.Update();
private void cDataGrid_SelectionChanged(object sender, EventArgs e)
{
int nCount = csvDataGrid.SelectedRows.Count;
if (nCount > 0)
{
for (int i = 0; i < nCount; i++)
{
int index = csvDataGrid.SelectedRows[i].Index;
if (index >= csvDataGrid.Rows.Count-1)
return;
for (int k = 0; k < chart.Series.Count; k++)
{
DataPointCollection pr = chart.Series[k].Points;
pr[index].MarkerColor = Color.DarkGoldenrod;
pr[index].MarkerStyle = MarkerStyle.Star10;
pr[index].MarkerSize = 20;
// chart.
}
chart.Update();
}
}
}
How to achieve this?
As Taw suggested I tried to set scaleview position.
I have 10 datapoints. The range of x value of datapoints are 20 to 200. Each x value has equal difference of 20. The view size is 100. In zoom mode, when I scrolling to maximum the x range is 101 to 200 in the view , the last point is displayed as 5th point in the view. Whereas if I use your code to set scaleview position to highlight last datapoint , the x range becomes 180 to 240 and highlighted last datpoint is visible as first range.
Why paintviewmin and paintviewmax values are changing?
The images are
You need to calculate the offset from the DataPoint dp.XValue, maybe like this:
Axis ax = chart.ChartAreas[0].AxisX;
var size = ax.ScaleView.ViewMaximum - ax.ScaleView.ViewMinimum;
ax.ScaleView.Position = dp.XValue - size / 2.0;
Example:
Update: When smaller data sets are displayed the automatically added margins mess up the simple calculation above. To avoid this you can add:
chart.ChartAreas[0].AxisX.IsMarginVisible = false;

C# MSChart how to shift Y axis like oscilloscope offset button?

I have a MSChart, that x-axis is t(ms), and y-axis is voltage data.
Now I would like programming the code like oscilloscope function "Offset".
When I adjust numericUpDown to shift the wave and Y-axis.
How to get this function? Just like below 2 picture. Thanks!
No shift wave and Y-axis
Now shift Y-axis and wave shift too
The way I would tackle it is to change the y-axis Minimum and/or Maximum values. You can also play with the IntervalOffset.
See here:
private void numericUpDown5_ValueChanged(object sender, EventArgs e)
{
Axis ay = chart2.ChartAreas[0].AxisY;
int oy = (int)numericUpDown5.Value;
if (radioButton1.Checked) ay.IntervalOffset = oy;
if (radioButton2.Checked) ay.Maximum = oy;
if (radioButton3.Checked) ay.Minimum = oy;
}
private void rbAy_CheckedChanged(object sender, EventArgs e)
{
Axis ay = chart2.ChartAreas[0].AxisY;
if (sender == radioButton1) numericUpDown5.Value = (decimal)ay.IntervalOffset;
if (sender == radioButton2) numericUpDown5.Value = (decimal)ay.Maximum;
if (sender == radioButton3) numericUpDown5.Value = (decimal)ay.Minimum;
}

C# Chart Y interval line missing after zoom

I have still have a problem with C# Chart (in System.Windows.Forms.DataVisualization.Charting namespace).
When i zoom on Y axis, sometimes, interval line aren't redrawn.
Look at the picture below, interval lines are missing under 0.Missing interval line
Usually, there is no problem and 11 interval lines are drawn.
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
if ((e != null) && (sender != null))
{
// on ne récupère que les évènement concernant l'axe Y. L'axe X se gère tout seul car il est unique
if (e.Axis.AxisName.ToString() == "Y")
{
// AxisY.ScaleView.ViewMinimum is the minimum Y axis value displayed. It contains the offset to apply to label, grid and interval on Y axis
e.ChartArea.AxisY.IntervalOffset = (e.ChartArea.AxisY.Interval - e.ChartArea.AxisY.ScaleView.ViewMinimum) % e.ChartArea.AxisY.Interval;
// To update Y axis label, major grid and interval.
e.ChartArea.AxisY.Interval = (e.ChartArea.AxisY.ScaleView.ViewMaximum - e.ChartArea.AxisY.ScaleView.ViewMinimum) / 11;
}
}
}
Above is my axisViewChanged event.
The Y axis is declared as below
chartArea1.AxisY.Interval = (sens.dMaximumValue - sens.dMinimumValue)/11.0;
chartArea1.AxisY.IntervalOffsetType = DateTimeIntervalType.Number;
chartArea1.AxisY.IntervalType = DateTimeIntervalType.Number;
chartArea1.AxisY.LabelStyle.Format = ".000";
chartArea1.AxisY.MajorGrid.LineColor = Color.White; // Color.DarkViolet;
chartArea1.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash;
chartArea1.AxisY.MajorTickMark.Enabled = false;
chartArea1.AxisY.Maximum = sens.dMaximumValue*1.1;
chartArea1.AxisY.Minimum = sens.dMinimumValue*1.1;
chartArea1.AxisY.ScaleView.MinSize = 0.01D;
chartArea1.AxisY.ScaleView.SmallScrollMinSize = 0.001D;
chartArea1.AxisY.ScrollBar.BackColor = Color.White;
chartArea1.AxisY.ScrollBar.ButtonColor = Color.LightGray;
As you can see, it is declared as Number, which is correct i think.
When this problem oocurs, if i click on the scrollbar, the 11 interval are correctly redrawn.
Has something solved this problem ?

Getting DataPoint with mouse X coordinate only

I need to access the DataPoint via X coordinate, but I can't seem to find any solutions for it. HitTest() is out, since it also needs Y coordinate (cannot hit anything if Y is 0). I know I could select the DataPoints via Linq and the X coordinate, but I was wondering if there are better solutions for this?
More specifically I'm trying to show Candlestick data (Open, Low, High, Close and DateTime) with a TextAnnotation, which follows the CursorX (it's anchored above my X-axis, which is located at the bottom of my chart), and my CursorX is intervalled so it is always in the center of a candle.
What I have so far, is a MouseMove function, which updates my CursorX, but lacks the data access and label update:
PointF _mouse = new PointF();
TextAnnotation _mouseLabel;
void UpdateMouseCursor(object sender, MouseEventArgs e)
{
if( _mouseLabel == null )
return;
_mouse.X = e.Location.X;
_mouse.Y = e.Location.Y;
var cursorX = chart1.ChartAreas[0].CursorX;
cursorX.SetCursorPixelPosition( _mouse, true );
_mouseLabel.X = cursorX.Position;
}
CursorX and _mouseLabel setup:
public void SetupMouse(double interval, DateTimeIntervalType intervalType)
{
chart1.ChartAreas[0].CursorX.IntervalType = intervalType;
chart1.ChartAreas[0].CursorX.Interval = interval;
chart1.ChartAreas[0].CursorX.LineColor = Color.FromArgb(128, 128,128,128);
if( _mouseLabel == null )
{
_mouseLabel = new TextAnnotation();
_mouseLabel.Text = "WOOHOO!";
_mouseLabel.AnchorY = 85;
_mouseLabel.AxisX = chart1.ChartAreas[0].AxisX;
chart1.Annotations.Add( _mouseLabel );
}
}
The visuals:

Categories