【问题标题】:Null reference dropdown in gridview网格视图中的空引用下拉列表
【发布时间】:2022-01-04 02:35:20
【问题描述】:

我已经动态创建了一个下拉列表,一旦页面加载,一切都很好。在下拉菜单旁边的 gridview 的每一行中都有一个按钮。此按钮更新所选项目的表格。我得到了我的密钥,但我得到的对象引用未设置为实例。这是因为下拉控件的 id 隐藏在 ct100 的东西中吗?

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

这里是我从页面来源刷的:

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

【问题讨论】:

标签: asp.net vb.net dropdown


【解决方案1】:

一些事情。

您可以让用户进行所有更改,在网格下方,一个保存按钮。

但是,既然您在每一行上都有一个按钮,可以将该行保存回数据库吗?

那么没有必要循环一个保存按钮行中的所有行????

但是,如果用户更改了几行会发生什么 - 忘记点击保存,然后点击保存?换句话说,用户在这里会有些困惑吗?

那么,不清楚点击保存按钮应该只保存当前行吗?

如果这是目标,那么我们可以说这个设置:

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

要加载的代码是:

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

我们现在有了这个:

好的,那么保存按钮 - 保存一行?

这行得通:

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

所以,如您所见,没有真正需要循环和保存所有行,是吗?

我想如果你想要一个保存按钮?

然后将保存按钮移出网格,然后保存有这样的:

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

现在是这样的:

还有一个保存按钮(我认为保存后应该说导航到其他页面 - 因为我们已经完成了)。现在保存所有行的代码是:

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

因此,代码对于保存“所有”行或仅保存一行非常相似。

但是,我们也可以在“保存”旁边添加一个名为“取消”或“取消”的按钮

因此,上面显示了如何获得行点击 - 用于保存 ONE 行,第二个代码显示如何对所有行执行此操作。

【讨论】:

  • 你能把 strSql 移到 For 循环之外吗?每次迭代都是一样的,看起来你每次都不需要一个新的字符串。
  • 不错的建议 - 在事情的范围内是次要的 - 但会做!鉴于我们可以轻松地运行什么,即使是在弱处理器上每秒十亿次循环?那么你真的无法在一个循环中看到或计算时间上的差异,从一个 GV 的循环中说 - 最多 50 条记录?因此,真正的答案是根据您的个人喜好编写代码 - 以及您会发现更具可读性的代码。但是,我喜欢这个建议并更改了代码。读者的选择是他们喜欢的任何东西——但作为一个好习惯?不重新运行不需要的代码是个好主意?提出一个好建议
【解决方案2】:

感谢您对这个问题的建议。是的,我现在将它作为一个按钮。 我有几件事导致它无法工作。我想只需一个按钮即可重新保存页面上的选择。

 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

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
相关资源
最近更新 更多