簡體   English   中英

來自單個數據庫的中繼器分組項目

[英]Repeater grouping items from single database

我有一個帶有標題的表格(示例):Group、DisplayName、EditableData、description。 在過去的幾天里,我一直在嘗試學習中繼器根據組對信息進行排序,這樣我就可以獲得類似於以下布局的內容。 這是我試圖放在一起的用戶控件。

Group1
------------------
Name1     EditableData    Some Description
Name2     EditableData    Some Description

Group2
------------------
Name3     EditableData    Some Description
Name4     EditableData    Some Description

我在網上查看了以下其他示例: 嵌套轉發器 - ASP.NET 中的分組數據嵌套轉發器

我相信我沒有正確理解中繼器如何工作以處理嵌套或數據源。

<asp:Repeater ID="Repeater1" runat="server">
    <ItemTemplate>
        Group: <%#Eval("Group")%><br />
        <%--Nested Repeater would go here for all the children info for each "Group"--%>
    </ItemTemplate>
</asp:Repeater>

在我的 SQL 中使用 DISTINCT 來只檢索“組”讓我擁有正確的組而不會重復,我想我可以改為在標簽中設置組,然后為每個特定標簽制作中繼器......這在我以后可能會很糟糕將 editableData 更新回數據庫。

我真正想要的是,我想至少有一個演練鏈接,它解釋了中繼器如何與 Eval() 和數據源一起工作。 我的意思是,完成項目第一步所需的所有代碼都是完美的;P 但我也希望能夠更好地理解這些,因為我可能會在不久的將來經常使用它們。

我曾經遇到過同樣的問題,我要按組對數據進行排序,並且必須在分組段中顯示常見項目。

當然,您可以通過多種方式檢索數據,例如,您可以獲取不同的組名稱並將其綁定到轉發器,然后在ItemDataBound事件上您可以執行並獲取其他元素,如下所示:

<asp:Repeater runat="server" ID="rptrGroups" OnItemDataBound="rptrGroups_ItemDataBound">
    <ItemTemplate>
        <asp:Label runat="server" ID="lblGroupName" Text='<%# Eval("GroupName") %>' />

        <asp:GridView runat="server" ID="gv">
        </asp:GridView>
    </ItemTemplate>
</asp:Repeater>

protected void rptrGroups_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item)
    {
        var lblGroupName = (Label)e.Item.FindControl("lblGroupName");
        GridView gv = (GridView)e.Item.FindControl("table");

        var dataTable = FetchDataWithGroupName(lblGroupName.Text); // Method that fetches data with groupname.
        gv.DataSource = dataTable;
        gv.DataBind();
    }
}

這不是推薦的方法,因為它進入數據庫,運行查詢,然后為每個項目獲取數據(如果您從數據庫獲取此數據)。 如果您有數千個組,那么它將進行數千次數據庫調用,這是一件壞事。

第二種解決方案是,您設計一個模型並提供一個自定義模型來完成這項工作。 讓我通過一個示例模型來解釋它:

public class GroupedModel
{
    public string GroupName {get; set;}
    public List<NestedData> TableData {get; set;}
}
public class NestedData
{
    public string Id {get; set;}
    // Your columns here...
}

然后查詢並初始化GroupedModel類的列表,然后將其提供給repeater 讓我用一些虛擬數據來做。

var tableData = new List<NestedData>();
var nestedData1 = new NestedData { Id = "1" };
var nestedData2 = new NestedData { Id = "2" };

tableData.Add(nestedData1);
tableData.Add(nestedData2);

var groupedModel = new GroupedModel 
{
    GroupName = "Group1",
    TableData = tableData
};

var listGroupedModel = new List<GroupedModel>();
listGroupedModel.Add(groupedModel);

rptrGroups.DataSource = listGroupedModel;

然后像這樣修改標記:

<asp:Repeater runat="server" ID="rptrGroups">
    <ItemTemplate>
        <asp:Label runat="server" ID="lblGroupName" Text='<%# Eval("GroupName") %>' />

        <asp:GridView runat="server" ID="gv" DataSource='<%# ((GroupedModel)Container.DataItem).TableData %>'>
        </asp:GridView>
    </ItemTemplate>
</asp:Repeater>

我發現僅使用 gridview 或列表視圖效果很好。 但是,不要嘗試使用分組功能 - 因為它用於在頁面上放置項目,而不是向下放置。

讓這一切變得非常簡單!

好的,我有一個酒店列表,但我想按城市分組。

