2010-03-26 58 views
2

我通過查詢(使用兩個分組參數)使用linq組,並且希望在嵌套中繼器中使用結果數據。如何從嵌套中繼器控件訪問linq group-by查詢的組?

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

「data」是來自SqlDataAdapter填充數據集的DataTable。 「dateGroups」用於父轉發器,我可以使用Eval(「key.StartDate」)和Eval(「key.EndDate」)來訪問組密鑰。

由於dateGroups實際上包含由開始/結束日期整齊分組的所有數據行,我想要訪問這些行以在兒童中繼器中顯示數據。

我將設置子重複器的DataSource?我嘗試了所有我能想到的標記表達方式;我認爲問題是我試圖訪問一個匿名成員(我不知道如何)。如果它不是很明顯,那麼在每次迭代中訪問元素的表達式是什麼?兒童中繼器?

是否有一個表達式可以讓我在標記中設置DataSource,還是必須在父代中繼器中的某個事件的代碼隱藏中?

回答

1

使用知道的類類型而不是匿名類。否則,你將不得不使用反射來檢查變得醜陋的匿名類型。

+0

搞清楚如何與ToDictionary表達訪問匿名成員後,我意識到我仍然沒有那種獲得我所需要的內gridview的其他成員。 我爲這個鍵創建了兩個成員類,然後在每個轉發器迭代過濾了內部gridview的原始數據表。 – Matt

+0

使用匿名類很好。我們不需要使用反射。 –

0

我認爲問題是,我試圖訪問一個匿名成員(我不知道怎麼辦。)

可以更換匿名類型與你自己的類?

3

我最終搜索了一下,發現了this。使用我創建了一個字典,其關鍵是起始日期/結束日期組合,並且值是數據行的列表:

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()); 

父中繼器編程約束,現在我具有內的GridView綁定到數據行的列表:

<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」。任何人都知道爲什麼這些專欄會出現?

+0

使用'ToDictionary'是一個很好的方法,儘管你不需要使用它。相反,您可以使用「GroupBy」的重載來修改組結果。 –

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

下面的作品起到了很好的GroupBy綁定到嵌套Repeater。關鍵是撥打CopyToDataTable。下面是關於其他答案的一些注意事項:

  1. 我們可以使用匿名類型而不是已知的類類型。
  2. 我們可以使用GroupBy的結果,而無需致電ToDictionary

代碼隱藏

使用GroupBy overload that lets us specify the type of both the key and the group。在這種情況下,密鑰是具有FirstNameLastName屬性的匿名類,結果是我們從IEnumerable<DataRow>複製的DataTable。我們要做這個副本,因爲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(); 

標記

我們在外部中繼器Key和內中繼器GroupEvalPhoneNumber只是原始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>