LINQ: Finding an item in a List which contains List of items - linq

guys!
I have a small issue with LINQ (Im total beginer in this topic). Maybe it is some desing mistake, but let you decide it.
I'm coding a Windows Store App, which is kind a calendar. It has a Day object. Because of the semantic zoom (and some groupping hack), I put this Day into a wrapper class, named as Month.
After loading all data, and after getting the current data, I want to extract from this structure the current Day object.
Here is the important code:
public class Day
{
public int nr { get; set; }
...
}
public class Month
{
public string Title {get;set;}
public List<Day> Days{get;set;}
}
Later I have this:
List<Month> Months;
It is correctly filled with lists of days. Now comes the tricky part:
Day Today = Months.Find( ??? )
I had some idea, but none of them was statisfying...
So, the question is:
How can I select an item from a multiple list hierarchy in LINQ?
(List<List<Day>>, and one condition must met in each list (Day.nr and Month.nr))

Create an Enum for every month:
public enum NamesOfMonths
{
January = 1,
February = 2,
// so on and so forth
}
Now, you can use it to find the correct Month, and eventually the correct Day.
var dayToday = DateTime.Now.Day;
var monthToday = DateTime.Now.Month;
Day Today = Months.Find(m => m.Title.Equals(((NamesOfMonths)monthToday).ToString()))
.Days.Where(d => d.Nr == dayToday).FirstOrDefault();

I think you're looking for SelectMany:
var days = months.SelectMany(m => m.Days); // Gets all the days in those months
var today = days.Where(d => /* some condition goes here */);

Related

Sorting a DataGridView by DateTime

I have a website that is written in asp.net using C#. grdStatus is an instance of System.Windows.Forms.DataGridView. It displays 2 columns -- StatusDate and Status. StatusDate contains DateTime values. Status contains strings. The problem is that when the grid is sorted on StatusDate, it does not sort the values as DateTimes. Honestly, I'm not quite sure how it's sorting them. When I click on the Status Date column header, it sorts the dates like this:
Status Date
9/24/2014 10:01:06 AM
9/24/2014 10:00:58 AM
9/23/2014 7:27:23 PM
9/1/2015 4:48:35 PM
10/22/2014 12:15:38 PM
10/22/2014 12:15:29 PM
10/22/2014 12:12:52 PM
10/22/2014 12:12:27 PM
It's certainly not sorting them by DateTime, but it doesn't seem to be sorting them alphabetically, either. Here's the method that refreshes the grid. I added the two lines indicated by ---> in an attempt to force it to sort the rows by DateTime, but they seem to have no effect.
private void RefreshGrid()
{
IEnumerable<OrderService.OrderDetailStatus> statusItems = services.OrderSvc.GetStatusHistoryForOrderDetail(OrderDetailId);
IEnumerable<ViewModels.StatusHistoryGridViewModel> gridItems = AutoMapper.Mapper.Map<IEnumerable<ViewModels.StatusHistoryGridViewModel>>(statusItems);
grdStatus.AutoGenerateColumns = false;
grdStatus.DataSource = gridItems.ToDataTable<ViewModels.StatusHistoryGridViewModel>();
--->grdStatus.Columns[0].ValueType = typeof(DateTime);
--->grdStatus.Sort(grdStatus.Columns[0], ListSortDirection.Ascending);
}
Here's the view model that's being used as the data source for the grid. As you can see, CreatedDate (which is mapped to StatusDate) is a DateTime member.
namespace IVGOffice.ViewModels
{
public class StatusHistoryGridViewModel
{
public string StatusName { get; set; }
public DateTime CreatedDate { get; set; }
}
}
I've looked at some other posting related to this, but I haven't found anything that helps. Can anyone explain to me how to get this to sort correctly?
Part of the problem was that I was overlooking that fact that one of the dates had a different year from the others. After I noticed that, I was able to get the control to sort the column by the date; however, I still wasn't able to get it to sort by both date and time. I think this may be a bug in the DateGridView control. I replaced it with an UltraGrid control from Infragistics and that worked correctly.

Telerik OpenAccess - Search With Non-Persistent Property

I'm using Telerik OpenAccess and SQL Server on a project and I need to be able to search by what someone's age will be on a certain date. The problem that I am running into is that the person's date of birth is stored in one table and the date to compare to is in another table, which prevents me from using a computed column. They are, however, joined together so that I can calculate the age by creating my own non-persistent property in the partial class like so:
public partial class Student
{
[Telerik.OpenAccess.Transient]
private int? _ageUponArrival;
public virtual int? AgeUponArrival
{
get
{
try
{
var dob = DateTime.Parse(this.StudentProfiles.First().Person.YearOfBirth);
var programStart = (DateTime)(this.StudentPrograms.First().ProgramStart);
this._ageUponArrival = programStart.Year - dob.Year;
if (dob > programStart.AddYears(-(int)(this._ageUponArrival)))
{
(this._ageUponArrival)--;
}
}
catch (Exception e)
{
this._ageUponArrival = null;
}
return _ageUponArrival;
}
set { }
}
}
Please ignore how bad the tables are set up, it's something that I inherited and can't change at this point. The problem with this approach is that the property is not available to search on with Linq. I know that I could create a view that would do this for me, but I would much rather not have to maintain a view just for this. Is there any way at all to create a calculated property through Telerik that would be calculated on the db server in such a way as to be searchable?
It appears that this is not possible at this point. http://www.telerik.com/community/forums/orm/linq-questions/dynamic-query-with-extended-field.aspx

Get single value from XML and bind it to a textblock?

