ViewState data doesn't update when deleting dynamically generated elements

28 Views Asked by At

The Entire table is generated dynamically. Addnewrow adds a row and deletebutton deletes the row. The problem lies when deleting the element gets deleted but the viewstate thinks there should be some data and on postback skips a row when entering data where the deleted row was originally positioned. Which in turn loses the last row of data

This is the back End

    protected void Page_Load(object sender, EventArgs e)
    {
        
        if (!Page.IsPostBack)
        {
            ViewState["Rows"] = tblTransactions.Rows != null ? tblTransactions.Rows.Count : 0;
        }
        else
        {
            RecreateDynamicControls();
        }
        
    }
    private void AddNewRow()
    {
        // Create a new row and set its properties
        TableRow row = new TableRow
        {
            CssClass = "transaction-row"
        };

        // Date of Sale (Calendar control)
        TableCell cellDate = new TableCell();
        Calendar calendarDate = new Calendar
        {
            SelectionMode = CalendarSelectionMode.Day,
            CssClass = "myCalendar",
            VisibleDate = new DateTime(2010, 4, 26),                                   
        };
        calendarDate.DayRender += calendarDisplay;
        //calendarDate.SelectionChanged += calendarDate_SelectionChanged;
        //calendarDate.ID = "calendarDate_" + tblTransactions.Rows.Count; // Assign a unique ID
        cellDate.Controls.Add(calendarDate);
        row.Cells.Add(cellDate);

        // Transaction type (DropDownList control)
        TableCell cellTransactionType = new TableCell();
        DropDownList ddlTransactionType = new DropDownList
        {
            CssClass = "form-control",
            
        };
        // Add your transaction type options here
        ddlTransactionType.Items.Add(new ListItem("Purchased", "Purchased"));
        ddlTransactionType.Items.Add(new ListItem("Sold", "Sold"));
        // Add more options as needed
        cellTransactionType.Controls.Add(ddlTransactionType);
        row.Cells.Add(cellTransactionType);

        // Number of Shares (TextBox control)
        TableCell cellNumberOfShares = new TableCell();
        TextBox txtShares = new TextBox
        {
            CssClass = "form-control",
            
        };
        txtShares.Attributes["type"] = "text";
        cellNumberOfShares.Controls.Add(txtShares);
        row.Cells.Add(cellNumberOfShares);

        // Total Sale Price (TextBox control)
        TableCell cellTotalSalePrice = new TableCell();
        TextBox txtSalePrice = new TextBox
        {
            CssClass = "form-control",
            
        };
        txtSalePrice.Attributes["type"] = "text";
        cellTotalSalePrice.Controls.Add(txtSalePrice);
        row.Cells.Add(cellTotalSalePrice);

        // Yes/No (DropDownList control)
        TableCell cellYesNo = new TableCell();
        DropDownList ddlShortSale = new DropDownList
        {
            CssClass = "form-control",
            
        };
        ddlShortSale.Items.Add(new ListItem("No", "0"));
        ddlShortSale.Items.Add(new ListItem("Yes", "1"));            
        cellYesNo.Controls.Add(ddlShortSale);
        row.Cells.Add(cellYesNo);

        // Delete button
        TableCell cellDeleteButton = new TableCell();
        Button btnDelete = new Button
        {
            Text = "Delete",
            CssClass = "btn btn-danger",               
        };
        btnDelete.Click += BtnDelete_Click;            
        cellDeleteButton.Controls.Add(btnDelete);
        row.Cells.Add(cellDeleteButton);

        
        // Add the row to the table
        tblTransactions.Rows.Add(row);
   
    }

    protected void btnAddRow_Click(object sender, EventArgs e)
    {
       
        AddNewRow();
        ViewState["Rows"] = (int)ViewState["Rows"] + 1;

        SaveViewState();
    }
    protected void BtnDelete_Click(object sender, EventArgs e)
    {
        // Get the reference to the clicked button
        Button btnDelete = (Button)sender;

        // Get the reference to the table row that contains the clicked button
        TableRow row = (TableRow)btnDelete.Parent.Parent;

        // Remove the row from the table
        tblTransactions.Rows.Remove(row);

        ViewState["Rows"] = (int)ViewState["Rows"] -1;


        SaveViewState();
        // Save the updated table data
    }
    private void RecreateDynamicControls()
    {
        int rows = (int)ViewState["Rows"];
        
        for (int i=0; i < rows-1; i++)
        {
            AddNewRow();
        }
        
    }

and the front end

    <asp:PlaceHolder ID="pnlTransactions" runat="server" ViewStateMode="Enabled">
        <asp:Table ID="tblTransactions" class="table table-bordered" runat="server" ViewStateMode="Enabled">
            <asp:TableHeaderRow ID="tblHeaderRow" runat="server">

                <asp:TableHeaderCell>Date of Sale</asp:TableHeaderCell>
                <asp:TableHeaderCell>Transaction type</asp:TableHeaderCell>
                <asp:TableHeaderCell>Number of Shares</asp:TableHeaderCell>
                <asp:TableHeaderCell>Total Sale Price</asp:TableHeaderCell>
                <asp:TableHeaderCell>Short Sale?</asp:TableHeaderCell>
                <asp:TableHeaderCell></asp:TableHeaderCell>
                <%--Empty column for delete button--%>
            </asp:TableHeaderRow>
            <%-- Dynamic rows will be added here --%>
        </asp:Table>

        <asp:Button ID="btnAddRow" runat="server" Text="Add New Row" OnClick="btnAddRow_Click" CssClass="btn btn-primary mt-3" />
    </asp:PlaceHolder>

The Initial Table

After Deleting the 2nd row

Any Postback afterwards

What could be the possible oversights on my end and what are the possible solutions?

I have tried generating a postback after a every user input to help initiate the viewstate cycle during postback but the only difference it makes is that instead of an empty row it has data from 3rd row(in the example above). Surprisingly enough the problem only exists with the dropdown and test boxes and not with the calendar inputs.

0

There are 0 best solutions below