所以,你構建一個這樣的查詢:

    Dim strSQL As String = 
       "SELECT ID, FirstName, LastName, HotelName, City FROM tblHotels ORDER BY City, HotelName"

    GridView1.DataSource = Myrst(strSQL)
    GridView1.DataBind()

好的,這樣就填充了我們的網格視圖。 我們得到這個:

在此處輸入圖片說明

到目前為止,兩行代碼!

但是,我們想按城市分組。

所以在表單類級別,添加簡單的 var:

Public Class HotelGroupGrid
    Inherits System.Web.UI.Page

    Dim LastCity As String    <----- this one

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If IsPostBack = False Then
            LastCity = ""
            Call LoadGrid()
        End If
    End Sub

好的,現在在數據項綁定事件上,只需添加一個新行。

代碼如下所示:

    If e.Row.RowType = DataControlRowType.DataRow Then

        ' if grouping = 1 then create a new row!
        Dim gvRow As DataRowView = DirectCast(e.Row.DataItem, DataRowView)

        If gvRow("City") <> LastCity Then
            LastCity = gvRow("City")

            ' insert a new row for grouping header
            Dim MyRow As New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
            Dim MyCel As New TableCell()
            'MyCel.Width = Unit.Percentage(100)
            Dim MyTable As Table = e.Row.Parent

            MyCel.ColumnSpan = MyTable.Rows(0).Controls.Count
            Dim MyLable As New Label
            MyLable.Text = "<h2>" & gvRow("City") & "</h2>"
            MyCel.Controls.Add(MyLable)
            MyRow.Cells.Add(MyCel)
            MyTable.Rows.AddAt(MyTable.Rows.Count - 1, MyRow)

        End If

    End If

現在,上面是一小塊需要咀嚼的“位”——但仍然沒有很多代碼。

所以,現在當我們在上面運行時,我們得到:

在此處輸入圖片說明

我們的網格視圖標記如下所示:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
  <Columns>
    <asp:BoundField DataField="City" HeaderText="City" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
    <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
    <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
     <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
     <asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
   </Columns>
</asp:GridView>

所以,還不算太糟。

如果您決定使用列表視圖? 然后代碼變得少了很多,但是 listview 的標記非常少。

我們所做的就是創建一行作為我們的標題,然后根據新分組的開始顯示或隱藏該行。

那么,如果決定使用列表視圖呢? 然后我們得到這個:

(我假設您使用數據綁定向導-您不可能手動輸入標記-對嗎?-在這里拯救世界貧困)

因此,對於列表視圖(我認為列表視圖更好,因為該標題行的布局選項對任何類型的標記和您夢寐以求的額外控件都是開放的。

所以,標記(生成 - 然后切掉脂肪)是這樣的:

<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID">
    <EmptyDataTemplate>
        <table runat="server" style="">
           <tr><td>No data was returned.</td></tr>
        </table>
    </EmptyDataTemplate>
    <ItemTemplate>

       <tr id="GroupHeading" runat="server" style="display:none">
           <td colspan="4">
           <h2><asp:Label ID="City" runat="server" Text='<%# Eval("City") %>' /></h2>
           </td>
       </tr>

       <tr>
          <td><asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' /></td>
          <td><asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstName") %>' /></td>
          <td><asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>' /></td>
          <td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
       </tr>
   </ItemTemplate>

 <LayoutTemplate>
     <table id="itemPlaceholderContainer" runat="server" border="0" style="">
     <tr runat="server">
        <th runat="server">ID</th>
        <th runat="server">FirstName</th>
        <th runat="server">LastName</th>
        <th runat="server">HotelName</th>
    </tr>
    <tr id="itemPlaceholder" runat="server">
    </tr>

    </table>
 </LayoutTemplate>
 </asp:ListView>

現在毫無疑問,列表視圖會吐出更多標記 - 但我們現在有一個完整的標題行。 所以我們得到這個:

在此處輸入圖片說明

但是,現在我們的代碼將簡單地隱藏或顯示我們在市場上的“額外”行。

現在很簡單:

If e.Item.GetType = GetType(ListViewDataItem) Then

  Dim MyRow As HtmlTableRow = e.Item.FindControl("GroupHeading")
  Dim lblCity As Label = MyRow.FindControl("City")
  If lblCity.Text <> LastCity Then
     LastCity = lblCity.Text
     ' Hide/show  group heading
     MyRow.Style("display") = "normal"
  Else
     MyRow.Style("display") = "none"
  End If

End If

因此,大多數情況下的技巧是簡單地布置該額外的行項目,然后在項目數據綁定事件上,您只需隱藏或顯示該標題部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM