Home > Enterprise >  Add (insert) new row textbox in grid view programmatically not showing
Add (insert) new row textbox in grid view programmatically not showing

Time:07-27

so I have this code for grid view in asp.net

    <asp:GridView ID="grdNewClaim" CssClass="table table-bordered table-condensed" GridLines="None" runat="server" AutoGenerateColumns="false">
        <Columns>
            <asp:BoundField DataField="claim_type" HeaderText="Claim Type" />
            <asp:BoundField DataField="purpose_desc" HeaderText="Purpos/Description" />
            <asp:BoundField DataField="currency" HeaderText="Currency" />
            <asp:BoundField DataField="amount" HeaderText="Amount" />
            <asp:TemplateField HeaderText="Currency Rate">
               <ItemTemplate>
                    <asp:TextBox ID="txtChangeCurrRate" runat="server"></asp:TextBox>
               </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Converted Rate">
                <ItemTemplate>
                    <asp:TextBox ID="txtChangeConvertedRate" runat="server"></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

And this code to add the new row for the gridview

    Private Sub addClaimProgrammatically()
        Dim dt As New DataTable
        Dim dr As DataRow
        If grdNewClaim.Rows.Count = 0 Then
            dt.Columns.Add("claim_type")
            dt.Columns.Add("purpose_desc")
            dt.Columns.Add("currency")
            dt.Columns.Add("amount")
            dt.Columns.Add("txtChangeCurrRate")
            dt.Columns.Add("txtChangeConvertedRate")


            dr = dt.NewRow
            dr.Item("claim_type") = cmbClaimtype.Text
            dr.Item("purpose_desc") = txtPurpDesc.Text
            dr.Item("currency") = cmbCurrency.Value
            dr.Item("amount") = txtAmmount.Text
            dr.Item("txtChangeCurrRate") = lblCurrencyrate.Text
            dr.Item("txtChangeConvertedRate") = lblconvertedRateMYR.Text
            dt.Rows.Add(dr)
        End If
      

        grdNewClaim.DataSource = dt
        grdNewClaim.DataBind()
    End Sub

But for some reason the items for for both textbox just blank like this : like this

So any idea why? Because if I change the textbox to <asp:BoundField/> it works just fine like this enter image description here

CodePudding user response:

When you use a boundfield, it works because you CAN SPECIFY which column to display.

bound field only works due to this:

enter image description here

Computers do not "guess" or "assume" what data column to use here.

But, when you use a templated column, and a standard control, then you need to use a expression that defines which column to use.

eg this:

<asp:TemplateField HeaderText="Currency Rate">
   <ItemTemplate>
      <asp:TextBox ID="txtChangeCurrRate" runat="server"></asp:TextBox>
   </ItemTemplate>
</asp:TemplateField>

so, in above, ask this question: Where in above does the markup KNOW which column to use?

So, you have to use a binding expression, since TextBox does not have a "boundfield" property to tell it which column to use.

Try like this:

<asp:TemplateField HeaderText="Currency Rate">
   <ItemTemplate>
      <asp:TextBox ID="txtChangeCurrRate" runat="server"
      Text = '<%# Eval("Currency") %>'
      ></asp:TextBox>
   </ItemTemplate>
</asp:TemplateField>

