Binding Cartesian livecharts to a data table adaptor - c#

I've been trying to to bind a data table adaptor to a Cartesian livecharts line series in c# winform with no luck
I've tried multiple method and none of them worked
Also there is no video on YouTube on how to bind the line series to data table adaptors only to simple data grid view so that data be inserted manually
I have done it with pie chart and I am in desperate need to do the same with line series
Could you help me to solve this problem
Best regards
cartesianChart2.Series.Clear();
SeriesCollection series = new SeriesCollection();
var types= (from o in brake1BindingSource.DataSource as List<Brake1TableAdapter>
select new { Braketype = o.Braketype }).Distinct();
foreach (var type in types)
{
List<double> values = new List<double>();
for (int vin= 1; vin<= 10000; vin++)
{
double value = 0;
var data = from o in brake1BindingSource.DataSource as List<Brake1TableAdapter>
where o.Braketype .Equals(type.Braketype ) && o.Braketype .Equals(vin)
orderby o.VIN ascending
select new { o.filling_amount, o.VIN };
if (data.SingleOrDefault() != null)
value = (double)data.SingleOrDefault().filling_amount;
values.Add(value);
}
series.Add(new LineSeries() { Title = type.Braketype .ToString(), Values = new ChartValues<double>(values) });
}
cartesianChart1.Series = series;

Related

How compare charts using a List<T> with LiveCharts?

I'm trying to compare a lot of charts using Live Charts according with the numbers of classes inside my List.
I'm trying some like this:
class MyClass
{
IList<double> a;
IList<double> b;
}
And to make a chart:
List<MyClass> aLotOfCharts = new List<MyClass>
for(int i=0; i < aLotOfCharts.Count; i++)
{
SeriesCollection = new SeriesCollection
{
new LineSeries
{
Values = new ChartValues<double> (aLotOfCharts[i].a)
},
};
}
I expect three charts with the "a" Data, but the actual output is only the last position of "aLotOfCharts.a".
I know I need to create more "new LineSeries" to input more charts, but I don't know how I can do this.
I do not know the Live Chart, but I think the answer is something like this:
List<MyClass> aLotOfCharts = new List<MyClass>()
SeriesCollection = new SeriesCollection()
for(int i=0; i < aLotOfCharts.Count; i++)
{
SeriesCollection.Add(new LineSeries
{
Values = new ChartValues<double> (aLotOfCharts[i].a)
});
}

C# simply chart binding

The idea is to simply to plot arrD[i] in a chart called chart5 SeriesA. The issue is that nothing is plotted in the windows form. Maybe someone could help. Many thanks.
chart5 = new Chart();
Series SeriesA = new Series();
Dictionary<int, double> value5 = new Dictionary<int, double>();
for (int i = 0; i < monthCount; i++)
{
value5.Add(i, arrD[i]);
}
SeriesA.XValueMember = "Location";
SeriesA.YValueMembers = "Value";
chart5.DataSource = value5;
chart5.Series.Add("SeriesA");
You do not add the series you created to your chart.
Try this code :
Series SeriesA = new Series();
SeriesA.Points.DataBind(arrD, "Location", "Value", "");
chart5.Series.Add(SeriesA);
Note that we add SeriesA and not "SeriesA"
Ok, I simplified the binding (which works well now) as well as the loop for hiding the zero values. But how to print now the modified chart without zero values .. many thanks.
chart7.Series["Series3"].ChartType = SeriesChartType.Line;
chart7.Series["Series3"].Points.DataBindXY(xVal, arrDouble3);
foreach (Series series in chart7.Series)
{
foreach (DataPoint arrP in series.Points)
{
if (arrP.YValues.Length > 0 && (double)arrP.YValues.GetValue(0) == 0)
{
arrP.IsValueShownAsLabel = false;
}
}
}
chart7.Series["Series3"].Points.DataBindXY(xVal, arrP); ????

Use LINQ to populate controls from object array

