0

I have dynamically created a dropdown and everything is fine once the page loads. There is a button in each row of the gridview next to the dropdown. This button updates the table for the selected item. I'm getting my key, but I"m getting object reference not set to an instance. Is that because the id of the dropdown control is burried in ct100 stuff?

Dim ddluid As String = CType(FindControl("Ddlos"), DropDownList).SelectedItem.Value

This here I have swiped from the source of the page:

<select name="ctl00$ContentPlaceHolder2$GridView1$ctl02$Ddlos" id="ctl00_ContentPlaceHolder2_GridView1_ctl02_Ddlos">
                <option value="0">-Select-</option>
                <option value="503841a3-c615-4e4d-8cf5-20fbddbf7a7f">John Doe</option>
                <option value="9b38e9cd-f16f-4fdd-a82e-501c866f9e45">Sam Beacon</option>
                <option value="fe6158c5-a549-443f-b5ff-c011937db1d7">John Doey</option>
                <option value="295e9f85-6ea6-46ec-9c00-c38d64023517">Scot King</option>

 Protected Sub btnsaveinfo(sender As Object, e As EventArgs)
        Dim key As String = ""
        For Each row As GridViewRow In GridView1.Rows
            If row.RowType = DataControlRowType.DataRow Then
                key = GridView1.DataKeys(row.RowIndex).Value.ToString()
                Dim ddluid As String = CType(FindControl("Ddlos"), DropDownList).SelectedItem.Value
                'Dim idvalue As String = ddluid.SelectedValue
                'Dim louid As Guid =
                Dim cn As New SqlConnection(ConfigurationManager.ConnectionStrings("sqlConnectionString").ConnectionString)
                Dim cmdupdate As New SqlCommand("update Profiles SET [loanrepid] = @loanrepid WHERE ApplicantID=@ApplicantID", cn)
                cmdupdate.Parameters.AddWithValue("@loanrepid", "1")
                cmdupdate.Parameters.AddWithValue("@ApplicantID", key)
                cmdupdate.CommandType = System.Data.CommandType.Text
                cmdupdate.Connection = cn
                cn.Open()
                cmdupdate.ExecuteNonQuery()
                cn.Close()
            End If
        Next
        lblresult.Text = " Details Updated Successfully"
        lblresult.Visible = True
    End Sub



          <asp:TemplateField HeaderText="Loan Officer" SortExpression="Loan Officer" ItemStyle-HorizontalAlign="Center">
                <ItemTemplate>
                    <asp:DropDownList ID="Ddlos" runat="server" Visible="false"></asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
Scot
  • 29
  • 4
  • 1
    Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Daniel A. White Jan 04 '22 at 02:36

2 Answers2

1

A a few things.

You could have the user make all changes, and the below the grid, one save button.

however, since you have a button on each row, to save the row back to database?

Then no need exists to loop all rows in the one save button row????

However, what happens if the user changes several rows - forgets to hit save, and then does hit save? In other words, the user going to be somewhat confused here?

So, it not clear that clicking on the save button should only save the current row?

If that is the goal, then we could have say this setup:

        <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID" CssClass="table" 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">
                    <ItemTemplate>
                    <asp:DropDownList ID="cboRank" runat="server"
                        DataValueField="ID"
                        DataTextField="Rating" >
                    </asp:DropDownList>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText="Save" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" Width="60"
                          OnClick="cmdSave_Click"  />                          
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

And code to load would be:

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

    Dim strSQL As String =
        "SELECT ID, FirstName, LastName, HotelName, Description, Ranking from tblHotels"

    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

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

    If e.Row.RowType = DataControlRowType.DataRow Then

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

        Dim v As Object = e.Row.DataItem
        Dim rData As DataRowView = e.Row.DataItem

        If Not IsDBNull(rData("Ranking")) Then
            cboRank.SelectedValue = rData("Ranking")
        End If

    End If

End Sub

and we now have this:

enter image description here

Ok, so the save button - to save the one row?

this works:

Protected Sub cmdSave_Click(sender As Object, e As EventArgs)

    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer

    Dim cboRank As DropDownList = gRow.FindControl("cboRank")
    Dim strSQL As String = "UPDATE tblHotels SET Ranking = @Rating WHERE ID = @ID"

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = GHotels.DataKeys(gRow.RowIndex).Value
            cmdSQL.Parameters.Add("@Rating", SqlDbType.Int).Value = cboRank.SelectedItem.Value
            conn.Open()
            cmdSQL.ExecuteNonQuery()
        End Using

    End Using

End Sub

So, as you can see, no real need to loop and save ALL rows, is there?

I would think that if you want ONE save button?

Then move the save button OUT of the grid, and then save have this:

        <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID" CssClass="table" 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">
                    <ItemTemplate>
                    <asp:DropDownList ID="cboRank" runat="server"
                        DataValueField="ID"
                        DataTextField="Rating" >
                    </asp:DropDownList>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        <br />
        <asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" Width="60"
        OnClick="cmdSave_Click"  />                          

