Add (insert) new row textbox in grid view programmatically not showing - asp.net

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 :
So any idea why? Because if I change the textbox to <asp:BoundField/> it works just fine like this
[![enter image description here][2]][2]
EDIT : create another rows in gridview
My markup is exactly the same as you. So this is my code behind. This code works just fine, however the only problem is my textbox for first row went blank. The second row is alright.
NOTE : I didn't do this on page_load.
Private Sub LoadGrid()
grdNewClaim.DataSource = dtGrd
grdNewClaim.DataBind()
End Sub
Private Sub addClaimProgrammatically()
Dim dr As DataRow
If grdNewClaim.Rows.Count = 0 Then
dtGrd.Columns.Add("claim_type")
dtGrd.Columns.Add("purpose_desc")
dtGrd.Columns.Add("currency")
dtGrd.Columns.Add("amount")
dtGrd.Columns.Add("CurrencyRate")
dtGrd.Columns.Add("ConvertedRate")
dr = dtGrd.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("CurrencyRate") = lblCurrencyrate.Text
dr.Item("ConvertedRate") = lblconvertedRateMYR.Text
dtGrd.Rows.Add(dr)
ElseIf grdNewClaim.Rows.Count > 0 Then
dtGrd.Columns.Add("claim_type")
dtGrd.Columns.Add("purpose_desc")
dtGrd.Columns.Add("currency")
dtGrd.Columns.Add("amount")
dtGrd.Columns.Add("CurrencyRate")
dtGrd.Columns.Add("ConvertedRate")
For i = 0 To grdNewClaim.Rows.Count - 1
dr = dtGrd.NewRow
dr.Item("claim_type") = grdNewClaim.Rows(i).Cells(1).Text
dr.Item("purpose_desc") = grdNewClaim.Rows(i).Cells(2).Text
dr.Item("currency") = grdNewClaim.Rows(i).Cells(3).Text
dr.Item("amount") = grdNewClaim.Rows(i).Cells(4).Text
dr.Item("CurrencyRate") = grdNewClaim.Rows(i).Cells(5).Text
dr.Item("ConvertedRate") = grdNewClaim.Rows(i).Cells(6).Text
dtGrd.Rows.Add(dr)
Next
dr = dtGrd.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("CurrencyRate") = lblCurrencyrate.Text
dr.Item("ConvertedRate") = lblconvertedRateMYR.Text
dtGrd.Rows.Add(dr)
End If
LoadGrid()
End Sub
Protected Sub btnAddClaim_Click(sender As Object, e As EventArgs) Handles btnAddClaim.Click
addClaimProgrammatically()
End Sub
The values just went missing
Thank you very much for your time !

When you use a boundfield, it works because you CAN SPECIFY which column to display.
bound field only works due to this:
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 our dt will be always updated in our session(). So, we now can work with table in code - not have to use the grid. 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

asp.net get table cell text

