如何从嵌套的转发器控件中访问linq group-by查询组?

时间:2010-03-26 21:09:40

标签: asp.net linq repeater anonymous-types

我通过查询使用linq组(带有两个分组参数),并希望在嵌套转发器中使用结果数据。

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

“data”是来自SqlDataAdapter填充的DataSet的DataTable。 “dateGroups”用于父转发器,我可以使用Eval(“key.StartDate”)和Eval(“key.EndDate”)访问组密钥。

由于dateGroups实际上包含按开始/结束日期整齐分组的所有数据行,因此我想访问这些行以在子转发器中显示数据。

我将如何设置子转发器的DataSource?我已经尝试了我能想到的标记中的每个表达;我认为问题是我正在尝试访问一个匿名成员(我不知道如何。)如果它不明显,那么在每次迭代中访问元素的表达式是什么?儿童中继器?

是否有一个表达式可以让我在标记中设置DataSource,还是必须在父转发器中的某个事件的代码隐藏中?

5 个答案:

答案 0 :(得分:3)

我最后再搜索一下,发现this。使用它我创建了一个Dictionary,其键是StartDate / EndDate组合,value是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”。有人知道为什么这些专栏会出现吗?

答案 1 :(得分:2)

我发现这个帖子非常有帮助。这是我使用外部中继器和内部中继器的概念验证解决方案。

如何使用LINQ分组填充嵌套数据绑定控件

<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; }
}

答案 2 :(得分:1)

使用知道类类型而不是匿名类。否则你将不得不使用反射来检查变得丑陋的匿名类型。

答案 3 :(得分:0)

  

我认为问题在于我正在尝试访问匿名成员(我不知道如何。)

您可以用自己的类替换匿名类型吗?

答案 4 :(得分:0)

以下可以很好地将GroupBy绑定到嵌套的Repeater。关键是致电CopyToDataTable。以下是其他答案的一些注释:

  1. 我们可以使用匿名类型而不是已知的类类型。
  2. 我们可以在不调用GroupBy的情况下使用ToDictionary的结果。
  3. 代码背后

    使用GroupBy overload that lets us specify the type of both the key and the group。在这种情况下,密钥是具有FirstNameLastName属性的匿名类,结果是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和内部转发器GroupPhoneNumber只是原始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>
    
相关问题