Traversing a nested LINQ query in of anonymous objects in C# view via ASP.NET MVC
Traversing a nested LINQ query in of anonymous objects in C# view via ASP.NET MVC
Hi, done a lot of searching and reading but still require some specific information. I have the following code:
List<DateTime> range = getRangeCollection();
var range = (
from years in rangeData
group years by years.Year
into yearsData
select new {
year = yearsData.Key,
months = (
from month in yearsData
group month by month.Month
into monthsData
select new {
month = monthsData.Key,
days = (
from days in monthsData
group days by days.Day
into daysData
select new {
day = monthsData.Key,
days = daysData
})
})
}).ToList();
I can send this as a ViewData property to a view like so.
<% foreach (var date in ((IEnumerable)ViewData["range"])) {
// another foreach needed to access date.month and loop days inside.
%>
<p><%=date%></p>
<% } %>
But I want use it to generate HTML that looks like the following:
2009
January
(all the days in jan)
February
(all the days in feb)
..ect
2010
Janurary
(al开发者_C百科l the days in jan)
February
...ect
I'm not sure if my LINQ is correct, but I'm trying to traverse the results in a ASP.NET MVC environment. I'm trying to get my head around IEnumerable and IQueryable. Am I on the right track?
I think you might be overcomplicating the solution, based on what I think you're trying to do. Ultimately it would be cool to write a little class to handle this type of data structure, where you want to aggregate the dates based on year and month.
I'm assuming that you want to leave out years / months that are empty, or that your date range is unlikely to have gaps. You'll also notice that I'm using IQueryable, rather than IEnumerable.
Basically you need to distinct the years in your range, and then distinct the months in each of the years. So, given this data set:
List<DateTime> dateRange = new List<DateTime>();
dateRange.Add(new DateTime(2009, 5, 18));
dateRange.Add(new DateTime(2009, 5, 12));
dateRange.Add(new DateTime(2009, 6, 22));
dateRange.Add(new DateTime(2009, 2, 14));
dateRange.Add(new DateTime(2009, 11, 23));
dateRange.Add(new DateTime(2010, 5, 2));
dateRange.Add(new DateTime(2010, 7, 17));
dateRange.Add(new DateTime(2010, 7, 10));
dateRange.Add(new DateTime(2009, 11, 28));
dateRange.Add(new DateTime(2009, 11, 16));
dateRange.Add(new DateTime(2010, 1, 30));
dateRange.Add(new DateTime(2010, 3, 1));
dateRange.Add(new DateTime(2010, 9, 23));
dateRange.Add(new DateTime(2010, 5, 1));
dateRange.Add(new DateTime(2010, 9, 4));
ViewData["range"] = dateRange.AsQueryable();
You could iterate through it in your view by doing:
<% var range = ViewData["range"] as IQueryable<DateTime>; %>
<% foreach (var year in range.Select(x=>x.Year)
.Distinct()
.OrderBy(x=>x))
{ %>
<ul>
<li><%=year %>
<ul>
<% foreach (var month in range.Where(x=>x.Year==year)
.OrderBy(x=>x.Month)
.Select(x=>x.Month)
.Distinct()) { %>
<li><%=(new DateTime(1900,month,1)).ToString("MMMM") %>
<ul>
<% foreach (var day in range.Where(x => x.Year == year && x.Month == month))
{ %>
<li>
<%=day.ToLongDateString() %>
</li>
<% } %>
</ul>
</li>
<% } %>
</ul>
</li>
</ul>
Ideally you just want to either use extension methods or a wrapper class so you could do:
foreach(var year in range.DistinctYears())
The months something that wraps the English format around the integer value would be nice too.
See how that works out for you.
Couldn't you simply OrderBy() this list by Year, Month, Day? Am I missing something?
range.OrderBy(r => r.Year).OrderBy(r => r.Month)...
精彩评论