Home > Software design >  Having trouble populating a drop down list within a gridview
Having trouble populating a drop down list within a gridview

Time:08-03

as the title states I am currently having trouble populating a drop down list that is contained within a gridview. At first glance this seems like a relatively simple problem and I have populated many gridviews and many drop down lists in the past, however this one is being a real pain. I am relatively new to software development so any help regarding this issue regardless of simplicity would be greatly appreciated. Below I have detailed the problem more explicitly and copied any relevant code, if there is anything I have missed I would be more than happy to supply it.

As stated before I have a drop down list (ddlPartEquipmentNew) within a gridview control (GridView3). So far there is one item in the ddl "---SELECT---" that I added as a ListItem in the aspx page. I am trying to populate the gridview with data from my database that corresponds to a value that is currently stored in a variable on the page. I have tested my query and can confirm that it returns the appropriate values in SSMS and it looks like

SELECT EquipmentType FROM Equipment WHERE Agreement = @Agreement

Below I have posted The aspx code of the gridview and drop down.

<asp:GridView ID="GridView3" runat="server"
    EmptyDataText="No Claimed Parts" AutoGenerateColumns="False"
    ShowHeaderWhenEmpty="True" DataKeyNames="RecID"
    ShowFooter="True" DataSourceID="SqlDataSource5" Width="95%">

<EmptyDataTemplate>
    <asp:DropDownList ID="ddlPartEquipmentNew" runat="server" DataSourceID="SqlDataSourcePartEquipment" DataValueField="EquipmentType" DataTextField="EquipmentType"
        AppendDataBoundItems="True" Width="270px" Height="20px" Style="margin-left: 70px;">
        <asp:ListItem Value="0">---SELECT---</asp:ListItem>
    </asp:DropDownList>
    <asp:DropDownList ID="ddlPartNew" runat="server" DataSourceID="SqlDataSourcePart" DataValueField="RecID"
        DataTextField="description" AppendDataBoundItems="True" Width="270px"  Height="20px"
        style="margin-left: 70px; margin-right: 110px">
        <asp:ListItem Value="0">---SELECT---</asp:ListItem>
    </asp:DropDownList>
    <asp:textbox ID="txtUnitPriceNew" runat="server" Width="95px"/>
    <asp:textbox ID="txtTaxNew" runat="server" Width="95px" text="0"/>
    <asp:Button ID="InsertDetail" runat="server" CommandName="InsertDetail" Height="25px" Text="Add Detail" Width="85px" />
</EmptyDataTemplate>

