如何在gridview asp.net中进行快速行计算

发布于 2025-01-17 01:44:34 字数 2420 浏览 3 评论 0原文

我正在使用 gridview 控件开发 ASP.NET WebForm 应用程序。我有超过 20 行的网格控件。每行有 4 列,例如已订购、已收到、当前正在接收和待处理。这里,当前接收列有输入框用于输入数量。输入数量后,待处理列将在计算完成后在相应行中显示待处理数量(待处理数量 = 已订购 - (Ex-Received + Current-Receiving) 。并且在页脚中将显示待处理数量和接收数量总和。如果我有 4 或 5 行,则工作正常。如果我有超过 15 行,则需要时间来计算,请在当前接收输入框 text_changed 事件中找到我的代码。有办法让它更快吗?将来行数会增加到 50 或更多。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

千纸鹤带着心事 2025-01-24 01:44:34

我敢打赌,您的主要问题和问题是您拥有的代码,但事实上,在页面加载时,您重新绑定了网格。

您开始采用 JavaScript 来设置焦点的事实就是这里的告诉标志。

在任何情况下,您都不应该每次都重新绑定网格。请记住,对于任何回发,页面加载事件都会触发。并且不需要保留您拥有的两个总值。

因此,如果页面上有数据源 - 我会删除它 - 在代码中加载 GV。

您应该能够使用控件的服务器端 .Focus() 方法(我看到您曾经或正在尝试使用该方法,现在正在使用 JavaScript。您不必这样做。

所以,在我制作的最后 100 个网页,或者实际上是 200 个网页,页面加载事件必须检查 isPostBack,并且只有一次运行任何代码以及要绑定的任何代码

这是一个示例网格,我有两个。可以回发的列(文本框),一个是数量,另一个是价格(我在代码中使用了数量 - 它显示为夜晚)

如果您有任何组合框绑定代码 - 再次,它。应该只运行一次 - 在行数据绑定事件中,

如果您愿意,您可以将整个事件放入更新面板中 - 但不是必需的,

所以,说这个标记:

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

好的,现在我们的代码 - 记住 - 仅绑定GV 一次,从来没有所以

网格看起来像这样:

在此处输入图像描述

我们加载网格的代码

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

好的,就是这样 - 不要重新绑定 gv。

现在,这是两个文本框(数量、价格)的两个代码存根,并且自动回发 = 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

事实上,我们有更多的代码将焦点设置到下一个控件,而不是实际的工作。

由于我有两个可以更改的控件,因此我为两个控件构建了一个通用例程来调用(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

当然,对行进行求和的代码 - 总计到页脚中是这样的:

但请注意 - 我不必保留该总值 - 它将并且应该在回发中幸存下来。

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

我使用了 nz() 函数 - 因为我做了一个严重的头部移动,并允许空值作为这些数字行的默认值 - 而不是 0。

没什么大不了的,但我

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

现在有 nz() 这个,有 20,或者即使是 30 行 - 它也很光滑,我无法区分 5 行或 30 行的速度差异。您应该会发现相同的结果。

因此,我的蜘蛛感知表明,每次页面加载时都会运行一些不稳定的代码。请记住,任何按钮、任何回发每次都会运行页面加载事件。

因此,请确保您只加载 GV 一次,并且不要重新绑定,因为这肯定会使运行速度变慢。

尝试上面的一些想法和代码 - 但要检查/解决第一页加载并且仅加载/绑定 GV 一次。

编辑:不允许或使用回发 - 执行此 100% 客户端

因此,当然,为了获得真正惊人的性能,解决方案当然是执行此 100% 客户端代码 - 在浏览器中。这将是即时的,更好的是,根本不需要回发。

因此,转储自动回发,现在我们的数量和价格控件看起来像这样 - 带有关于更改事件的 js 代码。

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

现在的脚本是这样的:

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

因此,消除回发并在 100% 客户端执行此操作也可以解决焦点问题。任何更改都会立即更新 - 包括最终总数。

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:

enter image description here

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文