You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C# LINQ按年月分组实现三级层级树视图结构

问题原因

你当前代码无法生成正确树形结构有两个核心问题:

  • 循环内每次都会覆盖单个TreeYear实例的属性,且每次都重新初始化Months列表,最终只会保留最后一条遍历到的报价数据,完全没有做分组聚合。
  • 你尝试编写的多层GroupBy语法错误,且分组维度选择不对,分组应该从原始的报价数据集出发,而不是基于未正确构造的TreeYear对象做二次分组。
数据模型调整

你当前定义的TreeMonth仅支持绑定单个QuoteSummary对象,而按照你要的年份-月份-关联业务项三级结构,同一个月份节点下会挂载多条关联业务数据,需要先把单对象属性调整为集合类型,否则无法承载同月下的多条数据:

public class TreeYear
{
    public string NodeYear { get; set; }
    public DateTime CreatedDateTime { get; set; }
    public List<TreeMonth> Months { get; set; } = new();
}

public class TreeMonth
{
    public int MonthID { get; set; }
    public string MonthName { get; set; }
    // 单对象改为集合,存储当月所有关联业务项
    public List<QuoteSummary> QuoteSummaries { get; set; } = new();
}

如果你的业务场景不需要对同月份数据做聚合,要求每个月份叶子节点直接对应单条业务项,可保留原有单QuoteSummary属性,参考后面的第二种写法即可。

正确LINQ分组实现

直接从原始报价列表做两层分组即可,不需要用复杂的GroupBy重载,逻辑清晰且易维护:

写法1:月份节点聚合当月所有业务项(匹配三级结构标准逻辑)

var allQuotes = QuoteSummary.ToList();

var treeResult = allQuotes
    // 第一层分组:按报价年份划分根节点
    .GroupBy(quote => quote.CreatedTime.Year)
    .Select(yearGroup => new TreeYear
    {
        NodeYear = yearGroup.Key.ToString(),
        CreatedDateTime = yearGroup.Min(quote => quote.CreatedTime),
        Months = yearGroup
            // 第二层分组:同一年份下按月份划分二级节点
            .GroupBy(quote => quote.CreatedTime.Month)
            .Select(monthGroup => new TreeMonth
            {
                MonthID = monthGroup.Key,
                MonthName = getAbbreviatedName(monthGroup.Key),
                QuoteSummaries = monthGroup.ToList()
            })
            // 按月份数字升序排列,避免10月、11月排在1月前面
            .OrderBy(month => month.MonthID)
            .ToList()
    })
    // 按年份升序排列根节点
    .OrderBy(year => year.NodeYear)
    .ToList();

写法2:单条业务项对应一个月份叶子节点(无需聚合场景)

如果不需要在月份节点下挂载多条业务项,保留你原来的TreeMonth单QuoteSummary定义即可,用以下写法:

var allQuotes = QuoteSummary.ToList();

var treeResult = allQuotes
    .GroupBy(quote => quote.CreatedTime.Year)
    .Select(yearGroup => new TreeYear
    {
        NodeYear = yearGroup.Key.ToString(),
        CreatedDateTime = yearGroup.Min(quote => quote.CreatedTime),
        Months = yearGroup
            .Select(quote => new TreeMonth
            {
                MonthID = quote.CreatedTime.Month,
                MonthName = getAbbreviatedName(quote.CreatedTime.Month),
                QuoteSummary = quote
            })
            .OrderBy(month => month.MonthID)
            .ToList()
    })
    .OrderBy(year => year.NodeYear)
    .ToList();

内容的提问来源于stack exchange,提问作者ScuffedCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:09:19