So, in above, we would be using column "Currency" for the text (or you can use "amount" or "purpose_desc" or any column from the data source.

So, your example does not work, since with a templated textbox, you have to specify the column to use - (by some how and some way). So, use the above binding expression.

Edit: data does not persist - only can add one row.

Correct - you need to save that table between each post-back, and NOT re-create the table from scratch each time, else you lose previous rows.

So, the code has to look like this:

NOTE how I defined dt at the class level (right before page load).

And note how I "restore" this dt in page load EACH time.

So, your code will become this

Markup like this:

   <asp:GridView ID="grdNewClaim" CssClass="table table-bordered table-condensed" 
            GridLines="None" runat="server" AutoGenerateColumns="false"
            ShowHeaderWhenEmpty="true" >
    <Columns>
        <asp:BoundField DataField="claim_type" HeaderText="Claim Type" />
        <asp:BoundField DataField="purpose_desc" HeaderText="Purpos/Description" />
        <asp:BoundField DataField="currency" HeaderText="Currency" />
        <asp:BoundField DataField="amount" HeaderText="Amount" />
        <asp:TemplateField HeaderText="Currency Rate">
           <ItemTemplate>
                <asp:TextBox ID="txtCRateZoo" runat="server"
                    Text = '<%# Eval("txtChangeCurrRate") %>'>
                </asp:TextBox>
           </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Converted Rate">
            <ItemTemplate>
                <asp:TextBox ID="txtConvertedRate" runat="server"                        
                    Text = '<%# Eval("txtChangeCurrRate") %>' >

                </asp:TextBox>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

And code now like this:

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

    If Not IsPostBack Then

        CreateTable()
        LoadGrid()
        Session("dt") = dt

    Else
        ' restore table
        dt = Session("dt")
    End If

End Sub


Sub CreateTable()

    dt.Columns.Add("claim_type", GetType(String))
    dt.Columns.Add("purpose_desc")
    dt.Columns.Add("currency", GetType(Double))
    dt.Columns.Add("amount", GetType(Double))
    dt.Columns.Add("txtChangeCurrRate", GetType(Double))
    dt.Columns.Add("txtChangeConvertedRate", GetType(Double))

End Sub

Sub LoadGrid()

    grdNewClaim.DataSource = dt
    grdNewClaim.DataBind()

End Sub


Private Sub addClaimProgrammatically()

    Dim dr As DataRow
    dr = dt.NewRow
    dr.Item("claim_type") = cmbClaimtype.Text
    dr.Item("purpose_desc") = txtPurpDesc.Text
    dr.Item("currency") = cmbCurrency.Value
    dr.Item("amount") = txtAmmount.Text
    dr.Item("txtChangeCurrRate") = lblCurrencyrate.Text
    dr.Item("txtChangeConvertedRate") = lblconvertedRateMYR.Text
    dt.Rows.Add(dr)

    LoadGrid()

End Sub

Edit2: allow edits of two text box - save back to table.

So, just add this to the code:

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

    If Not IsPostBack Then

        CreateTable()
        LoadGrid()
        Session("dt") = dt

    Else
        ' restore table
        dt = Session("dt")
        ' restore grid to dt
        GridToTable
    End If

End Sub

Sub GridToTable()

    ' move any and all possile updates to grid back to our table dt

    For Each gRow As GridViewRow In grdNewClaim.Rows

        Dim OneRow As DataRow = dt.Rows(gRow.RowIndex)
        Dim txtCurrRate As TextBox = gRow.FindControl("txtCRateZoo")
        Dim txtConvertRate As TextBox = gRow.FindControl("txtConvertedRate")

        OneRow("txtChangeCurrRate") = txtCurrRate.Text
        OneRow("txtChangeConvertedRate") = txtConvertRate.Text

    Next

End Sub

What we do is send any changes back to the dt.

This means, that any button click etc on that page will shuffle gv back to dt.

This also means that if you have a button click to jump or move on to the next page/url, then session("dt") will have the correct data.

but, since we doing this on page load, then don't use a link button, or a button with post-back url to jump to the next page (just use regular button code behind, and say:

 Response.Redirect("url to next page to jump to")

So, with above, user can now freely modify the two columns, and they will be sent back to the dt.

This also means you can loop/process the dt in code.

Say we drop a button on the form, and then behind that button we do this:

Protected Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

    For Each OneRow As DataRow In dt.Rows

        Debug.Print(OneRow("currency"))
        Debug.Print(OneRow("txtChangeCurrRate"))
        ' etc . etc.
    Next

End Sub

So, we don't even have to hit the original grid, and it will be always updated in our session(). As such, then we could have a button "continue" to move on to the next page - as along as we follow above setup, then dt will always have the latest data and edits upon a post-back.

  • Related