How can I remove line shadows on Live Chart line chart? - c#

I created a line chart using a live chart. But I cannot eliminate the shadows (shaded areas in the image) under these lines.
LineSeries yeni = new LineSeries();
yeni.PointGeometrySize = 20;
yeni.LineSmoothness = 0;
// yeni.BitmapEffect.
// yeni.PointForeground = System.Windows.Media.Brushes.Transparent;
yeni.Title = kisiler[i].ToString();
yeni.Values = new ChartValues<double>(allValues);
cartesianChart1.Series.Add(yeni);

This way I solved the problem:
yeni.Fill = System.Windows.Media.Brushes.Transparent;

Related

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)

Separate Legends for Multiple ChartAreas in Single Chart

I cannot seem to get my individual subcharts (contained within my single chart object) to host individual legends for their respective data series. I would like to know if this is possible and, if so, what I can adjust in my code to achieve this effect.
Thanks for your help
Code is as follows:
chart_MyChart.Legends.Clear();
ChartArea chartArea_MyData = new ChartArea("My Data");
ChartArea chartArea_YourData = new ChartArea("Your Data");
ChartArea chartArea_OtherData = new ChartArea("Other Data");
chart_MyChart.ChartAreas.Clear();
chart_MyChart.ChartAreas.Add(chartArea_MyData);
chart_MyChart.ChartAreas.Add(chartArea_YourData);
chart_MyChart.ChartAreas.Add(chartArea_OtherData);
/* Chart Area: My Data */
Series series01 = this.chart_MyChart.Series.Add("My first series");
series01.ChartArea = chartArea_MyData.Name;
Series series02 = this.chart_MyChart.Series.Add("My second series");
series02.ChartArea = chartArea_MyData.Name;
Legend legend01 = new Legend(series01.Name);
Legend legend02 = new Legend(series02.Name);
legend01.DockedToChartArea = chartArea_MyData.Name;
legend02.DockedToChartArea = chartArea_MyData.Name;
chart_MyChart.Legends.Add(legend01);
chart_MyChart.Legends.Add(legend02);
/* Chart Area: Your Data */
Series series03 = this.chart_MyChart.Series.Add("Your first series");
series03.ChartArea = chartArea_YourData.Name;
Series series04 = this.chart_MyChart.Series.Add("Your second series");
series04.ChartArea = chartArea_YourData.Name;
Legend legend03 = new Legend(series03.Name);
Legend legend04 = new Legend(series04.Name);
legend03.DockedToChartArea = chartArea_YourData.Name;
legend04.DockedToChartArea = chartArea_YourData.Name;
chart_MyChart.Legends.Add(legend03);
chart_MyChart.Legends.Add(legend04);
/* Chart Area: Other Data */
Series series05 = this.chart_MyChart.Series.Add("Other series");
series05.ChartArea = chartArea_OtherData.Name;
Legend legend05 = new Legend(series05.Name);
legend05.DockedToChartArea = chartArea_OtherData.Name;
chart_MyChart.Legends.Add(legend05);
foreach(Legend legend in chart_MyChart.Legends)
{
legend.IsDockedInsideChartArea = true;
}
foreach(widget myWidget in some.widget)
{
series01.Points.AddXY(widget.timeStamp, widget.data1);
series02.Points.AddXY(widget.timeStamp, widget.data2);
series03.Points.AddXY(widget.timeStamp, widget.data3);
series04.Points.AddXY(widget.timeStamp, widget.data4);
series05.Points.AddXY(widget.timeStamp, widget.data5);
}
At first glance you seem to be missing the association between the series and the Legend this is from the WebSamples project that you can download here, it really helps to see a full source examples.
In the MultiLegends section, the code looks like this:
// Add a second legend
Legend secondLegend = new Legend("Second");
secondLegend.BackColor = Color.FromArgb(((System.Byte)(220)), ((System.Byte)(255)), ((System.Byte)(255)), ((System.Byte)(255)));
secondLegend.BorderColor = Color.Gray;
secondLegend.Font = this.Chart1.Legends["Default"].Font;
this.Chart1.Legends.Add(secondLegend);
// Associate Series 2 with the second legend
this.Chart1.Series["Series 2"].Legend = "Second";
The only thing that I didn't see in your code is that last line of association.