And now this:

enter image description here

And the one save button (which I think after saving should say navagate to some other page - since we are done). That code to now save all rows, would be:

Protected Sub cmdSave_Click(sender As Object, e As EventArgs)

    Using conn As New SqlConnection(My.Settings.TEST4)

        Dim strSQL As String = "UPDATE tblHotels SET Ranking = @Rating WHERE ID = @ID"

        conn.Open()

        For Each gRow As GridViewRow In GHotels.Rows

            Dim cboRank As DropDownList = gRow.FindControl("cboRank")

            Using cmdSQL As New SqlCommand(strSQL, conn)
                cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = GHotels.DataKeys(gRow.RowIndex).Value
                cmdSQL.Parameters.Add("@Rating", SqlDbType.Int).Value = cboRank.SelectedItem.Value
                cmdSQL.ExecuteNonQuery()
            End Using
        Next

    End Using

End Sub

So, again the code is rather simular for saving "all" rows, or just the one row.

However, we could also drop in a button beside "save" called "un-do" or "cancel"

So, the above shows how to get the row click - for ONE row save, and the 2nd code shows how do to this for all rows.

Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51
  • 1
    Can you move strSql to outside the For loop? It is the same for each iteration and it seems you don't need a new string each time. – Mary Jan 04 '22 at 22:30
  • Nice suggestion - minor in the scope of things - but will do! Given that we can easy run what, a billion loops per second on even weak procesors? Then you not really ever be able to even SEE or count the difference time wise say in a loop from a GV that will have what - max 50 records? So the REAL answer then is to code to your personal preference - and what you would find more readable. However, I like the suggestion and have changed the code. The choice to readers is whatever they like - but as a good habit? And a good idea to not re-run code not required? Hands down a good suggestion – Albert D. Kallal Jan 04 '22 at 22:32
0

thank you for your advice on the problem. Yes, I have it as one button now. I had a couple things there that were causing it to not work. I figure just one button to resave the selections on the page.

 Protected Sub btnsaveinfo_Click(sender As Object, e As EventArgs) Handles btnsaveinfo.Click
        Dim key As String = ""
        For Each grow As GridViewRow In GridView1.Rows
            If grow.RowType = DataControlRowType.DataRow Then
                key = GridView1.DataKeys(grow.RowIndex).Value.ToString()
                Dim ddlo As DropDownList = grow.FindControl("Ddlos")
                Dim selectedlo As String = ddlo.SelectedValue
                Dim result As Int16 = ddlo.SelectedIndex
                If result = 0 Then
                    lblresult.Text = "You must select a Loan Officer for each loan"
                    lblresult.ForeColor = Drawing.Color.Red
                    lblresult.Visible = True
                    Exit Sub
                End If
                Dim loguid As Guid = Guid.Parse(selectedlo)
                Dim ddproc As DropDownList = grow.FindControl("ddlprocessor")
                Dim selectedproc As String = ddproc.SelectedValue
                Dim cn As New SqlConnection(ConfigurationManager.ConnectionStrings("sqlConnectionString").ConnectionString)
                Dim cmdupdate As New SqlCommand("update Loanapps SET [loanrepid] = @loanrepid WHERE ApplicantID=@ApplicantID", cn)
                cmdupdate.Parameters.AddWithValue("@loanrepid", loguid)
                cmdupdate.Parameters.AddWithValue("@ApplicantID", key)
                cmdupdate.CommandType = System.Data.CommandType.Text
                cmdupdate.Connection = cn
                cn.Open()
                cmdupdate.ExecuteNonQuery()
                cn.Close()
                If ddproc.SelectedIndex <> 0 Then
                    Dim procguid As Guid = Guid.Parse(selectedproc)
                    Dim cmdupdate2 As New SqlCommand("update Loanapps SET [processorid] = @processorid WHERE ApplicantID=@ApplicantID", cn)
                    cmdupdate2.Parameters.AddWithValue("@processorid", procguid)
                    cmdupdate2.Parameters.AddWithValue("@ApplicantID", key)
                    cmdupdate2.CommandType = System.Data.CommandType.Text
                    cmdupdate2.Connection = cn
                    cn.Open()
                    cmdupdate2.ExecuteNonQuery()
                    cn.Close()
                End If
            End If
        Next


        ' Response.Redirect("default.aspx")
        lblresult.Text = " Details Updated Successfully"
        lblresult.ForeColor = Drawing.Color.Green
        lblresult.Visible = True
        Page.ClientScript.RegisterStartupScript(Me.GetType(), "alertscript", "<script>$('.TempAlert1').hide(8000);</script>")
    End Sub
Scot
  • 29
  • 4
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 12 '22 at 02:09