Группировать по элементам в списке объектов (Sitecore Item) и связывать с помощью Repeater

Извините за длинное описание, но я хочу, чтобы пользователи поняли мою проблему. У меня есть список, который содержит DepartmentItem а также EmployeeItem,

 var empSubRelList = new List<EmpDeptRel>();

internal class EmpDeptRel
{
    public Item DepartmentItem { get; set; }
    public Item EmployeeItem { get; set; }
}

Вот код, который объясняет, как я добавляю элементы в список:

Item userProfile = Sitecore.Context.Database.GetItem("/sitecore/content/Intranet/User Profiles");

foreach (var subRelItem in userProfile.Axes.GetDescendants().Where(p => p.TemplateID.ToString() == Settings.GetSetting("SubRelTemplateID")
                                                  && p["Subsidiary"] == SubssdiaryItem.ID.ToString()).OrderBy(p => p["Department"]))
{
    empSubRelList.Add(new EmpDeptRel
    {
         DepartmentItem = GetItemById(subRelItem["Department"]),
         EmployeeItem = subRelItem.Parent.Parent
    });       
}

Я связываю это с повторителем:

repEmployees.DataSource = empSubRelList;
repEmployees.DataBind();

<asp:Repeater runat="server" ID="repEmployees">
   <ItemTemplate>
       <li>
            <%# Name(Eval("DepartmentItem") as Item)%>
            <%# Name(Eval("EmployeeItem") as Item)%>          
       </li>
   </ItemTemplate>

Вот код для метода "Name()"который находится внутри ретранслятора

protected string Name(Item item)
{
    if (item != null)
    {
        return item.Name;
    }
    return string.Empty;
}

Вывод:

IT TestUser1
Administration TestUser2
Administration TestUSer3
Administration TestUser4
Administration TestUser5
Finance TestUSer6

Можно ли как-то сгруппировать список "empSubRelList" с отделом, чтобы я мог получить следующий вывод:

IT TestUser1
Administration TestUser2 TestUser3 TestUser4 TestUser5
Finance TestUser6

2 ответа

Решение

Как писал Marco, вы можете выполнить группировку перед настройкой источника данных вашего ретранслятора:

IEnumerable<KeyValuePair<string, string>> dataSource = empSubRelList
    .GroupBy(listItem => Name(listItem.DepartmentItem))
    .Select(grouping => new KeyValuePair<string, string>(
        groupping.Key,
        string.Join(", ", grouping.Select(emp => Name(emp.EmployeeItem)))
    ));

repEmployees.DataSource = dataSource;

а затем в вашем HTML-коде:

<asp:Repeater runat="server" ID="repEmployees">
   <ItemTemplate>
       <li>
            <%# ((KeyValuePair<string, string>)Container.DataItem).Key %>
            <%# ((KeyValuePair<string, string>)Container.DataItem).Value %>
       </li>
   </ItemTemplate>
</asp:Repeater>

Это должно сделать это:

var list = new List<CustomItem>(){
    new CustomItem() { Department= "IT", UserName = "TestUser1"},
    new CustomItem() { Department = "Administration", UserName = "TestUser2"},
    new CustomItem() { Department = "Administration", UserName = "TestUser3"},
    new CustomItem() { Department = "Administration", UserName = "TestUser4"},
    new CustomItem() { Department = "Administration", UserName = "TestUser5"},
    new CustomItem() { Department = "Finance", UserName = "TestUser6"},
};

list.GroupBy (l => l.Department)
    .Select (l => new {
        Department = l.Key,
        Users = l.Select (x => x.UserName).Aggregate ((c,n) => c + ", " + n )
    });

Ouput:

введите описание изображения здесь

Ключевым моментом является то, что вы сначала группируете по пункту вашего департамента. После этого вы выбираете свойство username и агрегируете по ним. Какие Aggregate() делает, принимает текущий (c) и следующий (n), а затем делает то, что вы указываете с ними. В этом случае он объединяет их через запятую и пробел ((c,n) => c + ", " + n), Затем он переходит к следующему пункту

Демонстрационный код

Другие вопросы по тегам