I am just trying to find a better way to populate some RadioButtonList controls. There are a set number of these on the usercontrol.ascx. The code is what I am currently using but I am still not very good with Linq and was wondering if there's a better way to do this.
quizId1 = quiz.Items[0].questionId;
pTag1.InnerText = quiz.Items[0].QuestionText;
foreach (Question q in quiz.Items[0].AnswerChoice)
{
radiobuttonlist1.Items.Add(new ListItem(q.Value, q.answerId));
}
same for radiobuttonlist2 but using Items[1] etc.
quizId2 = quiz.Items[1].questionId;
pTag2.InnerText = quiz.Items[1].QuestionText;
foreach (Question q in quiz.Items[1].AnswerChoice)
{
radiobuttonlist2.Items.Add(new ListItem(q.Value, q.answerId));
}
Sorry, the InnerText is a server side 'P' tag, pTag1, pTag2 etc.
Try this
var listItems = (from x in quiz.Items[0].AnswerChoice
select new ListItem { Text = q.Value, Value = q.answerId }
).ToList<ListItem>();
radiobuttonlist1.DataSource = listItems;
radiobuttonlist1.DataBind();
I suppose you could do something like this:
var listItems = from q in quiz.Items[0].AnswerChoice
select new ListItem(q.Value, q.answerId);
radioButtonlist1.Items.AddRange(listItems.ToArray());
though I'm not really sure if that buys you anything other than experience with LINQ...
I assume you want to use ling to popiulate several controls, not an individual control.
Linq is for querying, not updating. To update you still need either for or foreach loops.
If your RadioButtonList objects are in a collection, you could just loop over them:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].Items.AddRange(quiz.Items[i]
.AnswerChoice
.Select(q => => new ListItem(q.Value, q.answerId))
.ToArray()
);
}
or use DataSource as others have suggested:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].DataSource = quiz.Items[i].AnswerChoice;
radioList[i].DataTextField = "Value";
radioList[i].DataValueField = "answerId";
}
but there's no Linq way to populate several controls.

Creating a two-dimensional array

