简体   繁体   中英

How to get any column value of selected row with checkbox in gridview without iterating?

I have a gridview which gets its data from a database in SQL Server 2014. The gridview has four columns from database ( p_id, p_image, p_name, p_price ) and followed by 2 additional columns, a dropdownlist and a checkbox and there is a textbox below the gridview.

My requirement is when I check the check box, the value from the price column of the selected row is to be multiplied with the value from the dropdownlist control and displayed in the textbox.

And again when I check another checkbox, I want the value of price column of this selected row to be multiplied with its dropdownlist value and added to the previous value of the textbox and displayed in the same textbox. The code I have used for that is :

public double sum = 0 ; 

protected void chkSelect_CheckedChanged(object sender, EventArgs e)
{
        foreach (GridViewRow row in gvPackaged.Rows)
        {
            CheckBox chk = (row.Cells[5].FindControl("chkSelect") as CheckBox);
            DropDownList ddl = (row.Cells[4].FindControl("ddlSelect") as DropDownList);
            if (row != null && chk != null)
            {
                if (chk.Checked)
                {
                    double quantity = Convert.ToDouble(ddl.Text);
                    double price = Convert.ToDouble(row.Cells[3].Text);
                    sum += (price * quantity);
                    tbTotal.Text = Convert.ToString(sum);
                }
            }
        }
}

The code is working but the problem is every time I check the checkbox, the onCheckedChanged method is called and it will iterate through all the rows in the gridview and then displays the value in the textbox which makes the process considerably slow.

I have searched in many forums including this one and found only this approach is being used in almost every question and answer.

The only other approach is :

GridViewRow row = myGridview.SelectedRow;

instead of

foreach (GridViewRow row in myGridview.Rows)

and hence I used that in my code :

public double sum = 0 ; 

protected void chkSelect_CheckedChanged(object sender, EventArgs e)
{
        GridViewRow row = gvPackaged.SelectedRow;
        CheckBox chk = (row.Cells[5].FindControl("chkSelect") as CheckBox);         //HERE
        DropDownList ddl = (row.Cells[4].FindControl("ddlSelect") as DropDownList);

        if (row != null && chk != null)
        {
            if (chk.Checked)
            {
                double quantity = Convert.ToDouble(ddl.Text);
                double price = Convert.ToDouble(row.Cells[3].Text);
                sum += (price * quantity);
                tbTotal.Text = Convert.ToString(sum);
            }
        }
}

And then this error occurred in the above code on the //HERE line:

NullReferenceException

which means that exception occurred with the row var in the line above, and

Object reference not set to an instance of an object.

Again I searched for it and found it to be a general exception and did not find a sol specific to my problem.

Can anyone PLEASE help me to retrieve the current selected row into the row variable so that I can perform calculations using that row directly without having to use loops and iterate.

Try this:

GridViewRow row=(sender as CheckBox).Parent.Parent as GridViewRow;

or this:

CheckBox cb = (CheckBox)sender;
GridViewRow row = (GridViewRow)cb.NamingContainer;
if (row != null)
{
   ...
}

