Как получить доступ к группе запроса linq group-by из вложенного элемента управления повторителя? - PullRequest
2 голосов
/ 27 марта 2010

Я использую группу linq по запросу (с двумя параметрами группировки) и хотел бы использовать полученные данные во вложенном повторителе.

var dateGroups = from row in data.AsEnumerable()
    group row by new { StartDate = row["StartDate"], EndDate = row["EndDate"] };

«data» - это DataTable из набора данных, заполненного SqlDataAdapter. «dateGroups» используется в родительском повторителе, и я могу получить доступ к групповым ключам, используя Eval («key.StartDate») и Eval («key.EndDate»).

Поскольку dateGroups на самом деле содержит все строки данных, аккуратно сгруппированные по дате начала / окончания, я хотел бы получить доступ к этим строкам для отображения данных в дочернем повторителе.

На что бы я установил источник данных дочернего ретранслятора? Я попробовал каждое выражение в разметке, о котором только мог подумать; Я думаю, что проблема в том, что я пытаюсь получить доступ к анонимному члену (и я не знаю как.) Если это не окажется очевидным, каким будет выражение для доступа к элементам в каждой итерации детский ретранслятор?

Есть ли выражение, которое позволило бы мне установить источник данных в разметке, или оно должно быть в коде позади некоторого события в родительском повторителе?

Ответы [ 5 ]

3 голосов
/ 29 марта 2010

Я закончил поиском еще немного и нашел это . Используя это, я создал словарь, ключом которого является комбинация StartDate / EndDate, а значением является список DataRows:

var dateGroups = (from row in data.AsEnumerable()
    group row by new
    {
        StartDate = row["StartDate"],
        EndDate = row["EndDate"]
    } into g select g)
    .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Родительский Repeater программно связан, и теперь у меня есть внутренний GridView, связанный со списком DataRows:

<asp:Repeater ID="CourseScheduleRepeater" runat="server">
    <ItemTemplate>
        <h4><%# Eval("key.StartDate", "{0:MMM. dd, yyyy}") %> - <%# Eval("key.EndDate", "{0:MMM. dd, yyyy}") %></h4>

        <asp:GridView ID="GridView1" runat="server"
                DataSource='<%# Eval("value") %>'>
            <Columns>
                <asp:TemplateField HeaderText="Section">
                    <ItemTemplate>
                        <%# DataBinder.Eval(Container.DataItem, "[SectionCode]") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Location">
                    <ItemTemplate>
                        <%# DataBinder.Eval(Container.DataItem, "[LocationName]") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Schedule">
                    <ItemTemplate>
                        <%# DataBinder.Eval(Container.DataItem, "[Schedule]") %>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>        
        </asp:GridView>

    </ItemTemplate>
</asp:Repeater>

Моя единственная жалоба состоит в том, что я должен использовать поля шаблона и что в GridView отображаются два дополнительных столбца - «RowError» и «HasErrors». Кто-нибудь знает, почему появятся эти столбцы?

2 голосов
/ 18 мая 2011

Я нашел эту тему очень полезной. Вот мое проверенное на практике решение с использованием внешнего повторителя и внутреннего повторителя.

Как использовать LINQ Grouping для заполнения вложенных элементов управления, связанных с данными

<form id="form1" runat="server">
<div>
    <table>
        <asp:Repeater ID="Repeater1" runat="server">
            <ItemTemplate>
                <tr>
                    <td>
                        <%# Eval("key.FavoriteColor")%>
                    </td>
                    <td>
                        <%# Eval("key.FavoriteFood")%>  
                    </td>
                    <td colspan="2"></td>
                </tr>
                <asp:Repeater ID="Repeater2" DataSource='<%# Eval("value") %>' runat="server">
                    <ItemTemplate>                      
                        <tr>
                            <td>
                                <%# Eval("ID") %>
                            </td>
                            <td>
                                <%# Eval("Name") %>
                            </td>
                            <td>
                                <%# Eval("FavoriteColor") %>
                            </td>
                            <td>
                                <%# Eval("FavoriteFood") %>
                            </td>
                        </tr>                       
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </table>
</div>
</form>