I am trying to create a two dimensional array and I am getting so confused. I was told by a coworker that I need to create a dictionary within a dictionary for the array list but he couldn't stick around to help me.
I have been able to create the first array that lists the the programs like this
+ project 1
+ project 2
+ project 3
+ project 4
The code that accomplishes this task is below-
var PGList = from x in db.month_mapping
where x.PG_SUB_PROGRAM == SP
select x;
//select x.PG.Distinct().ToArray();
var PGRow = PGList.Select(x => new { x.PG }).Distinct().ToArray();
So that takes care of my vertical array and now I need to add my horizontal array so that I can see the total amount spent in each accounting period. So the final output would look like this but without the dashes of course.
+ program 1-------100---200---300---400---500---600---700---800---900---1000---1100---1200
+ program 2-------100---200---300---400---500---600---700---800---900---1000---1100---1200
+ program 3-------100---200---300---400---500---600---700---800---900---1000---1100---1200
+ program 4-------100---200---300---400---500---600---700---800---900---1000---1100---1200
I have tried to use a foreach to cycle through the accounting periods but it doesn't work. I think I might be on the right track and I was hoping SO could provide some guidance or at the very least a tutorial for me to follow. I have posted the code that I written so far on the second array below. I am using C# and MVC 3. You might notice that their is no dictionary within a dictionary. If my coworker is correct how would I do something like that, I took a look at this question using dictionary as a key in other dictionary but I don't understand how I would use it in this situation.
Dictionary<string, double[]> MonthRow = new Dictionary<string, double[]>();
double[] PGContent = new double[12];
string lastPG = null;
foreach (var item in PGRow)
{
if (lastPG != item.PG)
{
PGContent = new double[12];
}
var MonthList = from x in db.Month_Web
where x.PG == PG
group x by new { x.ACCOUNTING_PERIOD, x.PG, x.Amount } into pggroup
select new { accounting_period = pggroup.Key.ACCOUNTING_PERIOD, amount = pggroup.Sum(x => x.Amount) };
foreach (var P in MonthList)
{
int accounting_period = int.Parse(P.accounting_period) - 1;
PAContent[accounting_period] = (double)P.amount;
MonthRow[item.PG] = PGContent;
lastPG = item.PG;
}
I hope I have clearly explained my issue, please feel free to ask for any clarification needed as I need to solve this problem and will be checking back often. Thanks for your help!
hope this helps.
// sample data
var data = new Dictionary<string, List<int>>();
data.Add("program-1", new List<int>() { 100, 110, 130 });
data.Add("program-2", new List<int>() { 200, 210, 230 });
data.Add("brogram-3", new List<int>() { 300, 310, 330 });
// query data
var newData = (from x in data
where x.Key.Contains("pro")
select x).ToDictionary(v => v.Key, v=>v.Value);
// display selected data
foreach (var kv in newData)
{
Console.Write(kv.Key);
foreach (var val in kv.Value)
{
Console.Write(" ");
Console.Write(val.ToString());
}
Console.WriteLine();
}
output is:
program-1 100 110 130
program-2 200 210 230
Don't try to use anonymous types or LINQ projection to create new data types, especially if you're a beginner, you will just get confused. If you want a specialized data type, define one; e.g.:
public class Account
{
public string Name { get; private set; }
public decimal[] MonthAmount { get; private set; }
readonly int maxMonths = 12;
public Account(string name, ICollection<decimal> monthAmounts)
{
if (name == null)
throw new ArgumentNullException("name");
if (monthAmounts == null)
throw new ArgumentNullException("monthAmounts");
if (monthAmounts.Count > maxMonths)
throw new ArgumentOutOfRangeException(string.Format(" monthAmounts must be <= {0}", maxMonths));
this.Name = name;
this.MonthAmount = new decimal[maxMonths];
int i = 0;
foreach (decimal d in monthAmounts)
{
this.MonthAmount[i] = d;
i++;
}
}
}
Use instances of this type directly, you do not have to convert them to arrays, dictionaries, lists, or anything else:
var accountPeriods = new List<Account>();
accountPeriods.Add(new Account("program-1", new decimal[] { 1, 2, 3, 4 }));
You can use LINQ or whatever to query or alter instances of your new type:
foreach (Account a in accountPeriods)
foreach (decimal d in a.MonthAmount)
DoSomethingWith(d);
That should be enough to get you started.
I want to thank #Ray Cheng and #Dour High Arch for their help but I have figured out another way to accomplish this task and I wanted to post my code so that the next person that is having the same trouble can figure out their problem faster.
Above I split my code into more managable sections to explain my problem as clearly as I could and the code below has all those parts combined so you can see the big picture. This code returns an array that contains the program and the amounts for every month.
public virtual ActionResult getAjaxPGs(string SP = null)
{
if (SP != null)
{
var PGList = from x in db.month_mapping
where x.PG_SUB_PROGRAM == SP
select x;
var PGRow = PGList.Select(x => new { x.PG }).Distinct().ToArray();
float[] PGContent = new float[12];
Dictionary<string,float[]> MonthRow = new Dictionary<string, float[]>();
foreach (var item in PGRow)
{
PGContent = new float[12];
var MonthList = from x in db.month_Web
where x.PG == item.PG
group x by new { x.ACCOUNTING_PERIOD, x.PG, x.Amount } into pggroup
select new { accounting_period = pggroup.Key.ACCOUNTING_PERIOD, amount = pggroup.Sum(x => x.Amount) };
foreach (var mon in MonthList)
{
int accounting_period = int.Parse(mon.accounting_period) - 1;
PGContent[accounting_period] = (float)mon.amount/1000000;
}
MonthRow[item.PG] = PGContent;
}
return Json(MonthRow, JsonRequestBehavior.AllowGet);
}
return View();
}
This code worked great for me since I am pulling from a Linq to SQL query instead of adding data directly into the code. My problems stemmed from mainly putting the data pulls outside of the foreach loops so it only pulled 1 piece of data from the SQL instead of all twelve months. I hope this helps some one else who is trying to pull data in from SQL data sources into multidimensional arrays.

Converting data from discrete properties of objects in an IEnumerable into an array/series for charting?

I have an IEnumerable (List<>) of a particular Type. The Type has a set of properties which I would like to chart as individual series (MVC3/Razor).
Is there a way I can transpose the data in the list of objects into a list of the properties?
e.g.
Given the code below, the end result I am trying to acheive is a set of Series so I have
Bucket1: IEnumerable<Date, Value>
Bucket2: IEnumerable<Date, Value>
etc
So that I can then chart each series to get a line chart with Date on x and value on y, for (in this example) 3 series/lines. This code works perfectly, but just feels wrong somehow?
var buckets = new List<Bucket>(){
new Bucket{
Date=DateTime.Today.AddDays(-3),
Bucket1=1000,
Bucket2=2000,
Bucket3=3000},
new Bucket{
Date=DateTime.Today.AddDays(-2),
Bucket1=1000,
Bucket2=2020,
Bucket3=3300},
new Bucket{
Date=DateTime.Today.AddDays(-1),
Bucket1=1000,
Bucket2=2040,
Bucket3=3600}
};
var chart = new Chart(){ Height = 400, Width = 600 };
var area = new ChartArea();
chart.ChartAreas.Add(area);
var series1 = chart.Series.Add("Bucket 1");
var series2 = chart.Series.Add("Bucket 2");
var series3 = chart.Series.Add("Bucket 3");
foreach (var series in chart.Series)
{
series.ChartType = SeriesChartType.Line;
}
foreach (var item in buckets)
{
series1.Points.AddXY(item.Date, item.Bucket1);
series2.Points.AddXY(item.Date, item.Bucket2);
series3.Points.AddXY(item.Date, item.Bucket3);
}
What about just using a Lambda expression for each serie (code below was not tested - it's just a prototype):
var series1 = buckets.Select(b => new { b.Date, b.Bucket1 });
var series2 = buckets.Select(b => new { b.Date, b.Bucket2 });
Thanks to the comments posted I kept my original code and don't think there's an easier way to do this.

Categories