I'm developping an asp.net Web application.
I have a table and I add rows/cells to the table through code :
<asp:Table ID="Table2" runat="server" Style="table-layout:auto;" GridLines="Both">
<asp:TableRow runat="server" Enabled="False" Font-Bold="True" HorizontalAlign="Center" VerticalAlign="Top" BackColor="#FF704C" ForeColor="Black">
<asp:TableCell runat="server">Famille</asp:TableCell>
<asp:TableCell runat="server">Editeur</asp:TableCell>
<asp:TableCell runat="server">Référence</asp:TableCell>
<asp:TableCell runat="server">Solutions</asp:TableCell>
<asp:TableCell runat="server">Nature</asp:TableCell>
<asp:TableCell runat="server">Unité</asp:TableCell>
<asp:TableCell runat="server">Usage</asp:TableCell>
<asp:TableCell runat="server">Version</asp:TableCell>
<asp:TableCell runat="server">PP net (€)</asp:TableCell>
<asp:TableCell runat="server">Quantité</asp:TableCell>
</asp:TableRow>
</asp:Table>
--
Dim tfp As New TextFieldParser(My.Settings.FilePath)
tfp.Delimiters = New String() {My.Settings.Delimiter}
tfp.TextFieldType = FieldType.Delimited
tfp.ReadLine() ' skip header
Dim Ligne As Integer = 0
While tfp.EndOfData = False
Dim fields = tfp.ReadFields()
Dim trow As New TableRow
Ligne = Ligne + 1
For i = 0 To 8
Dim tcell As New TableCell
tcell.Controls.Add(New LiteralControl(fields(i)))
trow.Cells.Add(tcell)
Next
Table2.Rows.Add(trow)
End While
Later in code, after the user click on a button, I want to get the text which is in the cell, but I always get an empty string.
MyCell = table2.rows(3).Cells(2)
? Mycell.text
""
How can I get the text which is inside the cell ?
Thank you
Ok, the main issue, is that the asp.net "table" has ONE huge big nasty issue.
Asp.net tables do NOT have viewstate nor persistence. So, in code when you add some rows, they are objects added - but NOT with viewstate.
So, your code would have to RE-RUN every time!!!!
In other words, if you run some code to add a row, you have to save that "list" or object of additions, and then on each page load - re-create, and re-add that data each time.
As a result, you are MUCH ,but I mean REALLY BEYOND WORLD poverty better off to use a control with persistence (viewstate) build in.
EVEN in that case where you want to persist the data, I STRONG suggest you persist ONLY the data table used (note how I said the data table - NOT the markup, nor the HTML markup table).
And we do not yet need to have a database to do this!!!
Of course I grasp this is just for learning, but at the end of the day? That data needs to be placed in a database. You then do the data adding, deleting, manipulation, processing against the database. If you need to show updated data as a result (say adding a new row to the database), YOU THEN RE-BIND the control on the form.
so, keep the concept of working with the data 100% separate from the control or so called UI (the web page).
Again, I 100% grasp the goal of learning, and starting out simple. The problem, is that eventually, that data WILL and NEEDS to be in a table. This will allow data base operations, or at the VERY least allow you to use code to add rows, reference a column etc.
so, I suggest you use a GridView, and THEN also create a data table (in code behind).
So, our markup now becomes this:
<asp:GridView ID="GridView1" runat="server" CssClass="table" Width="50%"
ShowHeaderWhenEmpty="true" HeaderStyle-BackColor="LightGray">
</asp:GridView>
<br />
<asp:Button ID="Button1" runat="server" Text="Add new row" CssClass="btn" />
And now our code to create the table, and also code for the add button.
We have this now:
Dim rstData As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' first page load - create a table,
' send to our grid
CreateTable
LoadGrid
Session("rstData") = rstData
Else
rstData = Session("rstData")
End If
End Sub
Sub CreateTable()
rstData.Columns.Add("Famille")
rstData.Columns.Add("Editeur")
rstData.Columns.Add("Référence")
rstData.Columns.Add("Solutions")
rstData.Columns.Add("Nature")
rstData.Columns.Add("Unité", GetType(Integer))
rstData.Columns.Add("Usage")
rstData.Columns.Add("Version", GetType(Double))
rstData.Columns.Add("PP Net(€)", GetType(Double))
rstData.Columns.Add("Quantité", GetType(Double))
End Sub
Sub LoadGrid()
GridView1.DataSource = rstData
GridView1.DataBind()
End Sub
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' add a new row to our table
Dim MyNewRow As DataRow = rstData.NewRow
MyNewRow("Famille") = "this is test" ' example refernce by colum name
MyNewRow(1) = "My Editeur" ' example refernce by colum index
rstData.Rows.Add(MyNewRow) ' send new row to the table
LoadGrid() ' re-display grid to show this new row
End Sub
And when I run above, click the button, I now see this:
Note how we had much less markup, but of course a bit of extra code. However, if that table comes from a database, then we did not even have the code to "create" the table, since in most cases, that table and data would be in a database.
Other advantages?
Well, I can now format the grid, increase column lengths, even drop in a image control, or whatever I like.
In above, I did let the grid load the data table, and format the column widths, but you will often of course want to control the column widths, settings, and even what kind of control to use here.
In fact, if you have a boatload of custom controls on the grid you want, then often I suggest using a ListView in place of GridView (the hard part and learning curve is to learn when and what control to use - you have so many to choose from!!!).
So, I suggest the above.
You can then say I want the 2nd row, and cell like this:
rstData.Rows(1).Item("Famile")
rstData.Rows(1).Item(0)
Again, you can reference column(s) by number (index) or by name.
And say I want even MORE control, then say I have a grid like this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Preview">
<ItemTemplate>
<asp:Image ID="Image2" runat="server" ImageUrl = '<%# Eval("ImagePath") %>' Width="140" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="View" CssClass="btn"
CommandArgument = '<%# Eval("ImagePath") %>' OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note how we now have AutoGenerateColumns = false. That's because I want to "control" each column such as width, etc. And I wanted a image control in that "table".
So, my code to load up the above is now this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGridF()
End If
End Sub
Sub LoadGridF()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * FROM Fighters", conn)
conn.Open()
Dim rstData = New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
And now I get this:

