Reputation: 87
I have a gridview having a textbox and a checkbox.when the checkbox is checked,a value will be populated into the textbox which a user may alter the value.
Here is the code for the gridview
<asp:GridView ID="gvPayment" runat ="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="Vertical" Width="100%" ShowFooter="true" CssClass="jumbSize1" OnRowDataBound="gvPayment_RowDataBound" AllowPaging="true" PageSize="5" OnPageIndexChanging="gvPayment_PageIndexChanging" >
<Columns>
<asp:TemplateField HeaderStyle-Width="5%">
<ItemTemplate>
<asp:CheckBox ID="chkSelect" runat="server" CssClass="checkbox" OnCheckedChanged="chkSelect_CheckedChanged" AutoPostBack="true" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="TRANSACTION DATE" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:Label ID="SalesDate" runat="server" Text='<%#Eval("Date", "{0:dd/MM/yyyy}") %>' />
</ItemTemplate>
<FooterTemplate>
<asp:Button ID="Submit" Text="Submit" runat="server" OnClick="Submit_Click" CssClass="btn btn-primary" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Sales Code" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:Label ID="SalesCode" runat="server" Text='<%#Eval("SALES_CODE") %>' />
</ItemTemplate>
<FooterTemplate>
<div style="padding: 0 0 5px 0;">
<asp:Label Text="Page Totals" runat="server" align="right" />
</div>
<div>
<asp:Label Text="Grand Totals" runat="server" align="right" />
</div>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ACTUAL SALE" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:Label ID="ActualSales" runat="server" Text='<%#Eval("ACTUAL", "{0:N2}") %>' />
</ItemTemplate>
<FooterTemplate>
<div style="padding: 0 0 5px 0;">
<asp:Label ID="PageActual" runat="server" align="right" />
</div>
<div>
<asp:Label ID="GrandActual" runat="server" align="right" />
</div>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ADVANCE" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:Label ID="AdvPay" runat="server" Text='<%#Eval("ADVANCE", "{0:N2}") %>' />
</ItemTemplate>
<FooterTemplate>
<div style="padding: 0 0 5px 0;">
<asp:Label ID="PageAdvance" runat="server" align="left" />
</div>
<div>
<asp:Label ID="GrandAdvance" runat="server" align="left" />
</div>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="AMOUNT DUE" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:Label ID="AmtDue" runat="server" Text='<%#Eval("DUE", "{0:N2}") %>' />
</ItemTemplate>
<FooterTemplate>
<div style="padding: 0 0 5px 0;">
<asp:Label ID="PageDue" runat="server" align="left" />
</div>
<div>
<asp:Label ID="GrandDue" runat="server" align="left" />
</div>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="AMOUNT PAID" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:TextBox ID="AmtPaid" runat="server" CssClass="form-control CapLock" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="#4870BE" ForeColor="#FFFFFF" />
<FooterStyle BackColor="#76543c" ForeColor="#FFFFFF" Font-Bold="true" />
<HeaderStyle BackColor="#76543c" ForeColor="#FFFFFF" Font-Bold="true" />
<PagerSettings Mode="NextPrevious" NextPageText="Next &gt;&gt;" PreviousPageText="Prev &lt;&lt;" />
<PagerStyle BackColor="#76543c" ForeColor="#FFFFFF" HorizontalAlign="Center" />
<RowStyle BackColor="#EFF3FB" /></asp:Gridview>
Here is the code to bind gridview to data source and get the grand totals in viewstate
private void GetCustomer()
{
dt = new DataTable();
try
{
using (con = new SqlConnection(conString))
{
using (cmd = con.CreateCommand())
{
string query = @"dbo.sp_get_sales";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = query;
cmd.Parameters.AddWithValue("@ID", CustInfo.SelectedValue);
con.Open();
da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(dt);
//CALCULATE THE TOTAL AMOUNTS AND HOLD THE VALUE IN A "VIEWSTATE"
ViewState["TotalActual"] = null;
if (ViewState["TotalActual"] == null)
{
Decimal dActual = 0;
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
dActual += dt.Rows[i].Field<Decimal>("ACTUAL");
}
ViewState["TotalActual"] = dActual.ToString("N2");
}
ViewState["TotalAdvance"] = null;
if (ViewState["TotalAdvance"] == null)
{
Decimal dAdvance = 0;
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
dAdvance += dt.Rows[i].Field<Decimal>("ADVANCE");
}
ViewState["TotalAdvance"] = dAdvance.ToString("N2");
}
ViewState["TotalDue"] = null;
if (ViewState["TotalDue"] == null)
{
Decimal dDue = 0;
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
dDue += dt.Rows[i].Field<Decimal>("DUE");
}
ViewState["TotalDue"] = dDue.ToString("N2");
}
}
//BIND QUERY RESULT WITH THE GRIDVIEW
gvPayment.DataSource = dt;
gvPayment.DataBind();
}
}
catch (Exception ex)
{
ErrorMessage.Text = "An error occured: " + ex.Message;
}
finally
{
con.Close();
con.Dispose();
}
foreach (GridViewRow row in gvPayment.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
TextBox AmtPaid = (TextBox)row.FindControl("AmtPaid");
AmtPaid.Attributes.Add("readonly", "readonly");
}
}
}
Here is the code to enable and populate textbox on check changed event
protected void chkSelect_CheckedChanged(object sender, EventArgs e)
{
GridViewRow row = ((GridViewRow)((CheckBox)sender).NamingContainer);
int index = row.RowIndex;
CheckBox chkSelect = (CheckBox)gvPayment.Rows[index].FindControl("chkSelect");
TextBox AmtPaid = (TextBox)gvPayment.Rows[index].FindControl("AmtPaid");
Label AmtDue = (Label)gvPayment.Rows[index].FindControl("AmtDue");
if (chkSelect.Checked && chkSelect != null)
{
AmtPaid.Text = AmtDue.Text.Replace(",", "");
AmtPaid.Attributes.Remove("readonly");
}
else
{
AmtPaid.Text = string.Empty;
AmtPaid.Attributes.Add("readonly", "readonly");
}
}
The textbox get populated with the desired value when the checkbox is selected but both controls lost their values on pageindexchanging event.
I want the checkbox to maintain its state and textbox to maintain whatever value user entered when the pageindexchanging event is called.
Here is the code to move to next page
protected void gvPayment_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvPayment.PageIndex = e.NewPageIndex;
GetCustomer();
}
Note: I have gone through all suggested similar questions with no luck or success.
Upvotes: 1
Views: 1609
Reputation: 460078
You have to persist them, for example by storing a Disctionary<int, bool>
in the ViewState
where the key is the RowIndex
and the value is the bool
(CheckBox
is Checked
?):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["EnabledAmtPaidTextBoxes"] = new Dictionary<int, bool>();
GetCustomer();
}
}
I would encapsulate this logic in a method, you need to call it from RowDataBound
and CheckedChanged
. You don't need that final loop in GetCustomer
anymore:
protected void gvPayment_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
EnabledAmtPaidTextBox(e.Row);
}
}
protected void chkSelect_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkSelect = (CheckBox)sender;
GridViewRow row = (GridViewRow)chkSelect.NamingContainer;
EnabledAmtPaidTextBox(row, chkSelect.Checked);
}
private void EnabledAmtPaidTextBox(GridViewRow row, bool? newCheckedOrApplyOld = null)
{
TextBox AmtPaid = (TextBox)row.FindControl("AmtPaid");
Label AmtDue = (Label)row.FindControl("AmtDue");
CheckBox chkSelect = (CheckBox)row.FindControl("chkSelect");
Dictionary<int, bool> enabledAmtPaidTextBoxes = (Dictionary<int, bool>)ViewState["EnabledAmtPaidTextBoxes"];
if (!enabledAmtPaidTextBoxes.ContainsKey(row.RowIndex))
enabledAmtPaidTextBoxes[row.RowIndex] = false;
if (newCheckedOrApplyOld.HasValue)
enabledAmtPaidTextBoxes[row.RowIndex] = newCheckedOrApplyOld.Value;
else
chkSelect.Checked = enabledAmtPaidTextBoxes[row.RowIndex];
if (enabledAmtPaidTextBoxes[row.RowIndex])
{
AmtPaid.Text = AmtDue.Text.Replace(",", "");
AmtPaid.Attributes.Remove("readonly");
}
else
{
AmtPaid.Text = string.Empty;
AmtPaid.Attributes.Add("readonly", "readonly");
}
}
Also, if you use the using-statement you don't need con.Close
and con.Dispose
in finally
because that is done by the using
-statement already.
Upvotes: 1