<AlternatingRowStyle BackColor="#CCCCCC" />
    <Columns>
        <asp:CommandField ShowEditButton="True" footertext="Add -->" ShowDeleteButton="True" HeaderStyle-Width="70px"/>
        <asp:BoundField DataField="RecID" HeaderText="RecID" SortExpression="RecID" ReadOnly="True" Visible="False" />

        <asp:TemplateField HeaderText="Parts Description" ItemStyle-HorizontalAlign="center">
            <ItemTemplate>
                <asp:label ID="lblDescriptionAdd" Text='<%# Bind("PartFailed") %>' runat="server"/>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList ID="ddlPartEquipmentEdit" runat="server" DataValueField="Agreement" DataTextField="EquipmentType"
                    AppendDataBoundItems="True" Width="270px" Height="20px" Style="margin-left: 70px;">
                    <asp:ListItem Value="0">---SELECT---</asp:ListItem>
                </asp:DropDownList>
                <asp:DropDownList ID="ddlPartEdit" runat="server" DataSourceID="SqlDataSourcePart" DataValueField="RecID" DataTextField="description" SelectedValue='<%# Eval("RepairID")%>' AppendDataBoundItems="True" Width="270px"/>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:DropDownList ID="ddlPartEquipmentInsert" runat="server" DataValueField="Agreement" DataTextField="EquipmentType"
                    AppendDataBoundItems="True" Width="270px" Height="20px" Style="margin-left: 70px;">
                    <asp:ListItem Value="0">---SELECT---</asp:ListItem>
                </asp:DropDownList>
                <asp:DropDownList ID="ddlPartInsert" runat="server" DataSourceID="SqlDataSourcePart" DataValueField="RecID" DataTextField="description" AppendDataBoundItems="True" Width="270px">
                    <asp:ListItem Value="0">---SELECT---</asp:ListItem>
                </asp:DropDownList>
            </FooterTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Part Cost Requested" ItemStyle-HorizontalAlign="center" HeaderStyle-Width="100px">
            <ItemTemplate>
                <asp:label ID="lblUnitPrice" Text='<%# Bind("PartCost", "{0:C}") %>' runat="server" Enabled="False"/>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:textbox ID="txtUnitPriceEdit" Text='<%# Bind("PartCost") %>' Enabled="true" runat="server"/>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:textbox ID="txtUnitPriceInsert" Text='<%# Bind("PartCost") %>' runat="server" style="width: 100%; box-sizing: border-box;"/>
            </FooterTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Tax" ItemStyle-HorizontalAlign="Center" HeaderStyle-Width="100px">
            <ItemTemplate>
                <asp:LinkButton ID="lbTaxTotal" Text='<%# Bind("Tax", "{0:C}")%>' runat="server" CommandArgument="Part" OnClick="lblTaxTotal_Click"/>
                <asp:HiddenField ID="hidPartGST" runat="server" Value='<%# Bind("GST")%>' />
                <asp:HiddenField ID="hidPartPST" runat="server" Value='<%# Bind("PST")%>' />
                <asp:HiddenField ID="hidPartQST" runat="server" Value='<%# Bind("QST")%>' />
                <asp:HiddenField ID="hidPartHST" runat="server" Value='<%# Bind("HST")%>' />
            </ItemTemplate>
            <EditItemTemplate>
                <asp:textbox ID="lblTaxTotalEdit" Text='<%# Bind("Tax")%>' Enabled="true" runat="server"/>
            </EditItemTemplate>
            <FooterTemplate>
                <asp:textbox ID="txtTaxTotalInsert" Text="0" runat="server" Enabled="true" style="width: 100%; box-sizing: border-box;"/>
            </FooterTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Insert New" HeaderStyle-Width="85px">
            <ItemTemplate>
                <asp:Label ID="lblEmpty" Text="" runat="server" Width="75px"/>
            </ItemTemplate>
            <FooterTemplate>
                <asp:Button ID="Insert" runat="server" CommandName="InsertNewDetail" Height="22px" Text="Insert" style="width: 100%; box-sizing: border-box;" />
            </FooterTemplate>
        </asp:TemplateField>
        </Columns>
        <HeaderStyle BackColor="#336699" ForeColor="White" />
    </asp:GridView>

In order to populate the drop down list I have associated it with an asp:SqlDataSource control below.

<asp:SqlDataSource ID="SqlDataSourcePartEquipment" runat="server" ConnectionString="<%$ ConnectionStrings:WarrantyConnectionString %>" 
    SelectCommand="SELECT EquipmentType FROM Equipment WHERE Agreement = @Agreement">
</asp:SqlDataSource>