public partial class WebForm1 : Page
{
    private List<Child> CreateChildren()
    {
        List<Child> children = new List<Child>();

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Green,
            FavoriteFood = Child.Food.IceCream,
            Name = "Sam",
            ID = 1,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Blue,
            FavoriteFood = Child.Food.Hamburgers,
            Name = "Tom",
            ID = 2,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Blue,
            FavoriteFood = Child.Food.Pizza,
            Name = "Fred",
            ID = 3,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Orange,
            FavoriteFood = Child.Food.Tacos,
            Name = "Mark",
            ID = 4,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Green,
            FavoriteFood = Child.Food.Pizza,
            Name = "Harry",
            ID = 5,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Pink,
            FavoriteFood = Child.Food.Pizza,
            Name = "Natalie",
            ID = 6,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Green,
            FavoriteFood = Child.Food.Pizza,
            Name = "Amy",
            ID = 7,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Yellow,
            FavoriteFood = Child.Food.Hamburgers,
            Name = "Katie",
            ID = 8,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Red,
            FavoriteFood = Child.Food.IceCream,
            Name = "Betty",
            ID = 9,
        });

        children.Add(new Child
        {
            FavoriteColor = Child.Color.Pink,
            FavoriteFood = Child.Food.Pizza,
            Name = "Erica",
            ID = 10,
        });

        return children;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        List<Child> children = CreateChildren();

        // Use LINQ to create the groupings.
        var query = (from c in children
                     group c by new
                     {
                        c.FavoriteColor,
                        c.FavoriteFood,
                     }
                     into g select g).ToDictionary(g => g.Key, g => g.ToList());

        // Here is the same code using LINQ chain methods.
        // var query = children.GroupBy(c => new { c.FavoriteColor, c.FavoriteFood }).Select(g => g).ToDictionary(g => g.Key, g => g.ToList());

        Repeater1.DataSource = query;
        Repeater1.DataBind();
    }
}

public class Child
{
    public enum Color
    {
        Black,
        Blue,
        Brown,
        Green,
        Orange,
        Pink,
        Purple,
        Red,
        Yellow,
        White,
    }

    public enum Food
    {
        Chicken,
        Hamburgers,
        IceCream,
        Pizza,
        Tacos,
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public Color FavoriteColor { get; set; }
    public Food FavoriteFood { get; set; }
}
1 голос
/ 27 марта 2010

Используйте известный тип класса, а не анонимный класс.В противном случае вам придется использовать рефлексию для проверки анонимного типа, который выглядит ужасно.

0 голосов
/ 04 мая 2015

Следующее работает хорошо, чтобы связать GroupBy с вложенным Repeater. Ключ должен позвонить CopyToDataTable. Вот некоторые заметки о других ответах:

  1. Мы можем использовать анонимные типы вместо известных типов классов.
  2. Мы можем использовать результат GroupBy без вызова ToDictionary.

Код позади

Используйте перегрузку GroupBy, которая позволяет нам указать тип ключа и группы . В этом случае ключ является анонимным классом со свойствами FirstName и LastName, а результатом является DataTable, который мы копируем из IEnumerable<DataRow>. Мы должны сделать эту копию, потому что Repeaters не привязывается к IEnumerable<DataRow>.

var grouped = dataRows
    .GroupBy(row => new
    {
        FirstName = row["FirstName"],
        LastName = row["LastName "]
    },
    (key, group) => new
    {
        Key = key,
        Group = group.CopyToDataTable()
    });

rptOuter.DataSource = grouped;
rptOuter.DataBind();

Разметка

Мы Eval во внешнем повторителе до Key и во внутреннем повторителе до Group. PhoneNumber - это просто одно из имен столбцов из оригинального DataTable.

<asp:Repeater ID="rptOuter" runat="server">
    <ItemTemplate>
        <p><%# Eval("Key.FirstName") %></p>
        <p><%# Eval("Key.LastName") %></p>
        <asp:Repeater ID="rptInner" runat="server"
            DataSource='<%# Eval("Group") %>' >
            <ItemTemplate>
                <p><%# Eval("PhoneNumber") %></p>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>
0 голосов
/ 27 марта 2010

Мне кажется, проблема в том, что я пытаюсь получить доступ к анонимному участнику (и я не знаю, как).

Можете ли вы заменить анонимный тип своим собственным классом?

...