在gridview模板字段中需要可变数量的下拉列表

时间:2012-06-11 20:06:41

标签: asp.net gridview

我定义了以下gridview,它完美填充:

    <asp:GridView runat="server" ID="chargeDetail" AutoGenerateColumns="false" DataKeyNames="LineItemNumber,DetailId,IsParking" CellSpacing="0" CellPadding="6"
     HorizontalAlign="Center" EnableViewState="true" ShowFooter="true">
        <Columns>
            <asp:BoundField DataField="StudentID" HeaderText="Student ID" ReadOnly="True" ItemStyle-HorizontalAlign="Center" />
            <asp:BoundField DataField="StudentName" HeaderText="Name" ReadOnly="true" />
            <asp:BoundField DataField="CampusName" HeaderText="Campus" ReadOnly="true" />
            <asp:TemplateField HeaderText="Description" ItemStyle-HorizontalAlign="Center">
                <ItemTemplate>
                    <asp:Label runat="server" ID="LineItemDetailLabel" Text='<%# IIf(Eval("Mandatory") = "1", Eval("LineItemDetail") + " *", Eval("LineItemDetail")) %>' />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Item Cost" ItemStyle-HorizontalAlign="Center">
                <ItemTemplate>
                    $<asp:Label runat="server" ID="LineItemCostLabel" Text='<%# Eval("LineItemCost") %>' />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Options" ItemStyle-HorizontalAlign="Center">
                <ItemTemplate>
                    <asp:Label runat="server" ID="lblOptionsAvailable" 
                     Text='<%# IIf(Eval("AttributesAvailable") = "1", "Options will be available to select on the next screen.", "No options available.") %>' />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Pay Now" ItemStyle-HorizontalAlign="Center" FooterText="Total:">
                <ItemTemplate>
                    <asp:Checkbox runat="server" ID="cbLineItemSelected" Checked='<%# IIf(Eval("Selected") = "1", "True", "False") %>'
                     Enabled='<%# IIf(Eval("Mandatory") = "1", "False", "True") %>' AutoPostBack="True" OnCheckedChanged="cbLineItemSelected_CheckedChanged" />
                </ItemTemplate>
                <FooterStyle Font-Bold="True" HorizontalAlign="Right" />
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Total">
                <ItemTemplate>
                    $<asp:Label runat="server" ID="lblLineTotalCost" Text='<%# IIf(Eval("Selected") = "1", Eval("LineItemCost"), "0.00") %>' />
                </ItemTemplate>
                <FooterTemplate>
                    $<asp:Label runat="server" ID="lblTotal" />
                </FooterTemplate>
                <FooterStyle Font-Bold="True" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

在HeaderText =“Options”的TemplateField中,我需要能够创建可变数量的下拉列表。对于学校可能收取的每项费用,他们可以拥有任何数量的相关属性。例如,TShirt费用可能需要收集尺寸和颜色,每个属性可能有多个选项。

现在,您可以看到我有一个正确填充的标签,但我需要能够创建两个下拉列表,在本例中为Size和Color,因此父级可以在检查时指定它们在他们的收费中包含此费用的方框。您会注意到,在“立即付款”列中,该复选框有一个OnCheckedChanged事件,该事件当前更新了页脚行中的总列数和总计。

理想情况下,我希望在检查下拉时填充下拉列表,以便父级可以进行选择。我还需要知道如何处理这些下拉列表中的帖子,这样我才能正确记录选择。

从我能找到的,我猜我需要创建一个嵌套的gridview,我可以放下下拉列表,但我找不到任何例子来指出我如何使这项工作正确的方向。我可以轻松地从后面的代码填充下拉列表,如果指向正确的方向,则在父项输入时访问数据。只需要一点方向或更简单的方法。

提前致谢!

1 个答案:

答案 0 :(得分:0)

好的,我想出了一个似乎有用的解决方案。在gridview定义中,我使用下面的下拉列表嵌套了另一个gridview,如下所示:

        <asp:TemplateField HeaderText="Options" ItemStyle-HorizontalAlign="Center">
            <ItemTemplate>
                <asp:GridView runat="server" ID="gvOptions" AutoGenerateColumns="False" DataKeyNames="AttributeId" HorizontalAlign="center" EnableViewState="true"
                    GridLines="None" EmptyDataText="No available options." ShowHeader="False">
                    <Columns>
                        <asp:BoundField DataField="Description" ReadOnly="true" ItemStyle-HorizontalAlign="Center" />
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:DropDownList runat="server" ID="ddlOptionSelection" DataTextField="Description" DataValueField="OptionId"
                                    EnableViewState="true" AutoPostBack="true" OnSelectedIndexChanged="ddlOptionSelection_SelectedIndexChanged">
                                </asp:DropDownList>
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>