In the vb.net code behind I have declared the parameter in the page load event as seen below

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    'Decrypt et get params
    MaintainScrollPositionOnPostBack = True
    hashtableParams = RedirectionHandler.EncryptedRequest(Request.QueryString("data"))
    'SqlDataSourcePartEquipment.SelectParameters.Add("@Agreement", hashtableParams("agreementNumber"))
    'If Page.IsPostBack Then
    'Dim wcICausedPostBack As WebControl = CType(GetControlThatCausedPostBack(TryCast(sender, Page)), WebControl)
    'Dim indx As Integer = wcICausedPostBack.TabIndex
    'Dim ctrl = _
    'From control In wcICausedPostBack.Parent.Controls.OfType(Of WebControl)() _
    'Where control.TabIndex > indx _
    'Select control
    'ctrl.DefaultIfEmpty(wcICausedPostBack).First().Focus()
    'End If

    'Dim SClaimID As String = CType(Session.Item("SClaimID"), String)
    If Not IsPostBack Then
        Dim agreement As String = hashtableParams("agreementNumber")
        Dim claimID As String

        If hashtableParams.Count > 0 AndAlso Not IsNothing(hashtableParams("claimID")) Then
            claimID = hashtableParams("claimID")
            Session("ClaimID") = claimID
        Else
            claimID = CType(Session.Item("ClaimID"), String)
        End If

        Me.txtAgreement.Text = agreement
        Me.txtOtherInvoice.Text = "I'm Working"

        If Not String.IsNullOrEmpty(claimID) Then
            objCn.Open()
            objSelectCmd.Connection = objCn
            objSelectCmd.CommandText = "Select * From Claim Where ClaimNumber = @ClaimID"
            objSelectCmd.Parameters.Add("ClaimID", SqlDbType.Int).Value = claimID

            objSelectCmd.Connection = objCn
            objDa.SelectCommand = objSelectCmd
            objDa.Fill(objDs, "Claim")
            objDataTable = objDs.Tables("Claim")
            objCurrentRow = objDataTable.Rows(0)
            Me.txtAgreement.Text = objCurrentRow("Agreement").ToString
            Me.txtServicerNumber.Text = objCurrentRow("AccountNumber").ToString
            'Me.txtCNumber.Text = objCurrentRow("AccountNumber").ToString
            Me.lblClaimNumber.Text = objCurrentRow("ClaimNumber").ToString
            lblCreationDate.Text = Convert.ToDateTime(objCurrentRow("CreateDate").ToString).ToShortDateString
            Me.txtProblem.Text = objCurrentRow("ProblemDescription").ToString
            Me.txtSubmitDate.Text = Convert.ToDateTime(objCurrentRow("ReceivedDate").ToString).ToShortDateString
            Me.txtWorkPerformed.Text = objCurrentRow("WorkPerformed").ToString
            Me.txtServiceDate.Text = Convert.ToDateTime(objCurrentRow("FailDate").ToString).ToShortDateString
            Me.txtWorkInvoice.Text = objCurrentRow("WorkInvoice").ToString
            Me.txtOtherInvoice.Text = objCurrentRow("OtherInvoice").ToString
            Me.lblClaimStatus.Text = objCurrentRow("Status").ToString
            SqlDataSourcePartEquipment.SelectParameters.Add("@Agreement", hashtableParams(agreementNumber))

(There is much more code in the Page_load() event, and if required I can supply it) When I execute this code and navigate to the web form in question I receive an exception error "Must declare the scalar variable "@Agreement". To my knowledge I am declaring the @Agreement variable in the last line of what I posted of the Page_Load event. I have also used the "agreement" variable seen earlier in the page load event and when I use that, I don't receive the exception error but my drop down still isn't populated.

Whats confusing me so much is that every variable or control that stores the value I need for my parameter either populates nothing to my drop down or I receive the exception mentioned above.

If anyone has an idea as to why this could be happening I would greatly appreciate some input here as I am at a loss as to what to do.

CodePudding user response:

Ok, you have a lot of moving parts.

But, how to setup a combo box in a gv?

Say this simple markup:

<asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ID" CssClass="table table-striped" Width="50%">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName"     />
        <asp:BoundField DataField="LastName" HeaderText="LastName"       />
        <asp:BoundField DataField="HotelName" HeaderText="HotelName"     />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="Rate Hotel">
            <ItemTemplate>
            <asp:DropDownList ID="cboRank" runat="server"
                DataValueField="ID"
                DataTextField="Rating" >
            </asp:DropDownList>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:Button ID="cmdSave" runat="server" Text="Save Changes" CssClass="btn" 
OnClick="cmdSave_Click"  />                          

<asp:Button ID="cmdAddNew" runat="server" Text="New Hotel" CssClass="btn"
    style="margin-left:20px" />                          

And code to load this up is this:

Dim rstRank As New DataTable ' to load cbo box

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

    If Not IsPostBack Then
        LoadData()
    End If

End Sub

Sub LoadData()

    ' load combo box data
    rstRank = MyRst("SELECT ID, Rating from tblRating ORDER BY ID")

    ' load gv
    Dim strSQL As String =
        "SELECT * FROM tblHotelsA ORDER BY HotelName"

    GHotels.DataSource = MyRst(strSQL)
    GHotels.DataBind()

End Sub