By default, interactive server controls embedded in a GridView (Buttons, DDL's) can trigger a postback. If you enable a GridView row selection that too will cause a postback due to event bubbling.

Do you need all those postbacks? Generally speaking...probably not unless you're doing something in the code behind that alters the GridView contents

If each row of your GridView has a ddl which, on selection, is to be multiplied by a price on the same row and the textbox positioned after the grid is to hold an accumulation, you can do all this clientside very fast with a very small bit of jquery, or a slightly larger bit of javascript.

Consider this GridView Markup:

    <asp:GridView ID="GridView1" runat="server" 
      ClientIDMode="Predictable"
      DataSourceID="SqlDataSource1" >
      <Columns>
        <asp:BoundField DataField="p_price" HeaderText="p_price" SortExpression="p_price"></asp:BoundField>
        <asp:TemplateField>
          <ItemTemplate>
            <div class="parent-div">
              <input type="checkbox" ID="CheckBox1" runat="server" />
              <asp:DropDownList ID="ddl_qty" runat="server" AutoPostBack="false">
                <asp:ListItem Text="1" Value="1"></asp:ListItem>
                <asp:ListItem Text="2" Value="2"></asp:ListItem>
                <asp:ListItem Text="3" Value="3"></asp:ListItem>
              </asp:DropDownList>
            </div>
          </ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>

    <asp:TextBox ID="tbxTotal" runat="server" 
        ClientIDMode="Static"></asp:TextBox>

And this RowDataBound event in the code behind, Sorry for the VB:

    Private Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
      If e.Row.RowType = DataControlRowType.DataRow Then
        Dim drv As DataRowView = e.Row.DataItem

        Dim ddl_qty As DropDownList = e.Row.FindControl("ddl_qty")
        ddl_qty.Attributes("data-associated-price") = drv("p_price")

        Dim CheckBox1 As HtmlInputCheckBox = e.Row.FindControl("CheckBox1")
        CheckBox1.Attributes("data-associated-ddl") = String.Format("#{0}", ddl_qty.ClientID)
        CheckBox1.Attributes("onclick") = "CalculateTotal()"
      End If
    End Sub

Here is the client side Jquery to do the calculation

  function CalculateTotal() {
    var total = 0.0;

    $(".parent-div").each(function(i, e) {
      var $cbx = $(this).find("input:checkbox");

      if ($cbx.is(":checked")) {
        var ddl_id = $cbx.attr("data-associated-ddl")
        var $ddl = $(ddl_id);
        var p = parseFloat($ddl.attr("data-associated-price"));
        var q = parseFloat($ddl.val());
        total += (p * q);
      }
    });

    $('#tbxTotal').val(total);
  }

In this snippet the html is generated by the above code behind and note the jquery that does the calculation. Be aware I'm not recalculating on select change but that can easily be added as well in the code behind.

 function CalculateTotal() { var total = 0.0; $(".parent-div").each(function(i, e) { var $cbx = $(this).find("input:checkbox"); if ($cbx.is(":checked")) { var ddl_id = $cbx.attr("data-associated-ddl") var $ddl = $(ddl_id); var p = parseFloat($ddl.attr("data-associated-price")); var q = parseFloat($ddl.val()); total += (p * q); } }); $('#tbxTotal').val(total); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <table cellspacing="0" rules="all" border="1" id="cphMain_GridView1" style="border-collapse:collapse;"> <tbody> <tr> <th scope="col">p_price</th> <th scope="col">&nbsp;</th> </tr> <tr> <td>10.000000</td> <td> <div class="parent-div"> <input name="ctl00$cphMain$GridView1$ctl02$CheckBox1" type="checkbox" id="cphMain_GridView1_CheckBox1_0" data-associated-ddl="#cphMain_GridView1_ddl_qty_0" onclick="CalculateTotal()"> <select name="ctl00$cphMain$GridView1$ctl02$ddl_qty" id="cphMain_GridView1_ddl_qty_0" data-associated-price="10.000000"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </div> </td> </tr> <tr> <td>10.220000</td> <td> <div class="parent-div"> <input name="ctl00$cphMain$GridView1$ctl03$CheckBox1" type="checkbox" id="cphMain_GridView1_CheckBox1_1" data-associated-ddl="#cphMain_GridView1_ddl_qty_1" onclick="CalculateTotal()"> <select name="ctl00$cphMain$GridView1$ctl03$ddl_qty" id="cphMain_GridView1_ddl_qty_1" data-associated-price="10.220000"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </div> </td> </tr> <tr> <td>10.480000</td> <td> <div class="parent-div"> <input name="ctl00$cphMain$GridView1$ctl04$CheckBox1" type="checkbox" id="cphMain_GridView1_CheckBox1_2" data-associated-ddl="#cphMain_GridView1_ddl_qty_2" onclick="CalculateTotal()"> <select name="ctl00$cphMain$GridView1$ctl04$ddl_qty" id="cphMain_GridView1_ddl_qty_2" data-associated-price="10.480000"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </div> </td> </tr> </tbody> </table> <input name="ctl00$cphMain$tbxTotal" type="text" id="tbxTotal"> 

All the calculating is done in on the clientside and you can have one button to postback when all is done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM