I am trying to plot a file's byte count over a C# WinForms bar graph. As such, the X-axis will have values 0-255 (if greater than zero) and the Y-axis varies upon the length of the file and the byte distribution. The code is as follows:
for (int i = 0; i < byteDistribution.Count; i++)
{
if (byteDistribution[i] > 0)
{
Series series = new Series(i.ToString());
series.Points.AddXY(i, byteDistribution[i]);
// PointWidth has no affect?
series.SetCustomProperty("PointWidth", "1");
this.crtBytes.Series.Add(series);
}
Questions:
This works well but the way the chart is shown is not to my liking.
I would like each bar to fill in as much space as possible (ie. no
margin / border). From what I've read elsewhere it was suggested to
use PointWidth or PixelPointWidth but none of these approaches is
working.
Is there a way to remove the inner black grid lines from
showing? Ideally, I would like the bottom X-axis numbering to remain just the same, but remove the grid lines.
For removing the gaps:
series["PointWidth"] = "1";
For removing the gridlines:
chartArea.AxisX.MajorGrid = new FChart.Grid {Enabled = false};
chartArea.AxisY.MajorGrid = new FChart.Grid { Enabled = false };
UPDATE:
I think your problem is that you create a new series for each data point. So you also get the "color effect". Just create ONE series, add it to the chart area and add all data points to this series.
Series series = new Series();
this.crtBytes.Series.Add(series);
series.SetCustomProperty("PointWidth", "1");
for (int i = 0; i < byteDistribution.Count; i++)
{
if (byteDistribution[i] > 0)
{
series.Points.AddXY(i, byteDistribution[i]);
// PointWidth has no affect?
}
}
PointWidth property is a relative amount, try something like series["PointWidth"] = 1.25.
The black lines are called MajorGrid, use chartArea.MajorGrid.Enabled = False.
Related
Below is the code for a bar graph using System.Windows.Forms.DataVisualization.Charting that I got from the Web. The problem is that I don't understand several parts of it and I'm at a loss as to where to find a good resource to learn about all the ins and outs of using all of the charting stuff. Isn't there some 3rd party book available? Normally Microsoft provides example code for how to use the various classes and members but when it comes to charting I can't find anything other than a few random and unexplained 3rd party examples on the Web.
Anyway, below is the code and the graph it produces follows it. I have the following questions...
Why are two of the bars to the left of the 1 on the X axis and the other two to the right of it? What controls this and how do I make them start at 0?
What controls the width of the bars?
How do I remove all labels along the X axis (the 0, 1, and 2)?
About all I do understand about the results I'm seeing is why there are 4 bars and why their Y-values are 2, 1, 7, and 5.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
System.Windows.Forms.DataVisualization.Charting.Chart chart1 = new System.Windows.Forms.DataVisualization.Charting.Chart();
chartArea1.Name = "ChartArea1";
chart1.ChartAreas.Add(chartArea1);
chart1.Location = new System.Drawing.Point(0, 0);
chart1.Name = "chart1";
series1.ChartArea = "ChartArea1";
series1.Name = "Series1";
chart1.Series.Add(series1);
chart1.Size = new System.Drawing.Size(500, 400);
chart1.TabIndex = 0;
chart1.Text = "chart1";
this.Controls.Add(chart1);
string[] seriesArray = { "Cat", "Dog", "Bird", "Monkey" };
int[] pointsArray = { 2, 1, 7, 5 };
for (int i = 0; i < seriesArray.Length; i++)
{
Series series = chart1.Series.Add(seriesArray[i]);
series.Points.Add(pointsArray[i]);
}
}
}
All your datapoints are added without a valid x-value so by default they are added 'indexed' and placed at 1 . You can change that by adding them with a valid x-value of your choice; use the AddXY method for this. (Recommended). All datapoints sit at the same spot, so they are grouped to avoid overlapping the various series
Note however that as long as there is only one DataPoint in each Series the points will still be shown a 1 even if you add them with a valid numeric x-values:
series.Points.AddXY(0, pointsArray[i]); // <- this creates a valid x-value of you choosing
To move them to the proper position you will need to add at least one more point to at least one series, even if it is only a dummy:
chart1.Series[0].Points.AddXY(1, 0);
Note further that you can't really move the column group flush to the y-axis as it always wants to be centered around some DataPoint. So you would have to calculate the total width of the group and then use half of it as the Minimum x-value to display; but this will be a rather complex calculation involving ChartArea percentage etc. Not recommended.. You may be fine with some trial and error..:
chartArea1.AxisX.Minimum = -0.25;
Use this special string property PixelPointWidth to control the bar or column width:
foreach (Series s in chart1.Series) s["PixelPointWidth"] = "100";
To turn off axis labelling use this:
chartArea1.AxisX.LabelStyle.Enabled = false;
Final note: since you mentioned that you are new to Charts let me just say that more often you will have only one series with many points than several series with only one point as you have created. But as it stands it is fine, one series for each category and your categries are the animals.
But imagine some other animal statistics like weight, price, age, speed etc..
Now you might want to use these as the categories and add one data point for each animal..
I think this piece of code will do what you expected. Your created a new series for each animal so you get four series with one data point and the chart tries to group all values on data point "1".
string[] seriesArray = { "Cat", "Dog", "Bird", "Monkey" };
Series series = chart1.Series.Add("Animals");
int[] pointsArray = { 2, 1, 7, 5 };
for (int i = 0; i < seriesArray.Length; i++)
{
DataPoint point = series.Points.Add(pointsArray[i]);
point.AxisLabel = seriesArray[i];
}
So basically I have a graph as below in the image, I am going to be implementing some check boxes to enable and disable each line graph.
My main question is:
As you can see on the graphs there is dips in the data down to ZERO - How do I get these to automatically highlight for the user to see!
I.e. Set a point on the X Axis that displays interval!
One way would be to add a another Series of ChartType Point and add only those Zero Points as red dots..:
// add a new Series:
Series sz = chart1.Series.Add("Zeroes");
sz.ChartType = SeriesChartType.Point;
sz.Color = Color.Red;
sz.BorderWidth = 3;
// add Points wherever the other series is zero or less
foreach (DataPoint dp in chart1.Series[0].Points )
{
if (dp.YValues[0] <= 0) sz.Points.AddXY(dp.XValue, 0);
}
If you need to check on more Series you can repeat the loop for them..
I'm trying to use the chart control on a windows form and have it working, plotting some real time data, however before the data arrives nothing is displayed. I would like to show an empty graph with an X Y of 10 30 but still have the graph auto range if values go above this.
I cannot find a property to show the "blank" graph it this possible and if so how?
thanks
You can hide all data of a Series by making its line color Transparent. If you also set its LegendText to be " " all you can see are the Axis ticks. you can control them by adding a few Points and by setting the Minimum and Maximum values:
// short reference for our dummy:
Series S0 = chart1.Series[0];
// a simple type
S0.ChartType = SeriesChartType.Line;
// set 10 point with x-values going from 0-100 and y-values going from 1-10:
for (int i = 0; i < 100; i +=10) S0.Points.AddXY(i , i / 10);
// or add only a few, e.g. the first and last points:
//S0.Points.AddXY(100, 10);
//S0.Points.AddXY(0, 10);
// hide the line:
S0.Color = Color.Transparent;
// hide the legend text (it will still take up a little space, though)
S0.LegendText = " ";
// limit the axis to the target values
chart1.ChartAreas[0].AxisX.Maximum = 100;
chart1.ChartAreas[0].AxisX.Minimum = 0;
The result looks like an empty chart:
This is an incredibly localized problem but I've spent a while on it now and just can't get the formatting to work. Basically what I want to do is show a column chart for a value but no bells and whistles (i.e. no labeling, no title, no legend, nothing!) And I want it to look like this:
But instead it looks like this:
The axis extends out and to the right and I can't figure out how to make it go away. Here is my code:
charts[i].Series.Clear();
charts[i].Series.Add("Block " + i + 1);
charts[i].Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column;
charts[i].Series[0].Points.Add(liveData[i]);
charts[i].ChartAreas[0].AxisY.Maximum = 4;
charts[i].ChartAreas[0].AxisY.Minimum = 0;
charts[i].ChartAreas[0].AxisX.Maximum = 1;
charts[i].ChartAreas[0].AxisX.Minimum = 1;
charts[i].ChartAreas[0].AxisX.MajorGrid.LineWidth = 0;
charts[i].ChartAreas[0].AxisY.MajorGrid.LineWidth = 0;
charts[i].ChartAreas[0].AxisX.LabelStyle.Enabled = false;
charts[i].ChartAreas[0].AxisY.LabelStyle.Enabled = false;
charts[i].ChartAreas[0].AxisY.LineWidth = 0;
charts[i].ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
charts[i].ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
charts[i].Series[0].IsVisibleInLegend = false;
Now I am guessing this is a min/max thing but for the life of me I just can't get it to work. Can someone see my mistake? Or suggest another method besides charts?
Also note the 'Block 1 (V)' label you see underneath is not generated by the chart, it is a textbox label that just happened to get cut into the screenshot.
Thanks!
Your data has the x-value of 1. By default the bar is centered on the 1 mark. by shifting the limits you are actually only seeing half of it. Two things to do: Tell the bar exactly how wide it shall be and limit the x-axes accordingly.
charts[i].Series[0].CustomProperties = "PointWidth = 1"; // One bar takes a width of 1 unit on the x-axis
charts[i].ChartAreas[0].AxisX.Minimum = 0.5; // change!
charts[i].ChartAreas[0].AxisX.Maximum = 1.5; // change!
So I am working on building a WPF TeeChart Editor, but I am having some issues with trying to change the Type of a Series on a chart using the static method:
Steema.TeeChart.WPF.Styles.Series.ChangeType(ref Series s, Type newType)
Original code idea:
//user has selected a sample chart showing the Series Type they want
Type targetType = selectedChart.Series[0].GetType();
//SelectedItems contains Series objects already on a chart
for (int i = 0; i < SelectedItems.Count; i++)
{
Series sS = (Series) SelectedItems[i];
Series.ChangeType(ref sS, targetType);
}
When the above code runs, my chart ends up with two series: the original, and a new series that is some blend of the original and the target.
For example, if I put a Points Series on the Chart with 4 random values, then run the above code with the only thing in SelectedItems being the points series I just created, my chart has a new series of type Line but with point markers on it, as well as the original Points Series.
I modified the above code to remove duplicates, then I realized something was removing the other items from the SelectedItems collection. Below is the final code that removes the original Series and also works when multiple Series are in the SelectedItems collection.
//Added List to keep selected items since they were being lost
List<Series> selected = new List<Series>(SelectedItems.Count);
for (int x = 0; x < SelectedItems.Count; x++)
selected.Add((Series) SelectedItems[x]);
for (int i = 0; i < selected.Count; i++)
{
Series sS = selected[i];
int cI = chart.Series.IndexOf(sS); //added to track index in chart
Series.ChangeType(ref sS, targetType);
//The following line ensures overwite of original Series in chart
// since new Series is being created inside above method
chart.Series[cI] = sS;
//finally, remove original Series from chart
chart.Series.Remove(selected[i]);
}
That fixes the problem with it leaving the original Series on the chart, but I still cannot figure out why the Style of the Series is becoming some strange blend of the original and the target Series Type.
Is there something I am missing or overlooking in my approach? Is there a better method to call to change the type of a Series? I was unable to find any useful information in the TeeChart documentation.
I do not think this behavior is intended because when I compare the output I am getting from this method with the WinForms TeeChart Editor, the WinForms version does not blend the styles of the Series.
I am afraid it is a bug of TeeChartWPF and we have added it in bug list report with number [TW16016232]. We will try to fix it to upcoming maintenance releases of TeeChartFor.Net. On the other hand, I suggest you a workaround to solve your problem, it consist in do that the source series are replaced for Points Series, in this case.
private void InitializeChart()
{
tChart1.Series.Clear();
Steema.TeeChart.WPF.Styles.Line line1 = new Steema.TeeChart.WPF.Styles.Line(tChart1.Chart);
Steema.TeeChart.WPF.Styles.Line line2 = new Steema.TeeChart.WPF.Styles.Line(tChart1.Chart);
line2.FillSampleValues();
line1.FillSampleValues();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 2; i++)
{
Steema.TeeChart.WPF.Styles.Points s = new Steema.TeeChart.WPF.Styles.Points(tChart1.Chart);
s.DataSource = tChart1[i];
tChart1[i].Visible = false;
}
}
Can you tell us, if previous code works as you expect, at the moment?
I hope will help.
Thanks,
Best Regards,
Sandra Pazos
Steema Support Central
http://www.steema.com/