通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询

Posted

技术标签:

【中文标题】通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询【英文标题】:Traversing a nested LINQ query in of anonymous objects in C# view via ASP.NET MVC 【发布时间】:2010-01-27 14:13:55 【问题描述】:

您好,进行了大量搜索和阅读,但仍需要一些具体信息。 我有以下代码:

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

我可以将它作为 ViewData 属性发送到这样的视图。

    <% foreach (var date in ((IEnumerable)ViewData["range"]))  
// another foreach needed to access date.month and loop days inside.
 %> 
 <p><%=date%></p>
  <%  %>

但我想用它来生成如下所示的 html

2009
  January
    (all the days in jan)
  February
    (all the days in feb)
    ..ect
2010
  Janurary
    (all the days in jan)
  February
    ...ect

我不确定我的 LINQ 是否正确,但我正在尝试在 ASP.NET MVC 环境中遍历结果。我试图了解 IEnumerable 和 IQueryable。我在正确的轨道上吗?

【问题讨论】:

【参考方案1】:

根据我认为您正在尝试做的事情,我认为您可能使解决方案过于复杂。最终,编写一个小类来处理这种类型的数据结构会很酷,您希望在其中根据年份和月份聚合日期。

我假设您想省略空的年份/月份,或者您的日期范围不太可能有间隔。您还会注意到我使用的是 IQueryable,而不是 IEnumerable。

基本上,您需要区分范围内的年份,然后区分每年的月份。所以,给定这个数据集:

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

您可以通过以下方式在视图中遍历它:

<% 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>

理想情况下,您只想使用扩展方法或包装类,这样您就可以做到:

foreach(var year in range.DistinctYears())

将英文格式包裹在整数值周围的月份也会很好。

看看你的效果如何。

【讨论】:

布里克斯顿,非常感谢!在您的帮助下,它完全符合我的需要。我觉得我所知道的关于 ASP.NET 的所有知识都开始为我联系在一起了 :) 干杯!【参考方案2】:

您不能按年、月、日简单地 OrderBy() 这个列表吗?我错过了什么吗?

range.OrderBy(r => r.Year).OrderBy(r => r.Month)...

【讨论】:

以上是关于通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询的主要内容,如果未能解决你的问题,请参考以下文章

C# 和 ASP.NET MVC:在视图中使用 #if 指令

ASP.NET MVC & C#:将视图模型传递给控制器

C# ASP.NET MVC:动态更新视图

asp.net mvc视图中的C#复选框事件不在表单内

如何在 ASP.NET MVC 视图中用 C# 打印出 GridView?

asp.net mvc c# - 是不是可以从 CodeBehind 中的模型访问视图中文本框的值?