我通过查询使用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,还是必须在父转发器中的某个事件的代码隐藏中?
答案 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
。以下是其他答案的一些注释:
GroupBy
的情况下使用ToDictionary
的结果。使用GroupBy
overload that lets us specify the type of both the key and the group。在这种情况下,密钥是具有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>