Search code examples
asp.netajaxlistboxupdatepanelsqldatasource

Why won't my UpdatePanel update my Listbox as I expect on button click?


I have a form with a dropdownlist, two buttons, and two Listboxes inside an UpdatePanel. The Dropdownlist, and listboxes are all bound to SqlDatasources. The dropdownlist allows you to choose your department.

The first listbox shows a list of Jobs associated with what you've selected from the department.

The second listbox shows an inverse list of those items. (Jobs in the database that are not associated with your department)

When an item is removed from the 1st listbox, it should show up in the 2nd listbox. When an item is removed from the 2nd listbox, it should show up in the 1st listbox.

This functionality allows you to add and remove jobs from your department

The are two buttons on the page function as Add and Remove buttons. Everything is working except the Listboxes will not reliably update. The Data itself is updated in the database, and if I refresh (F5) it will show correctly.

<asp:ScriptManager ID="smgrDeptsJobs" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="uPanelDeptsJobs" runat="server">
    <ContentTemplate>
        <asp:DropDownList ID="ddlDepartments" runat="server" 
            DataSourceID="sqldsDepartments" DataTextField="Department" 
            DataValueField="DeptID" Width="150px" AutoPostBack="True">
        </asp:DropDownList>

        <asp:ListBox ID="lstJobsIn" runat="server" DataSourceID="sqldsJobsIn" 
            DataTextField="JobName" DataValueField="JobID" height="156px" 
            width="220px">
        </asp:ListBox>

        <asp:Button ID="btnAddJob" runat="server" Text="&lt;&lt;" Width="70px" 
            CausesValidation="False" />

        <asp:Button ID="btnRemoveJob" runat="server" Text="&gt;&gt;" Width="70px" 
            CausesValidation="False" />

        <asp:ListBox ID="lstJobsOut" runat="server" DataSourceID="sqldsJobsOut" 
            DataTextField="JobName" DataValueField="JobID" height="156px" 
            width="220px">
        </asp:ListBox>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="ddlDepartments" 
            EventName="SelectedIndexChanged" />
        <asp:AsyncPostBackTrigger ControlID="btnAddJob" EventName="Click" />
        <asp:AsyncPostBackTrigger ControlID="btnRemoveJob" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>

The code for the two button click events is below:

Protected Sub btnAddJob_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddJob.Click

    Dim sqlJobsDB As New SqlConnection(ConfigurationManager.ConnectionStrings("JobsDB").ConnectionString)
    Dim sqlCmdInsert As SqlCommand = sqlJobsDB.CreateCommand()

    sqlJobsDB.Open()
    sqlCmdInsert.CommandText = _
        "INSERT INTO tblDeptsJobs (DeptID, JobID) VALUES " + _
        "(@DeptID, @JobID)"

    ' Declare the data types for the parameters
    sqlCmdInsert.Parameters.Add("@DeptID", SqlDbType.TinyInt)
    sqlCmdInsert.Parameters.Add("@JobID", SqlDbType.TinyInt)

    ' Assign the parameters values from the form
    sqlCmdInsert.Parameters("@DeptID").Value = ddlDepartments.SelectedValue
    sqlCmdInsert.Parameters("@JobID").Value = lstJobsOut.SelectedValue

    ' Execute the insert Statement
    sqlCmdInsert.ExecuteNonQuery()

    sqlJobsDB.Close()

End Sub

Protected Sub btnRemoveJob_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRemoveJob.Click

    Dim sqlJobsDB As New SqlConnection(ConfigurationManager.ConnectionStrings("JobsDB").ConnectionString)
    Dim sqlCmdDelete As SqlCommand = sqlJobsDB.CreateCommand()

    sqlJobsDB.Open()
    sqlCmdDelete.CommandText = _
        "DELETE FROM tblDeptsJobs WHERE tblDeptsJobs.DeptID = @DeptID AND tblDeptsJobs.JobID = @JobID"

    ' Declare the data types for the parameters
    sqlCmdDelete.Parameters.Add("@DeptID", SqlDbType.TinyInt)
    sqlCmdDelete.Parameters.Add("@JobID", SqlDbType.TinyInt)

    ' Assign the parameters values from the form
    sqlCmdDelete.Parameters("@DeptID").Value = ddlDepartments.SelectedValue
    sqlCmdDelete.Parameters("@JobID").Value = lstJobsIn.SelectedValue

    ' Execute the insert Statement
    sqlCmdDelete.ExecuteNonQuery()

    sqlJobsDB.Close()

End Sub

It feels like when I add or remove a job, the listbox that I last selected an item in, is the one that doesn't update.

I also can't get the dropdownlist to update the listboxes without setting autopostback on the dropdownlist to True.

The ugly Band-Aid fix I've come up with is using the listbox.items.clear() method and then rebinding the data for each listbox.


Solution

  • Basically what is happening is that you update your database but never rebind your controls. I'm not sure exactly what you will have to put into your click handlers to make this work (because I have never used the SQL datasource controls before), but it should look something like this:

    Protected Sub btnAddJob_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddJob.Click
    
        Dim sqlJobsDB As New SqlConnection(ConfigurationManager.ConnectionStrings("JobsDB").ConnectionString)
        Dim sqlCmdInsert As SqlCommand = sqlJobsDB.CreateCommand()
    
        sqlJobsDB.Open()
        sqlCmdInsert.CommandText = _
            "INSERT INTO tblDeptsJobs (DeptID, JobID) VALUES " + _
            "(@DeptID, @JobID)"
    
        ' Declare the data types for the parameters
        sqlCmdInsert.Parameters.Add("@DeptID", SqlDbType.TinyInt)
        sqlCmdInsert.Parameters.Add("@JobID", SqlDbType.TinyInt)
    
        ' Assign the parameters values from the form
        sqlCmdInsert.Parameters("@DeptID").Value = ddlDepartments.SelectedValue
        sqlCmdInsert.Parameters("@JobID").Value = lstJobsOut.SelectedValue
    
        ' Execute the insert Statement
        sqlCmdInsert.ExecuteNonQuery()
    
        sqlJobsDB.Close()
    
        //may need to do explicit call to DB to get data here
        //after you have the data, rebind
        lstJobsIn.DataBind();
        lstJobsOut.DataBind();
    End Sub
    

    That's roughly what it will look like. I would be interested to see what exactly you do to solve your problem.