2008-10-06 42 views
10

Tôi cần truy xuất tập hợp các Widget từ lớp truy cập dữ liệu của tôi, được nhóm theo widget.Manufacturer, để hiển thị trong một tập hợp các ASP.NET ListViews lồng nhau.Hiển thị IGrouping <> với ListView lồng nhau

Vấn đề là (theo như tôi có thể biết) cách tiếp cận ListView lồng nhau yêu cầu tôi định hình dữ liệu trước khi sử dụng và tôi không thể tìm ra cách tiếp cận tốt nhất để thực hiện. Điều tốt nhất tôi đã có thể đưa ra cho đến nay là để đặt một truy vấn LINQ trong lớp truy cập dữ liệu của tôi như vậy:

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

Dĩ nhiên, các kiểu nặc danh không thể được thông qua xung quanh, do đó doesn' t làm việc. Xác định một lớp tùy chỉnh để kèm theo dữ liệu có vẻ như sai đường đi. Có cách nào tôi có thể thực hiện các nhóm trên bên ASP.NET của sự vật? Tôi đang sử dụng ObjectDataSources để truy cập vào DAL.

Cập nhật: OK, tôi không tạo ra một loại vô danh nữa, và thay vào đó Dal tôi đi một IEnumerable<IGrouping<Manufacturer, Widget>> vào trang ASP.NET, nhưng làm thế nào tôi có thể sử dụng trong ListViews của tôi? Tôi cần phải làm cho HTML sau đây (hoặc một cái gì đó khá nhiều như nó)

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

Ban đầu, tôi đã có một ListView trong một ListView như vậy:

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

Lưu ý cách DataSource tài sản của WidgetsListView là chính nó databound. Làm thế nào tôi có thể sao chép chức năng này mà không cần định hình lại dữ liệu?

Điều này trở nên phức tạp, xin lỗi nếu tôi chỉ nên tạo một câu hỏi riêng.

Trả lời

12

Ok, tôi sẽ mâu thuẫn với tuyên bố trước của tôi. Vì eval muốn một số loại tên thuộc tính trong điều khiển lồng nhau, có lẽ chúng ta nên định hình dữ liệu đó.

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

// và sử dụng nó thusly ...

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

/// và thậm chí sau đó ...

<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> 
3

Khi bạn đang sử dụng LINQ to nhóm, bạn có thể nhận được một đối tượng mạnh mẽ gõ mà không định hình rằng:

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

Trong trường hợp của bạn, bạn phải:

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

này sẽ cho phép bạn trả lại kết quả từ phương thức.

+0

Cảm ơn lời khuyên. Tôi đã cập nhật câu hỏi ban đầu của mình với nhiều thông tin hơn. –

5

Tôi vừa trải qua một thời gian khá về vấn đề này. Cuối cùng tìm thấy giải pháp và nó rất đơn giản.


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") trả về giá trị nhóm. Khi truy xuất thông tin con, Container.DataItem thuộc loại IGrouping nhưng bạn chỉ cần đưa nó vào đúng loại.

Hy vọng điều này sẽ giúp người khác.

+0

Trong mẫu mục của bạn, bạn có thể thay thế '<% # ((DataRow) Container.DataItem) [" ChildDataColumn1 "]%>' với '<% # Eval (" ChildDataColumn1 ")%>'. – Armstrongest

+0

Tìm thấy tuyệt vời! Tôi đã tìm một loại giá trị như ".Values" hoặc một cái gì đó. Một trong những khó khăn của nó để đưa vào một truy vấn tìm kiếm là tốt. Cảm ơn! – rtpHarry

Các vấn đề liên quan