挑战在于弄清楚如何将所有内容联系在一起,因为嵌套网格视图中的数据依赖于父网格视图中的数据键。父级的RowDataBound事件查找子gridview并按如下方式填充下拉列表(gvOptions是子级,chargeDetail是父级):

Protected Sub chargeDetail_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles chargeDetail.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then
        Dim gv As GridView = DirectCast(e.Row.FindControl("gvOptions"), GridView)
        Dim cb As CheckBox = DirectCast(e.Row.FindControl("cbLineItemSelected"), CheckBox)
        Dim lineItem As String = chargeDetail.DataKeys(e.Row.RowIndex).Values("LineItemNumber")
        gv.DataSource = GetOptions(chargeDetail.DataKeys(e.Row.RowIndex).Values("DetailId"))
        gv.DataBind()

        Dim gridLineCount As Integer = gv.Rows.Count()
        Dim gridWorkingRow As Integer

        For gridWorkingRow = 0 To gridLineCount - 1
            Dim ddl As DropDownList = gv.Rows(gridWorkingRow).FindControl("ddlOptionSelection")
            Dim AttribId As Integer = gv.DataKeys(gridWorkingRow).Values("AttributeId")
            ddl.DataSource = PopulateOptions(AttribId)
            ddl.DataBind()
            ddl.SelectedValue = GetSelectedValue(AttribId, lineItem)

            If cb.Checked Then
                ddl.Enabled = True
            Else
                ddl.Enabled = False
            End If
        Next gridWorkingRow
    End If
End Sub

当其中一个下拉列表发生变化时,会触发以下内容。基于数据存储在数据库中的方式,我发现更容易重新发送所有选项,因为属性:选项对被连接起来存储在一个字段中:

Protected Sub ddlOptionSelection_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
    Dim ddlSender As DropDownList = DirectCast(sender, DropDownList)
    Dim row As GridViewRow = DirectCast(ddlSender.NamingContainer, GridViewRow)
    Dim gvOption As GridView = DirectCast(row.NamingContainer, GridView)
    Dim chargeDetailRow As GridViewRow = DirectCast(gvOption.Parent.Parent, GridViewRow)
    Dim LineItemNumber As Integer = CInt(chargeDetail.DataKeys(chargeDetailRow.RowIndex).Values("LineItemNumber"))

    Dim gridLineCount As Integer = gvOption.Rows.Count()
    Dim gridWorkingRow As Integer
    Dim OptionString As String = ""

    For gridWorkingRow = 0 To gridLineCount - 1
        Dim ddl As DropDownList = gvOption.Rows(gridWorkingRow).FindControl("ddlOptionSelection")
        Dim AttribId As String = gvOption.DataKeys(gridWorkingRow).Values("AttributeId")

        If gridWorkingRow = gridLineCount - 1 Then
            OptionString = OptionString + AttribId + ":" + ddl.SelectedValue
        Else
            OptionString = OptionString + AttribId + ":" + ddl.SelectedValue + ","
        End If
    Next gridWorkingRow

    Dim PortalConn As New SqlConnection
    PortalConn.ConnectionString = ConfigurationManager.ConnectionStrings("PortalConnStr").ConnectionString
    PortalConn.Open()

    Dim WriteBackSQL As New SqlCommand("sp_schedulePickup_UpdateOption", PortalConn)
    WriteBackSQL.CommandType = Data.CommandType.StoredProcedure
    WriteBackSQL.Parameters.Add(New SqlParameter("@SessionID", Session.SessionID.ToString()))
    WriteBackSQL.Parameters.Add(New SqlParameter("@LineItemNumber", LineItemNumber))
    WriteBackSQL.Parameters.Add(New SqlParameter("@Option", OptionString))

    Dim returnStatus As Integer
    Dim rsReturn As SqlDataReader = WriteBackSQL.ExecuteReader()
    Do While rsReturn.Read()
        returnStatus = rsReturn("ReturnStatus")
    Loop
    rsReturn.Close()
    rsReturn = Nothing

    PortalConn.Close()
    PortalConn = Nothing

    chargeDetail.DataSource = GetChargeDetails()
    chargeDetail.DataBind()
    getTotal()
End Sub