麻烦显示树结构

时间:2012-12-03 19:37:37

标签: c# .net linq

我想显示这样的树结构:

  • Mission1

    • 活性1
      • PROJECT1
    • 活性2
  • Mission2

    • Activity3
      • Project2的

但相反,我得到一个列表,为每个不同的活动或项目重复父元素:

  • Mission1

    • 活性1
      • PROJECT1
  • Mission1

    • 活性2

我想将活动和项目分组到一个父元素('Mission')元素下。

这是我的LINQ查询:

var q = from mission in _context.tMissions
                join activity in _context.tActivities on mission.id equals activity.missionId
                join project in _context.tDefaultEventTypes on activity.id equals project.activityId
                where !project.isRemoved && project.defaultCategoryId == 4
                orderby mission.name
                select CreateFrom(project);

        return q.ToList();

然后我将它绑定到列表并在页面上显示它。这是我的aspx:

    <asp:DataList ID="dlTierTypes" runat="server">
      <ItemTemplate>
        <li><%# Eval("Activity.Mission.Name") %></li>
          <ul>
            <li><%# Eval("Activity.Name") %></li>
            <ul>
              <li><%# Eval("Name") %></li>
            </ul>
      </ItemTemplate>
    </asp:DataList>

背后的代码只是绑定它:

    public void SetTierTree(IEnumerable<DefaultEventType> tierList)
    {
      dlTierTypes.DataSource = tierList;
      dlTierTypes.DataBind();
    }

不确定如何解决这个问题。

编辑 - 这是我在存储库中的新功能。

    public ICollection<DefaultEventType> GetTierTree()
    {
        var q = from mission in _context.tMissions
                join activity in _context.tActivities on mission.id equals activity.missionId
                join project in _context.tDefaultEventTypes on activity.id equals project.activityId
                where !project.isRemoved && project.defaultCategoryId == 4
                orderby mission.name
                select new DefaultEventType(project.tierLevel.TryParseEnum<GanttType>(GanttType.Unknown), DefaultCategoryRepository.CreateFrom(project.tDefaultCategory))
                {
                    //t = new DefaultEventType(project.tierLevel.TryParseEnum<GanttType>(GanttType.Unknown), DefaultCategoryRepository.CreateFrom(project.tDefaultCategory)),
                    AllowNumericSuffix = project.allowNumericSuffix,
                    AttachMilestoneMoniker = project.attachMilestoneMoniker,
                    Description = project.description,
                    Id = project.id,
                    IsReadOnly = project.isReadOnly,
                    IsSticky = project.isSticky,
                    Name = project.name,
                    Sid = project.sid,
                    Style = project.style.TryParseEnum<GanttElementStyle>(GanttElementStyle.Unknown),
                    TimeStamp = project.createdDT,
                    UpdatedTimeStamp = project.updatedDT,
                    Activity = new Activity { Id = activity.id, Name = activity.name, Mission = new Mission { Id = mission.id, Name = mission.name } }
                };

        var q2 = q.GroupBy(row => row.Activity.Mission.Id)
            .Select(group => group.GroupBy(row => row.Activity.Id));

        return q2.Cast<DefaultEventType>().ToList();
    }

但是在显示页面时收到此错误: '无法从类型'System.Collections.Generic.List 1[System.Linq.IGrouping 2 [System.Int32,DefaultEventType]]'转换为'DefaultEventType'。'

1 个答案:

答案 0 :(得分:1)

首先,您需要调整查询。在此示例中,使用GroupBy可以极大地帮助。

完全按照你所拥有的,然后按任务分组结果。对于每个组,按活动对任务进行分组(这需要是嵌套的分组,而不是按顺序分组)。

var q2 = q.GroupBy(row => row.MissionID)
     .Select(group => group.GroupBy(row => row.ActivityID));

我不确定您的提供商是否可以在数据库端进行映射;如果没有在需要的时候在该查询中抛出AsEnumerable

接下来,您需要更改呈现数据的方式以反映此更改。

而不是单个DataList,您需要3个嵌套数据列表。您将整个查询绑定到显示任务的外层,然后订阅数据绑定事件以将内部组设置为内部数据列表的该实例的数据源。然后,在该内部数据列表中,显示活动并将最里面的组级别绑定到最里面的DataList,它可以正常绑定项目名称。

此外,您可以考虑使用TreeView呈现数据结构而不是DataList,因为TreeView用于呈现树。我不确定你是否因某些原因需要拒绝它,或者只是不考虑它,但它可能更容易使用。如果您确实按照我的建议去了那条路,那么查询仍然会被修改,你只需要任何嵌套的ASP控件。