How to make fast row calculation in gridview asp.net

I am developing asp.net webform application with gridview control. I have grid control which is having more than 20 rows. Each rows having 4 columns like Ordered, Ex-Received, Current-Receiving and Pending. Here, Current-Receiving column having input box to enter the qty. Once entered the qty, Pending Columns will show the Pending qty in the corresponding row after calculate done (Pending Qty = Ordered - (Ex-Received + Current-Receiving) . And in footer sum of pending and sum of receiving qty will show. It working fine if i have 4 or 5 rows. If i have more than and above 15 rows, it takes time to calculate. Please find below my code which is written in current-receiving input box text_changed event. Any idea to make it faster ? In future, rows count will increase like 50 or more.
Dim textBox1 As TextBox = CType(sender, TextBox)
Dim dt As New DataTable
Dim RowIndex As Integer = CType(CType(sender, TextBox).NamingContainer, GridViewRow).RowIndex
Dim glblRcvdRolls As Label =grd.Rows(RowIndex).FindControl("lblRcvdRolls")
'
Dim glblOrdRolls As Label = grd.Rows(RowIndex).FindControl("lblOrdRolls")
Dim glblPendWt As Label = grd.Rows(RowIndex).FindControl("lblPendWt")
If textBox1.Text = "" Then textBox1.Text = 0
If glblRcvdRolls.Text = "" Then glblRcvdRolls.Text = 0
If glblOrdRolls.Text = "" Then glblOrdRolls.Text = 0
'Each Row Calculations
glblPendWt.Text = Convert.ToInt32(glblOrdRolls.Text) - (Convert.ToInt32(textBox1.Text) + Convert.ToInt32(glblRcvdRolls.Text))
If Convert.ToInt32(glblPendWt.Text) < 0 Then
glblPendWt.ForeColor = System.Drawing.Color.Yellow
Else
glblPendWt.ForeColor = System.Drawing.Color.White
End If
' Total Row Calculations
Dim mPendQty As Double = ViewState("PndQty")
Dim mRcvdQty As Double = ViewState("RcvdQty")
If IsNumeric(glblPendWt.Text) Then mPendQty += Convert.ToDouble(glblPendWt.Text)
If IsNumeric(textBox1.Text) Then mRcvdQty += Convert.ToDouble(textBox1.Text)
ViewState("PndQty") = mPendQty
ViewState("RcvdQty") = mRcvdQty
grd.FooterRow.Cells(5).Text = mRcvdQty
grd.FooterRow.Cells(6).Text = mPendQty
'Setfocus after postback - otherwise focus will set somewhere in the form.
If RowIndex <=grd.Rows.Count Then
Dim grdNRText As TextBox = grd.Rows(RowIndex + 1).FindControl("txtRcvdQty")
'grdNRText.Focus()
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "focus", "document.getElementById('" + grdNRText.ClientID + "').focus();document.getElementById('" + grdNRText.ClientID + "').select();", True)
Else
'btnInward.Focus()
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "focus", "document.getElementById('" + btnInward.ClientID + "').focus();document.getElementById('" + btnInward.ClientID + "').select();", True)
End If
Exit Sub
I am betting that your main issue and problem is the the code you have, but in fact that on page load, you re-binding the grid.
The fact that you started adopting JavaScript to set the focus is the tell tell sign here.
You should not in ANY case re-bind the grid each time. Remember, for ANY post-back, the page load event will fire. And there should be no need to persist the two total values you have.
So, if you have a data source on the page - I would remove it - load the GV in code.
You should be able to use the server side .Focus() method of the control (and I see at one time you had or were attempting to use that, and now are using JavaScript. You should NOT have to do that.
So, in the last 100, or in fact 200 web pages I had made, the page load event MUST check the isPostBack, and ONLY ONE time do you run ANY code, and ANY code to bind.
Here is a example grid, and I have TWO columns that can post back (text boxes), one is Qty, and the other is Price (I used Qty in code - it was displaed as nights).
Take a close look. If you ahve any combo box binding code - again, it should ONLY run one time - in row data bound event.
And if you want, you can drop the whole thing into a update panel - but it not required.
So, say this markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID"
ShowFooter="True" CssClass="table">
<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="Nights" SortExpression="Nights">
<ItemTemplate>
<asp:TextBox ID="txtNights" runat="server" Text='<%# Bind("Nights") %>'
OnTextChanged="txtNights_TextChanged" AutoPostBack="true"
TextMode="Number">
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" SortExpression="Price">
<ItemTemplate>
<asp:TextBox ID="txtPrice" runat="server" Text='<%# Bind("Price") %>'
OnTextChanged="txtPrice_TextChanged" AutoPostBack="true"
TextMode="Number"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Tamount"
ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" >
<ItemTemplate>
<asp:Label ID="lblAmount" runat="server" Text='<%# Bind("Tamount") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate >
<asp:Label ID="LblTotal" runat="server" Text="0"></asp:Label>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Ok, now our code - remember - ONLY bind the GV ONE time, NEVER again.
So the grid looks like this:
Our code to load the Grid
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(
"SELECT top 10 * FROM tblHotels WHERE Description is not null ORDER BY HOtelName", conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
SumRows()
End Using
End Using
End Sub
Ok, that's it - don't re- bind the gv.
Now, here are the two code stubs for the two text boxes (qty, price), and auto postback = true.
Protected Sub txtNights_TextChanged(sender As Object, e As EventArgs)
Dim tQty As TextBox = sender
Dim gRow As GridViewRow = tQty.NamingContainer
Call RowCalc(gRow)
' we were in Qty control - set focus to next (price) control
Dim tPrice As TextBox = gRow.FindControl("txtPrice")
tPrice.Focus()
SumRows()
End Sub
Protected Sub txtPrice_TextChanged(sender As Object, e As EventArgs)
Dim tPrice As TextBox = sender
Dim gRow As GridViewRow = tPrice.NamingContainer
Call RowCalc(gRow)
SumRows()
' we in Price - we jump to next row below (or cycle to first row)
Dim gRowNext As GridViewRow = Nothing
If gRow.RowIndex + 1 < GridView1.Rows.Count Then
gRowNext = GridView1.Rows(gRow.RowIndex + 1)
Else
' jump to top row
gRowNext = GridView1.Rows(0)
End If
Dim tQty As TextBox = gRowNext.FindControl("txtNights")
tQty.Focus()
End Sub
Sub RowCalc(gRow As GridViewRow)
Dim tQty As TextBox = gRow.FindControl("txtNights")
Dim tPrice As TextBox = gRow.FindControl("txtPrice")
Dim lblAmount As Label = gRow.FindControl("lblAmount")
lblAmount.Text = Nz(tQty.Text, 0) * Nz(tPrice.Text, 0)
End Sub
In fact, we have MORE code to set the focus to the next control then quite much the actuall work.
And since I had TWO controls that can change, then I built a common routine for both controls to call (RowCalc).
Sub RowCalc(gRow As GridViewRow)
Dim tQty As TextBox = gRow.FindControl("txtNights")
Dim tPrice As TextBox = gRow.FindControl("txtPrice")
Dim lblAmount As Label = gRow.FindControl("lblAmount")
lblAmount.Text = Nz(tQty.Text, 0) * Nz(tPrice.Text, 0)
End Sub
And, of course the code to sum the rows - total into footer is this:
But NOTE carefully - I don't have to persist that total value - it will and should survive post-backs.
Sub SumRows()
' sum value - set footer total value
Dim MyTotal As Double
For Each gRow As GridViewRow In GridView1.Rows
Dim lblAmount As Label = gRow.FindControl("lblAmount")
MyTotal += Nz(lblAmount.Text, 0)
Next
Dim lblTotal As Label = GridView1.FooterRow.FindControl("lblTotal")
lblTotal.Text = MyTotal
End Sub
And I used a nz() function - since I did a abone head move, and allowed nulls as the default for those number rows - not 0.
Not a huge deal, but I have this for nz()
Public Function Nz(ByVal Value As Object, Optional ByVal MyDefault As Object = 0) As Object
If Value Is Nothing OrElse IsDBNull(Value) OrElse (Value.ToString = "") Then
Return MyDefault
Else
Return Value
End If
End Function
Now, with 20, or even 30 rows - it is butter smooth, and I can't tell difference speed wise with 5 rows, or 30. And you should find the same results.
So, my spider sense suggests that you have some wonkey code running each time on page load. Keep in mind that any button, any post-back WILL run the page load event each time.
So, ensure that you only EVER load up the GV one time, and don't re-bind, as that will for sure make this run slow.
Try some of the above ideas and code - but do check/address the first page load and only load/bind the GV one time.
Edit: Don't allow nor use a post back - do this 100% client side
So, of course for really amazing performance, the solution of course is to do this 100% client side code - in the browser. This will be instant, and better yet, no post back required at all.
So, dump the auto post backs, and now our Qty, and Price controls look like this - with a js code on change event.
<asp:TemplateField HeaderText="Nights">
<ItemTemplate>
<asp:TextBox ID="txtNights" runat="server" Text='<%# Bind("Nights") %>'
OnTextChanged="txtNights_TextChanged" onchange="myjscalc(this,'txtNights')"
TextMode="Number">
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" SortExpression="Price">
<ItemTemplate>
<asp:TextBox ID="txtPrice" runat="server" Text='<%# Bind("Price") %>'
OnTextChanged="txtPrice_TextChanged" onchange="myjscalc(this,'txtPrice')"
TextMode="Number"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Tamount"
ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" >
<ItemTemplate>
<asp:Label ID="lblAmount" runat="server" Text='<%# Bind("Tamount") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate >
<asp:Label ID="LblTotal" runat="server" Text="0"></asp:Label>
</FooterTemplate>
</asp:TemplateField>
And now the script for this is this:
<script>
function myjscalc(ctl, tid) {
var Qty = $('#' + ctl.id.replace(tid, 'txtNights'))
var Price = $('#' + ctl.id.replace(tid, 'txtPrice'))
var tAmount = $('#' + ctl.id.replace(tid, 'lblAmount'))
var n = Qty.val() * Price.val()
tAmount.text(n.toFixed(2))
// now total
var MyTotal = 0.0
var rowCount = $("#<%=GridView1.ClientID %> tr").length;
rowCount = rowCount - 2 // remove header row, and footer from count
for (var iRow = 0; iRow < rowCount; iRow++) {
tAmount = $('#GridView1_lblAmount_' + iRow)
MyTotal = MyTotal + + tAmount.text()
}
$('#GridView1_LblTotal').text(MyTotal.toFixed(2))
}
</script>
So, elimination of the post-back and doing this 100% client side ALSO fixes the focus issue. And any change will update instant - including the final total.

How to verify all button in approved in gridview while click on other button that is outside the gridview

I want to add one button in vb.net e.g bulk approval outside the gridview in another table. While clicking on that button I.e is bulk approval.. all verify button are verified in gridview in every row... and changed into verified.
Ok, so we have some kind of grid, and some kind of approve button for each row.
Ok, so we have some typical markup like this:
This is a grid (hotel bookings), and then a the "administrator" has to approve each one.
So, say some markup like this - nothing special:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" ItemStyle-Width="180" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Approved" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:CheckBox ID="chkApproved" runat="server" Checked='<%# Eval("Approved") %>'
CssClass="bigcheck" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="By">
<ItemTemplate>
<asp:Label ID="lblApBy" runat="server" Text='<%# Eval("ApprovedBy") %>' ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Approve">
<ItemTemplate>
<asp:Button ID="cmdApprove" runat="server" Text="Approve" CssClass="btn"
onclick="cmdApprove_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div style="float:right">
<asp:Button ID="cmdApproveAll" runat="server" Text="Approve All" CssClass="btn" />
And our code to load the grid:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String = "SELECT TOP 6 * from tblHotels"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstData
GridView1.DataBind()
End Using
End Using
End Sub
And we now have this:
Ok, so we have a plane jane button on each row. The code to approve a row is this code:
(a simple standard button in the grid view - button click)
Protected Sub cmdApprove_Click(sender As Object, e As EventArgs)
' approve one row
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Call ApproveGRow(gRow)
End Sub
Sub ApproveGRow(gRow As GridViewRow)
' set checkbox = checked
Dim ckApprove As CheckBox = gRow.FindControl("chkApproved")
ckApprove.Checked = True
Dim lBy As Label = gRow.FindControl("lblApBy")
lBy.Text = UserInitials
' Get data base pk id
Dim pkID As Integer
pkID = GridView1.DataKeys(gRow.RowIndex).Item("ID")
' Now udpate database
Dim strSQL As String =
"UPDATE tblHotels SET Approved = 1, ApprovedBy = #Initials WHERE ID = #ID"
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
cmdSQL.Parameters.Add("#Initials", SqlDbType.NVarChar).Value = UserInitials
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = pkID
cmdSQL.ExecuteNonQuery()
End Using
End Using
End Sub
So, on a button click, we get the current row click, and then call our approve routine that accepts grid ro
So, if I click say on the second row, we see this:
However, what about do the WHOLE gird, with one button, and approve all rows?
Well, the button for the approve all looks like this:
Protected Sub cmdApproveAll_Click(sender As Object, e As EventArgs) Handles cmdApproveAll.Click
For Each gRow In GridView1.Rows
Call ApproveGRow(gRow)
Next
End Sub
And if I click on it, then I get this:

copy row from asp.net gridview to new page using VB

I am trying to copy a row from a gridview to be displayed on a new page through a button in one of the columns in the gridview. I have my gridview populated from an Access database that is linked to my project. I have tried several different things, but nothing will display the row information when the project is ran. The current code I am trying from the actual dataview is:
Example 1a
<asp:GridView ID="Grid1" runat="server" Width ="90%" AutoGenerateColumns="false" OnRowDeleting="Grid1_RowDeleting" DataKeyNames="Title">
<Columns>
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="Console" HeaderText="Console" />
<asp:BoundField DataField="Year_Released" HeaderText="Year Released" />
<asp:BoundField DataField="ESRB" HeaderText="ESRB Rating" />
<asp:BoundField DataField="Score" HeaderText="Personal Score" />
<asp:BoundField DataField="Publisher" HeaderText="Publisher" />
<asp:BoundField DataField="Developer" HeaderText="Developer" />
<asp:BoundField DataField="Genre" HeaderText="Genre" />
<asp:BoundField DataField="Purchase" HeaderText="Purchase Date" />
<asp:TemplateField ItemStyle-Width="7%" ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="lnkDetails" runat="server" Text="View" PostBackUrl='<%# "~/ViewDetails.aspx?RowIndex=" & Container.DataItemIndex %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And the codebehind code on the page where I am trying to have the code be displayed is:
Example 1b
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Me.Page.PreviousPage IsNot Nothing Then
Dim rowIndex As Integer = Integer.Parse(Request.QueryString("RowIndex"))
Dim GridView1 As GridView = DirectCast(Me.Page.PreviousPage.FindControl("Grid1"), GridView)
Dim row As GridViewRow = GridView1.Rows(rowIndex)
lblTitle.Text = row.Cells(0).Text
lblConsole.Text = row.Cells(1).Text
lblYear.Text = row.Cells(2).Text
lblESRB.Text = row.Cells(3).Text
lblScore.Text = row.Cells(4).Text
lblPublisher.Text = row.Cells(5).Text
lblDeveloper.Text = row.Cells(6).Text
lblGenre.Text = row.Cells(7).Text
lblPurchase.Text = row.Cells(8).Text
End If
End Sub
I have also tried another set of code where the button on the gridview was:
Example 2a
<asp:Button ID="btnLink" runat="server" Text="View Details" PostBackUrl='<%# Eval("Title", "~/ViewDetails.aspx?Id={0}") %>'/>
Where the codebehind code is:
Example 2b
Protected Sub Page_Load(sender As Object, e As EventArgs)
If Not IsPostBack Then
Dim GameTitle As String = Request.QueryString("Id")
Dim connString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;" + "DATA SOURCE=" + Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "App_Data" + "db1.accdb")
Using connection As New OleDbConnection(connString)
connection.Open()
Dim reader As OleDbDataReader = Nothing
Dim command As New OleDbCommand((Convert.ToString("SELECT * from [Video_Games] WHERE Title='") & GameTitle) + "'", connection)
reader = command.ExecuteReader()
While reader.Read()
lblTitle.Text = reader(0).ToString()
lblConsole.Text = reader(1).ToString()
lblYear.Text = reader(2).ToString()
lblESRB.Text = reader(3).ToString()
lblScore.Text = reader(4).ToString()
lblPublisher.Text = reader(5).ToString()
lblDeveloper.Text = reader(6).ToString()
lblGenre.Text = reader(7).ToString()
lblPurchase.Text = Convert.ToDateTime(reader(8).ToString()).ToShortDateString()
End While
End Using
End If
End Sub
End Class
I have tried making variations of both, mainly the second, but whatever I try the labels are not populated with the row information. Any assistance would be appreciated, and I can post any other code needed, like how I populated the gridview. Thank you.
It was as simple as changing the AutoEventWireup to "true" in my .aspx file.

Displaying different pictures in GridView depending on the data?

I am creating a WEB report in Visual Studio 2010 in VB.net. The report needs to display a table (please see the attached image). I am thinking to use the GridView component which i think it's the most appropriate one to choose. In the database there are students' data and marks. I can't alter the database in any way and i have to use Visual Studio 2010 with VB.
What i need to do is to show 3 different pictures(for example) depend on the student's marks. I got the pictures file in PNGs but this can be flexible.For example, over 70 will be a Smile picture. over 60 will be the Normal face. and over 40 will be the picture with no smile. I bit difficult for me to explain but i hope u get my point.
So pls advice me how can i achieve this. I am quite a newbie to this pls put as detail as you can. if there is a choice between client and server side script, i prefer server side script. Data source can be flexible (sql, or linq or anything).
You should use RowDataBound to bind data to controls in your GridView.
Following is a complete sample with aspx and codebehind(says more than thousand words):
<style type="text/css">
.GridViewRowStyle
{
background-color: #A0CFEC;
color:Blue;
}
.GridViewAlternatingRowStyle
{
background-color:White;
color:#15317E;
}
.GridViewHeaderStyle
{
background-color:White;
color:#15317E;
}
</style>
<asp:GridView ID="GridStudents" AutoGenerateColumns="false" GridLines="None" runat="server">
<RowStyle CssClass="GridViewRowStyle" />
<AlternatingRowStyle CssClass="GridViewAlternatingRowStyle" />
<HeaderStyle CssClass="GridViewHeaderStyle" />
<Columns>
<asp:TemplateField HeaderText="Student">
<ItemTemplate>
<asp:label runat="server" ID="LblStudent" Text='<%# Bind("Student") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Mark">
<ItemTemplate>
<asp:label runat="server" ID="LblMark" Text='<%# Bind("Mark") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Image runat="server" ID="ImgSmiley" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Codebehind(with sample-data):
Private Sub GridStudents_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridStudents.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim row = DirectCast(e.Row.DataItem, DataRowView)
Dim ImgSmiley = DirectCast(e.Row.FindControl("ImgSmiley"), Image)
Select Case DirectCast(row("Mark"), Int32)
Case Is < 50
ImgSmiley.ImageUrl = "~/Images/Smiley_Grim.png"
ImgSmiley.ToolTip = "bad"
Case Is < 70
ImgSmiley.ImageUrl = "~/Images/Smiley_Def.png"
ImgSmiley.ToolTip = "ok"
Case Else
ImgSmiley.ImageUrl = "~/Images/Smiley_Laugh.png"
ImgSmiley.ToolTip = "fine"
End Select
End Select
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
BindData()
End If
End Sub
Private Sub BindData()
Dim tblStudent As New DataTable("Students")
Dim colStudent = New DataColumn("Student", GetType(String))
Dim colMark As New DataColumn("Mark", GetType(Int32))
tblStudent.Columns.Add(colStudent)
tblStudent.Columns.Add(colMark)
Dim newRow = tblStudent.NewRow
newRow("Student") = "Tom"
newRow("Mark") = 70
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Bob"
newRow("Mark") = 40
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Danny"
newRow("Mark") = 60
tblStudent.Rows.Add(newRow)
newRow = tblStudent.NewRow
newRow("Student") = "Sussie"
newRow("Mark") = 40
tblStudent.Rows.Add(newRow)
GridStudents.DataSource = tblStudent
GridStudents.DataBind()
End Sub

Resources