Trying to create a prayer time app for prayertimes in Oslo. I have a XML file located in the app.
What i want to do:
Based on month and the day, get value for morning prayer, evening prayer and so on.
I want one value at a time, and show it in a textblock. how do i do it?
I am currently getting the info in a listBox but i rather want the single value to be shown in a textblock. Or should i use some other thing?
public class PrayerTime
{
public string Fajr { get; set; }
public string Sunrise { get; set; }
}
To get the value:
XDocument loadedCustomData = XDocument.Load("WimPrayerTime.xml");
var filteredData = from c in loadedCustomData.Descendants("PrayerTime")
where c.Attribute("Day").Value == myDay.Day.ToString()
&& c.Attribute("Moth").Value == myDay.Month.ToString()
select new PrayerTime()
{
Fajr = c.Attribute("Fajr").Value,
Soloppgang = c.Attribute("Soloppgang").Value,
};
listBox1.ItemsSource = filteredData;
Also i want to know how best the XML should be set up for this purpose.
Like this:
<PrayerTime>
<Day>1</Day>
<Month>5</Month>
<Fajr>07:00</Fajr>
<Sunrise>09:00</Sunrise>
</PrayerTime>
Or like this:
<PrayerTime
Day ="1"
Month="5"
Fajr="07:00"
Sunrise="09:00"
/>
yourTextBox.Text = filteredData.First().Fajr;
As to know whether it's best to put information in a XML file as attributes or nodes, that's a recurrent question with no definite answer. In most cases, it's just a matter of taste.

LINQ (Dynamic): OrderBy within a GroupBy using dynamic linq?

I had the following query using normal linq and it was working great (using anonymous type),
var result = from s in Items
group s by s.StartTime into groupedItems
select new {groupedItems.Key, Items= groupedItems.OrderBy(x => x.Name) };
But using Dynamic Linq I cannot get it to order by within the groupby.
result = Items.GroupBy("StartTime", "it").OrderBy("Name");
It states the Name isn't available. It is worth noting that if I take my OrderBy off, everything works great but items inside each "Key" are not ordered.
This is a good question!
I simulated your situation by creating a class called Item.
public class Item
{
public DateTime StartTime { get; set; }
public string Name { get; set; }
}
and then created a basic list of items to do the groupby.
List<Item> Items = new List<Item>()
{
new Item() { StartTime = DateTime.Today, Name = "item2"},
new Item() { StartTime = DateTime.Today, Name = "item1"},
new Item() { StartTime = DateTime.Today.AddDays(-1), Name = "item3"},
};
Now the big difference in the 2 queries is where the order by is being performed. In the first query, when you perform groupedItems.OrderBy(x => x.Name) its being performed on a IGrouping<DateTime,Item> or a single entry as it iterates through all the groupings.
In the second query, the orderby is being performed after the fact. This means you're doing an orderby on a IEnumerable<IGrouping<DateTime,Item>> because the iterations have already happened.
Since Microsoft was nice they added something to help deal with this for expressions. This overload allows you to specify the item returned as it iterates through the collection. Here's an example of the code:
var expressionResult = Items.GroupBy(x => x.StartTime,
(key, grpItems) => new { key, Items = grpItems.OrderBy(y => y.Name) });
The second part of the GroupBy you can specify a lambda expression that takes a key and a grouping of items under that key and return an entry that you specify, which is the same as you're doing in the original query.
Hope this helps!

How do I group items from a collection using LINQ and return the shaped data according the collection type

I have the following collection
public IQueryable<myObjectType > GetWorkCellLoadGraphDataByIdDummy()
{
IList<myObjectType> workCellLoadGraphDataCollection = new List<myObject>()
{
new myObjectType(DateTime.Today.AddHours(8).AddMinutes(30), 1),
new myObjectType(DateTime.Today.AddHours(10).AddMinutes( 10 ), 6 ),
new myObjectType(DateTime.Today.AddHours(13).AddMinutes( 30 ),8 ),
new myObjectType(DateTime.Today.AddDays(1).AddHours(8).AddMinutes(30), 1),
new myObjectType(DateTime.Today.AddDays(1).AddHours( 10 ).AddMinutes( 10 ), 5 ),
new myObjectType(DateTime.Today.AddDays(1).AddHours( 13 ).AddMinutes( 30 ), 2 )
};
// Write some LINQ code to group data according to first parameter
// Perform sum of last parameter
// Shape the data to be in the form of myObjectType
// return result;
}
and what I want to do is to group items by the first parameter of the myObjectType class.
Then for each grouping, I'd like to do the sum of all the last parameters.
Finally the result should be returned in the form of "myObjectType"
I know how to do it the old fashioned way i.e. looping through all the items and doing the sums. However, I'd like to learn how to do it in LINQ which is something I've just started.
Can anyone point me in the right direction so that I can translate my requirements into LINQ?
In effect, the result should be a collection containing two objects of type myObjectType as follows:
First object in collection is (DateTime.Today, 15 )
Second object in collection is (DateTime.Today.AddDays(1), 8)
TIA,
David
Given a class with this basic design
class MyObjectType
{
public MyObjectType(DateTime date, int count)
{
this.MyDate = date;
this.MyCount = count;
}
public DateTime MyDate { get; set; }
public int MyCount { get; set; }
}
You could fulfill your requirement using LINQ in the manner below. The first example produces IEnumerable<MyObjectType> using fluent extension method syntax.
var query = collection.GroupBy(obj => obj.MyDate.Date)
.Select(grp =>
new MyObjectType(grp.Key, grp.Sum(obj => obj.MyCount))
);
The second version achieves the same result but uses the more SQL-esque query expression syntax.
var query = from obj in collection
group obj by obj.MyDate.Date into grp
let mySum = grp.Sum(item => item.MyCount)
select new MyObjectType(grp.Key, mySum);
From there, you utilize the extension methods AsQueryable to yield an IQueryable result, or ToList() / ToArray() to yield concrete collections.

Resources