Отображение IGrouping <> с вложенными ListView

Мне нужно получить набор виджетов с моего уровня доступа к данным, сгруппированных по widget.Manufacturer, для отображения в наборе вложенных ASP.NET ListViews.

Проблема в том, что (насколько я могу судить) вложенный подход ListView требует, чтобы я формировал данные перед их использованием, и я не могу придумать лучший подход. Лучшее, что я смог придумать до сих пор, - это поместить запрос LINQ на мой уровень доступа к данным следующим образом:

var result = from widget in GetAllWidgets(int widgetTypeID)
             group widget by widget.Manufacturer into groupedWidgets
             let widgets = from widgetGroup in groupedWidgets
                           select widgetGroup
             select new { Manufacturer = groupedWidgets.Key, Widgets = widgets };

Конечно, анонимные типы нельзя передавать, так что это не работает. Кажется, что определение пользовательского класса для включения данных - неправильный путь. Есть ли способ выполнить группировку на стороне ASP.NET? Я использую ObjectDataSources для доступа к DAL.

Обновлено: Хорошо, я больше не создаю анонимный тип, и вместо этого мой DAL передает IEnumerable<IGrouping<Manufacturer, Widget>> на страницу ASP.NET, но как я могу использовать это в своих ListViews? Мне нужно отобразить следующий HTML-код (или что-то в этом роде)

<ul>
  <li>Foo Corp.
    <ol>
      <li>Baz</li>
      <li>Quux</li>
    </ol>
  </li>
  <li>Bar Corp.
    <ol>
      <li>Thinger</li>
      <li>Whatsit</li>
    </ol>
  </li>
</ul>

Изначально у меня был ListView внутри ListView вот так:

<asp:ListView ID = "ManufacturerListView">
    <LayoutTemplate>
        <ul>
            <asp:Placeholder ID = "itemPlaceholder" runat = "server" />
        </ul>
    </LayoutTemplate>
    <ItemTemplate>
        <li><asp:Label Text='<%# Eval("Manufacturer.Name") %>' />
        <li>
        <asp:ListView ID = "WidgetsListView" runat = "server" DataSource='<%# Eval("Widgets") %>'>
            <LayoutTemplate>
                <ol>
                    <asp:PlaceHolder runat = "server" ID = "itemPlaceholder" />
            </ol>
           </LayoutTemplate>
           <ItemTemplate>
               <li><asp:Label Text='<%# Eval("Name") %>'></li>
           </ItemTemplate>
        </asp:ListView>
        </li>
    </ItemTemplate>
</asp:ListView>

Обратите внимание, что свойство DataSource WidgetsListView само является привязкой к данным. Как я могу продублировать эту функцию без изменения данных?

Это становится довольно сложным, извините, если бы я просто задал отдельный вопрос.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
0
7 074
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Когда вы используете Linq для группировки, вы можете получить строго типизированный объект без этой формы:

List<int> myInts = new List<int>() { 1, 2, 3, 4, 5 };
IEnumerable<IGrouping<int, int>> myGroups = myInts.GroupBy(i => i % 2);
foreach (IGrouping<int, int> g in myGroups)
{
  Console.WriteLine(g.Key);
  foreach (int i in g)
  {
    Console.WriteLine("  {0}", i);
  }
}
Console.ReadLine();

В вашем случае у вас будет:

  IEnumerable<IGrouping<Manufacturer, Widget>> result =
    GetAllWidgets(widgetTypeId).GroupBy(w => w.Manufacturer);

Это позволит вам вернуть результат метода.

Спасибо за совет. Я обновил свой исходный вопрос, добавив дополнительную информацию.

Brant Bobby 07.10.2008 03:17
Ответ принят как подходящий

Хорошо, я собираюсь опровергнуть свое предыдущее заявление. Поскольку eval хочет иметь какое-то имя свойства во вложенном элементе управления, нам, вероятно, следует сформировать эти данные.

public class CustomGroup<TKey, TValue>
{
  public TKey Key {get;set;}
  public IEnumerable<TValue> Values {get;set;}
}

// и использовать его таким образом ...

IEnumerable<CustomGroup<Manufacturer, Widget>> result =
  GetAllWidgets(widgetTypeId)
  .GroupBy(w => w.Manufacturer)
  .Select(g => new CustomGroup<Manufacturer, Widget>(){Key = g.Key, Values = g};

/// и даже позже ...

<asp:ListView ID = "ManufacturerListView">
<LayoutTemplate>
    <ul>
        <asp:Placeholder ID = "itemPlaceholder" runat = "server" />
    </ul>
</LayoutTemplate>
<ItemTemplate>
    <li><asp:Label Text='<%# Eval("Key.Name") %>' />
    <li>
    <asp:ListView ID = "WidgetsListView" runat = "server" DataSource='<%# Eval("Values") %>'>
        <LayoutTemplate>
            <ol>
                <asp:PlaceHolder runat = "server" ID = "itemPlaceholder" />
            </ol>
       </LayoutTemplate>
       <ItemTemplate>
           <li><asp:Label Text='<%# Eval("Name") %>'></li>
       </ItemTemplate>
    </asp:ListView>
    </li>
</ItemTemplate>
</asp:ListView>

Я только что потратил на это довольно много времени. В конце концов нашли решение, и это так просто.


var enumerableData = myData.Tables[0].AsEnumerable();
var groupedData = enumerableData.GroupBy(x => x["GroupingColumn"]);

myParentRepeater.DataSource = groupedData;
myParentRepeater.DataBind();

<asp:Repeater ID = "myParentRepeater" runat = "server">
  <ItemTemplate>
    <h3><%#Eval("Key") %></h3>
    <asp:Repeater ID = "myChildRepeater" runat = "server" DataSource='<%# Container.DataItem %>'>
      <ItemTemplate>
        <%#((DataRow)Container.DataItem)["ChildDataColumn1"] %>
        <%#((DataRow)Container.DataItem)["ChildDataColumn2"] %>
      </ItemTemplate>
      <SeparatorTemplate>
        <br />
      </SeparatorTemplate>
    </asp:Repeater>
  </ItemTemplate>
</asp:Repeater>

Eval («Key») возвращает сгруппированное значение. При получении дочерней информации Container.DataItem имеет тип IGrouping, но вы просто приводите его к правильному типу.

Надеюсь, это поможет кому-то другому.

В шаблоне элемента вы можете заменить <%#((DataRow)Container.DataItem)["ChildDataColumn1"] %> на <%# Eval("ChildDataColumn1") %>.

Armstrongest 10.05.2010 21:50

Отличная находка! Я искал какую-то ценность вроде ".Values" или что-то в этом роде. Его тоже сложно ввести в поисковый запрос. Спасибо!

rtpHarry 26.04.2011 20:03

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