Function MyRst(strSQL As String) As DataTable

    Dim rst As New DataTable

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            conn.Open()
            rst.Load(cmdSQL.ExecuteReader)
        End Using
    End Using

    Return rst

End Function

And we get this:

enter image description here

The only extra part? We need to load up each row combo, and ALSO set the value from the data. We use the row data bound event, and this code:

Protected Sub GHotels_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GHotels.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then

        ' load combo box with choices
        Dim cboRank As DropDownList = e.Row.FindControl("cboRank")
        cboRank.DataSource = rstRank
        cboRank.DataBind()
        ' add blank row "select"
        cboRank.Items.Insert(0, New ListItem("Select", "0"))

        ' NOW set combo to current choice in database
        Dim rowData As DataRowView = e.Row.DataItem
        If Not IsDBNull(rowData("Rating")) Then
            cboRank.SelectedValue = rowData("Rating")
        End If

    End If

So, in a nutshell, the above is the basic approch. However, you have a boatload of markup, and seem to have the 2 combo boxes repeated at least 3 times. You need to VAST VAST reduce the amount of markup you have. You with a somewhat different approach reduce that markup to what I have above - and have editing. But, I would not use edit templates, and I would not even use a whole new alternatiing template for JUST display of bands (note how I used the style class = table to make the grid look nice, and added table-striped to alternate the bands). This is a bootstrap class - and by default most asp.net sites do have bootstrap installed.

If you need editing, then I would suggest a clean and simple layout using listview in place of grid view. it tends to mean VAST less markup, and is less convoluted.

And for each asp.net control, you don't have to wrap it around a template.

So, to allow editing of the data above, and a simple save to save all edits. Then I would use this (a list view).

   <style> 
       .borderhide input {border:none}
       .borderhide textarea {border:none}
   </style>

<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID">
<ItemTemplate>
    <tr style="">
        <td><asp:Textbox ID="txtFirst" runat="server" Text='<%# Eval("FirstName") %>' Width="100px"/></td>
        <td><asp:TextBox ID="txtLast" runat="server" Text='<%# Eval("LastName") %>'   Width="100px" /></td>
        <td><asp:TextBox ID="CityLabel" runat="server" Text='<%# Eval("City") %>'     Width="100px" /></td>
        <td><asp:TextBox ID="txtHotelName" runat="server" Text='<%# Eval("HotelName") %>' Width="100px" /></td>
        <td>
            <asp:TextBox ID="txtDescription" runat="server" Text='<%# Eval("Description") %>' 
                TextMode="MultiLine" Columns="60" /></td>
        <td>
            <asp:DropDownList ID="cboRank" runat="server"
            DataValueField="ID"
            DataTextField="Rating" >
            </asp:DropDownList>
        </td>
    </tr>
</ItemTemplate>
    <LayoutTemplate>
        <table id="itemPlaceholderContainer" runat="server"  >
            <tr runat="server" style="">
                <th runat="server">First Name</th>
                <th runat="server">Last Name</th>
                <th runat="server">City</th>
                <th runat="server">Hotel Name</th>
                <th runat="server">Description</th>
                <th runat="server">Rating</th>
            </tr>
            <tr id="itemPlaceholder" runat="server">
            </tr>
        </table>
    </LayoutTemplate>
</asp:ListView>

<asp:Button ID="cmdSave" runat="server" Text="Save Changes" CssClass="btn" 
OnClick="cmdSave_Click"  />                          

<asp:Button ID="cmdAddNew" runat="server" Text="New Hotel" CssClass="btn"
    style="margin-left:20px" />                          

But with above, I can have ONE easy save button - saves all edits. No messy edit template, no messy itemtemplates for each row. No noting. And the above allows editing of all rows - one simple save button sends all changes to the database.

so, as listview, we get this:

enter image description here

I can post the save code, but this question was about setting up a combo box.

But, to "save" all and any edits, the above markup remains "as is", and we save boatloads of markup, and boatloads of code behind here.

So the ONE set of markup allows:

Display of data
Editing of data
Save of data

Now, I did original use the wizard and the datasouce it puts on the page. I then just went on a delete hunt, and removed all the templates - only need itemtemplate and I am done for display, and editing of the data.

  • Related