C# Winchart configuration, adding more lines

I am having some trouble with my C# chart.
I want to create a winnings chart.
This chart is what I want to create:
I currently have this:
WinChart.ChartAreas[0].AxisY.Title = "$ USD";
WinChart.ChartAreas[0].AxisY.Minimum = -1;
WinChart.ChartAreas[0].AxisY.Maximum = 1;
WinChart.ChartAreas[0].AxisX.Title = "Tourneys";
WinChart.ChartAreas[0].AxisX.Minimum = 0;
WinChart.ChartAreas[0].AxisX.IsStartedFromZero = true;
WinChart.Series[0].Points.Add(0);
WinChart.Series[0].Points.Add(0.10);
WinChart.Series[0].Points.Add(0.20);
WinChart.Series[0].Points.Add(0.30);
WinChart.Series[0].Points.Add(-0.50);
WinChart.Series[0].Points.Add(-0.60);
WinChart.Series[0].Points.Add(-0.70);
How can I make it start at the coordinates 0,0 and how do I make a middle line that is $0 ?
Documentation link: http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.aspx
I'm going to assume some thing. WinChart is probably inheriting from Chart:
public class WinChart : Chart { }
and that ChartAreas is a ChartAreaCollection object and the same with Series
So I would do something like:
WinChart.ChartAreas[0].AxisY.Title = "$ USD";
WinChart.ChartAreas[0].AxisY.Minimum = -1;
WinChart.ChartAreas[0].AxisY.Maximum = 1;
WinChart.ChartAreas[0].AxisY.Interval = 0.2; // adjusts y axis scale
WinChart.ChartAreas[0].AxisX.Title = "Tourneys";
WinChart.ChartAreas[0].AxisX.Minimum = 0;
Series series = new Series();
series.Points.Add(0,0);
...
series.Points.Add(5, 1.05);
WinChart.Series.Add(series);
//repeat last five lines to add second line to graph

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);

How to plot MULTIPLE LineSeries on an OxyPlot chart?

I apologize for asking so many OxyPlot questions, but I seem to be really struggling with using the OxyPlot chart control.
My project is in WPF format so I was originally using a hosted WINFORMS chart and that worked like a charm and did absolutely everything I needed it to until I needed to overlay a WPF element on top of the hosted winform chart. Due to the "AirSpace" issue, I was not able to see the WPF element that I put on top of the hosted chart no matter what I did. That is when I decided to go with OxyPlot, which is giving me quite a few headaches so far.
Here is my origional question! that I asked over at CodePlex. I don't seem to be getting much help over there so I am trying again here.
My question is:
Does anyone know how to plot MULTIPLE LineSeries onto a Plot??
My approach so far:
I am taking a c# List array and adding a new copy of the LineSeries that holds new data to be plotted. My code:
// Function to plot data
private void plotData(double numWeeks, double startingSS)
{
// Initialize new Salt Split class for acess to data variables
Salt_Split_Builder calcSS = new Salt_Split_Builder();
calcSS.compute(numWeeks, startingSS, maxDegSS);
// Create the OxyPlot graph for Salt Split
OxyPlot.Wpf.PlotView plot = new OxyPlot.Wpf.PlotView();
var model = new PlotModel();
// Add Chart Title
model.Title = "Salt Split Degradation";
// Create new Line Series
LineSeries linePoints = new LineSeries() { StrokeThickness = 1, MarkerSize = 1, Title = numWeeks.ToString() + " weeks" };
// Add each point to the new series
foreach (var point in calcSS.saltSplitCurve)
{
DataPoint XYpoint = new DataPoint();
XYpoint = new DataPoint(point.Key, point.Value * 100);
linePoints.Format("%", XYpoint.Y);
linePoints.Points.Add(XYpoint);
}
listPointAray.Add(linePoints);
// Define X-Axis
var Xaxis = new OxyPlot.Axes.LinearAxis();
Xaxis.Maximum = numWeeks;
Xaxis.Minimum = 0;
Xaxis.Position = OxyPlot.Axes.AxisPosition.Bottom;
Xaxis.Title = "Number of Weeks";
model.Axes.Add(Xaxis);
//Define Y-Axis
var Yaxis = new OxyPlot.Axes.LinearAxis();
Yaxis.MajorStep = 15;
Yaxis.Maximum = calcSS.saltSplitCurve.Last().Value * 100;
Yaxis.MaximumPadding = 0;
Yaxis.Minimum = 0;
Yaxis.MinimumPadding = 0;
Yaxis.MinorStep = 5;
Yaxis.Title = "Percent Degradation";
model.Axes.Add(Yaxis);
// Add Each series to the
foreach (var series in listPointAray)
{
LineSeries newpoints = new LineSeries();
newpoints = linePoints;
model.Series.Add(newpoints);
}
// Add the plot to the window
plot.Model = model;
SaltSplitChartGrid.Children.Add(plot);
}
My code works the first time I press my "Graph Data" button, but fails on consecutive attempts with the following error:
The element cannot be added, it already belongs to a Plot Model
The following plot is the type of plot I would like to produce (it worked fine using WinForms Chart control):
I would like a new line with a new color to be plotted each time I run the method.
This is how I've created multi lines on an OxyPlot chart before, the key is creating a set of DataPoints for each series - called circlePoints & linePoints in the following example code, these are then bound to the CircleSeries and LineSeries:
var xAxis = new DateTimeAxis
{
Position = AxisPosition.Bottom,
StringFormat = Constants.MarketData.DisplayDateFormat,
Title = "End of Day",
IntervalLength = 75,
MinorIntervalType = DateTimeIntervalType.Days,
IntervalType = DateTimeIntervalType.Days,
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.None,
};
var yAxis = new LinearAxis
{
Position = AxisPosition.Left,
Title = "Value",
MajorGridlineStyle = LineStyle.Solid,
MinorGridlineStyle = LineStyle.None
};
var plot = new PlotModel();
plot.Axes.Add(xAxis);
plot.Axes.Add(yAxis);
var circlePoints = new[]
{
new ScatterPoint(DateTimeAxis.ToDouble(date1), value1),
new ScatterPoint(DateTimeAxis.ToDouble(date2), value2),
};
var circleSeries = new ScatterSeries
{
MarkerSize = 7,
MarkerType = MarkerType.Circle,
ItemsSource = circlePoints
};
var linePoints = new[]
{
new DataPoint(DateTimeAxis.ToDouble(date1), value1),
new DataPoint(DateTimeAxis.ToDouble(date2), value2),
};
var lineSeries = new LineSeries
{
StrokeThickness = 2,
Color = LineDataPointColor,
ItemsSource = linePoints
};
plot.Series.Add(circleSeries);
plot.Series.Add(lineSeries);
Sucess!!!!
AwkwardCoder, thank you for the help, but I realized my mistake was just me having overlooked some things!
Here is the version of the code that works:
// Make a new plotmodel
private PlotModel model = new PlotModel();
// Create the OxyPlot graph for Salt Split
private OxyPlot.Wpf.PlotView plot = new OxyPlot.Wpf.PlotView();
// Function to plot data
private void plotData(double numWeeks, double startingSS)
{
List<LineSeries> listPointAray = new List<LineSeries>();
// Initialize new Salt Split class for acess to data variables
Salt_Split_Builder calcSS = new Salt_Split_Builder();
calcSS.compute(numWeeks, startingSS, maxDegSS);
// Create new Line Series
LineSeries linePoints = new LineSeries()
{ StrokeThickness = 1, MarkerSize = 1, Title = numWeeks.ToString() + " weeks" };
// Add each point to the new series
foreach (var point in calcSS.saltSplitCurve)
{
DataPoint XYpoint = new DataPoint();
XYpoint = new DataPoint(point.Key, point.Value * 100);
linePoints.Format("%", XYpoint.Y);
linePoints.Points.Add(XYpoint);
}
listPointAray.Add(linePoints);
// Add Chart Title
model.Title = "Salt Split Degradation";
// Add Each series to the
foreach (var series in listPointAray)
{
// Define X-Axis
OxyPlot.Axes.LinearAxis Xaxis = new OxyPlot.Axes.LinearAxis();
Xaxis.Maximum = numWeeks;
Xaxis.Minimum = 0;
Xaxis.Position = OxyPlot.Axes.AxisPosition.Bottom;
Xaxis.Title = "Number of Weeks";
model.Axes.Add(Xaxis);
//Define Y-Axis
OxyPlot.Axes.LinearAxis Yaxis = new OxyPlot.Axes.LinearAxis();
Yaxis.MajorStep = 15;
Yaxis.Maximum = calcSS.saltSplitCurve.Last().Value * 100;
Yaxis.MaximumPadding = 0;
Yaxis.Minimum = 0;
Yaxis.MinimumPadding = 0;
Yaxis.MinorStep = 5;
Yaxis.Title = "Percent Degradation";
//Yaxis.StringFormat = "{0.00} %";
model.Axes.Add(Yaxis);
model.Series.Add(series);
}
// Add the plot to the window
plot.Model = model;
plot.InvalidatePlot(true);
SaltSplitChartGrid.Children.Clear();
SaltSplitChartGrid.Children.Add(plot);
}
Here are the multiple things I did wrong:
In my foreach var series loop, I was adding the original series which had already been added and NOT the next var series in the list! (dumb!)
I was creating a new model each time I ran the method. This means that each time the code ran, I was adding a series that already existed in the previous model. (also dumb!)
I was creating a new plot every time and trying to add a model in the new plot that already belonged to a previous plot. (getting dummer..)
The plot was being added to the grid each time I ran the method, so I had to CLEAR the grid's children first before re-adding the same plot.
I was not refreshing the plot.
That was a lot of mistakes, but I worked through it. Hopefully this helps someone in the future. Also, I know I am not using ordinary data binding techniques, but this, at-least, works.
Final result:
Here is how you can achieve a similar result in XAML especially if you are using the MVVM approach.
ViewModel:
public ObservableCollection<DataPoint> DataPointList1 {get;set;}
public ObservableCollection<DataPoint> DataPointList2 {get;set;}
public ObservableCollection<DataPoint> DataPointList3 {get;set;}
public ObservableCollection<DataPoint> DataPointList4 {get;set;}
Using a for loop like below populates DataPointList1 to DataPointList4 with the appropriate datasets.
for (int i = 0; i < dataList.Count; i++)
{
DataPointList1 .Add(new DataPoint{dataList[i].XValue,dataList[i].YValue });
}
XAML:
xmlns:oxy="http://oxyplot.org/wpf"
<oxy:Plot LegendPlacement="Outside" LegendPosition="RightMiddle" Title="Your Chart Title" >
<oxy:Plot.Axes>
<oxy:LinearAxis Title="Your X-axis Title" Position="Bottom" IsZoomEnabled="True" />
<oxy:LinearAxis Title="Your Y-axis Title" Position="Left" IsZoomEnabled="True" />
</oxy:Plot.Axes>
<oxy:Plot.Series>
<oxy:LineSeries Title="Plot1" Color="Black" ItemsSource="{Binding DataPointList1 }"/>
<oxy:LineSeries Title="Plot2" Color="Green" ItemsSource="{Binding DataPointList2 }"/>
<oxy:LineSeries Title="Plot3" Color="Blue" ItemsSource="{Binding DataPointList3 }"/>
<oxy:LineSeries Title="Plot4" Color="Red" ItemsSource="{Binding DataPointList4 }"/>
</oxy:Plot.Series>
</oxy:Plot>

Categories

Resources