I have an issue with both Dropdownlist_OnSelectedIndexChanged
and Checkbox_OnCheckedChanged
events not firing from within an UpdatePanel
after the UpdatePanel
has been updated from the code behind.
As you can see from the code below the DropDownList
and CheckBoxes
bind on the client side and when loaded / reloaded all of the Controls
bind to the values from the database.
When the page initially loaded with some data, both the Dropdownlist_OnSelectedIndexChanged
and Checkbox_OnCheckedChanged
events fire as expected. They also update the database values via the code behind.
However if, for example, I change the data range for my GridView
data and therefore refresh the UpdatePanel
and rebind all of the data, the Dropdownlist_OnSelectedIndexChanged
and Checkbox_OnCheckedChanged
events stop firing.
I have tried to diagnose this by adding various break points to the code behind when the Dropdownlist_OnSelectedIndexChanged
and Checkbox_OnCheckedChanged
events should be calling the relevant functions, however the breakpoints are never reached.
I also have OnSelectedIndexChanged
enabled in the GridView
where the above Controls
are located and it fire as expected, every time... Even when the above Controls
do not.
My code is:
<%@ Page Title="Downtime" Language="C#"
MasterPageFile="~/Reporting/Reporting.Master" AutoEventWireup="true" CodeBehind="GensetDowntime.aspx.cs" Inherits="ReportingSystemV2.Reporting.GensetDowntime" %>
<%@ MasterType VirtualPath="~/Reporting/Reporting.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ReportingSubContent" runat="server">
<div class="container-fluid">
<asp:UpdatePanel ID="updPanelDowntime" runat="server">
<ContentTemplate>
<%--Summary Table--%>
<div id="DowntimeSummaryDiv" visible="false" runat="server">
<table id="DowntimeSummary" class="table table-striped table-condensed" align="center" style="width: 50%">
<thead>
<tr>
<th>Gross Hours</th>
<th>Run Hours</th>
<th>Total Exempts</th>
<th>Total Non-Exempts</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<asp:Label ID="lblSumGrossHrs" runat="server" ToolTip="Total hours in this period"></asp:Label></td>
<td>
<asp:Label ID="lblSumRunHours" runat="server" ToolTip="Engine running hours in this period"></asp:Label></td>
<td>
<asp:Label ID="lblSumTotExempts" runat="server" ToolTip="(hhhh:mm)"></asp:Label></td>
<td>
<asp:Label ID="lblSumTotNonExempts" runat="server" ToolTip="(hhhh:mm)"></asp:Label></td>
<td>
<asp:Label ID="lblSumDifference" runat="server" ToolTip="Difference (Minutes) = Gross Hours - (Run Hours + Total Exempt + Total Non-Exempt)"></asp:Label></td>
</tr>
</tbody>
</table>
</div>
<%--End of Summary Table--%>
<%--Downtime Table--%>
<div class="row">
<div id="downtimeDiv" runat="server">
<asp:GridView ID="gridDowntime" runat="server" AutoGenerateColumns="False" GridLines="None" CssClass="table table-striped table-condensed"
OnRowDataBound="gridDowntime_RowDataBound"
OnSelectedIndexChanged="gridDowntime_SelectedIndexChanged"
DataKeyNames="ID,ID_Location,iddown,idup,dtdown,dtup,isexempt" EmptyDataText="No exempts in the selected period.">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ID" />
<asp:BoundField DataField="dtdown" DataFormatString="{0:dd/MM/yyyy HH:mm:ss.fff}"
HeaderText="Down" />
<asp:BoundField DataField="dtup" DataFormatString="{0:dd/MM/yyyy HH:mm:ss.fff}"
HeaderText="Up" />
<asp:BoundField DataField="timedifference"
HeaderText="Duration (min)" DataFormatString="{0:D4}" />
<asp:BoundField DataField="REASON"
HeaderText="Reason" />
<asp:TemplateField HeaderText="Exempt?">
<ItemTemplate>
<asp:DropDownList ID="ddlDowntimeExempt" AutoPostBack="true" runat="server"
OnSelectedIndexChanged="ddlDowntimeExempt_SelectedIndexChanged">
<asp:ListItem Value="-1">Unverified</asp:ListItem>
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0">No</asp:ListItem>
</asp:DropDownList>
<asp:Label ID="lblDowntimeExempt" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"isexempt")%>' Visible="false"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Exclude?">
<ItemTemplate>
<asp:CheckBox ID="chkDowntimeExclude" runat="server" Checked='<%#Convert.ToBoolean(Eval("ISEXCLUDED")) %>' OnCheckedChanged="chkDowntimeExclude_CheckedChanged" AutoPostBack="true"/>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowSelectButton="True" SelectText="Details" />
</Columns>
</asp:GridView>
</div>
</div>
<%--End of Downtime Table--%>
<%--Shutdown Values--%>
<div id="downtimeValueDiv" runat="server">
<asp:GridView ID="gridDowntimeRecalc" runat="server" AutoGenerateColumns="False" GridLines="None"
CssClass="table table-striped table-condensed" Width="50%" HorizontalAlign="Center">
<Columns>
<asp:BoundField DataField="dtdown" DataFormatString="{0:dd/MM/yyyy HH:mm:ss.fff}"
HeaderText="Downtime" />
<asp:BoundField DataField="dtup" DataFormatString="{0:dd/MM/yyyy HH:mm:ss.fff}"
HeaderText="Uptime" />
<asp:BoundField DataField="TimeDifference"
HeaderText="Duration (min)" DataFormatString="{0:D4}" />
<asp:TemplateField ShowHeader="false">
<ItemTemplate>
<asp:LinkButton ID="lnkReset" runat="server" OnClick="lnkReset_Click" ToolTip="Reset">
<span aria-hidden="true" class="fa fa-rotate-left"></span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div class="span7 text-center">
<br />
<div class="pull-right">
<div class="form-inline">
Events (min +/-):
<asp:DropDownList ID="ddlAdjust" runat="server" CssClass="form-control input-sm"
OnSelectedIndexChanged="ddlAdjust_SelectedIndexChanged" AutoPostBack="True">
<asp:ListItem>0</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
<asp:ListItem Selected="True">10</asp:ListItem>
<asp:ListItem>15</asp:ListItem>
<asp:ListItem>30</asp:ListItem>
<asp:ListItem>45</asp:ListItem>
<asp:ListItem>60</asp:ListItem>
<asp:ListItem>90</asp:ListItem>
<asp:ListItem>120</asp:ListItem>
<asp:ListItem>240</asp:ListItem>
</asp:DropDownList>
</div>
</div>
<br />
</div>
</div>
<%--End of Shutdown Values--%>
<%--Details Row--%>
<div id="detailDiv" runat="server">
<asp:GridView ID="gridDowntimeDetail" runat="server" AutoGenerateColumns="False"
GridLines="None" CssClass="table table-condensed"
OnRowDataBound="gridDowntimeDetail_RowDataBound"
OnRowCommand="gridDowntimeDetail_RowCommand"
DataKeyNames="ExemptId">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton ID="lnkBack" runat="server" Text="Back" CommandName="Back"
CommandArgument="<% Container.DataItemIndex + 1 %>"
CausesValidation="false">
<span aria-hidden="true" class="fa fa-arrow-circle-left"></span>
</asp:LinkButton>
</HeaderTemplate>
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Timestamp" DataFormatString="{0:dd/MM/yyyy HH:mm:ss.fff}" HeaderText="Time Stamp" />
<asp:BoundField DataField="Reason" HeaderText="Reason" />
<asp:BoundField DataField="Event" HeaderText="Event" />
</Columns>
</asp:GridView>
<br />
<br />
</div>
<%--End of Details Row--%>
<%--Notes Row--%>
<div class="span7 text-center">
<div id="notesDiv" runat="server">
<div class="form-horizontal">
<div class="form-group">
<label class="col-md-4 control-label">Notes</label>
<div class="col-md-4">
<asp:TextBox ID="tbNotes" runat="server" MaxLength="40" CssClass="form-control"></asp:TextBox>
</div>
</div>
</div>
<asp:LinkButton ID="lnkSave" runat="server" OnClick="lnkSave_Click">
<span aria-hidden="true" class="fa fa-floppy-o"></span> Save
</asp:LinkButton>
<br />
<br />
<asp:LinkButton ID="lnkBack1" runat="server" OnClick="lnkBack_Click">
<span aria-hidden="true" class="fa fa-arrow-circle-left"></span> Back
</asp:LinkButton>
</div>
</div>
<%--End of Notes Row--%>
</ContentTemplate>
</asp:UpdatePanel>
</div>
My code behind is:
namespace ReportingSystemV2.Reporting
{
public partial class GensetDowntime : System.Web.UI.Page
{
ReportingSystemDataContext RsDc = new ReportingSystemDataContext();
protected void Page_Load(object sender, EventArgs e)
{
// Attach to UserControl Event
Master.reportDateChanged += new EventHandler(report_DateChanged);
}
protected void Page_LoadComplete(object sender, EventArgs e)
{
ReportingBase f = (ReportingBase)Page.Master;
if (!Page.IsPostBack)
{
if (f.IdLocation != 0)
{
if (f.endDate < f.startDate)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "bootstrap_alert.warning('alert-warning', 'Oops!', 'Please select a valid date range..');", true);
}
else
{
BindDowntime();
bindDowntimeSummary();
}
}
else
{
Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "bootstrap_alert.warning('alert-warning', 'Oops!', 'Please select a site..');", true);
}
showDowntimeDetail(false);
}
}
private void report_DateChanged(object sender, EventArgs e)
{
// If the user changes the date lets update the table
BindDowntime();
bindDowntimeSummary();
showDowntimeDetail(false);
}
#region Overview
protected void BindDowntime()
{
// Binds the downtime to the gv
// Hide the downtime ID
ReportingBase f = (ReportingBase)Page.Master;
gridDowntime.Columns[1].Visible = false;
gridDowntime.DataSource = RsDc.FILTEREXEMPTS(f.IdLocation, f.startDate, f.endDate.AddHours(23).AddMinutes(59).AddSeconds(59));
gridDowntime.DataBind();
if (gridDowntime.Rows.Count > 0)
{
// CSS Header Sytle
gridDowntime.UseAccessibleHeader = true;
gridDowntime.HeaderRow.TableSection = TableRowSection.TableHeader;
}
}
protected void bindDowntimeSummary()
{
ReportingBase f = (ReportingBase)Page.Master;
// Binds the summary at the top of the page for the user to see the downtime at a glance
int hrsRun = 0;
TimeSpan tsGrossHours = (f.endDate - f.startDate);
if (f.startDate.Date == f.endDate.Date)
{
tsGrossHours = tsGrossHours.Add(new TimeSpan(24, 0, 0));
hrsRun = Convert.ToInt32(RsDc.ACTUALHOURSRUN(f.IdLocation, f.startDate, f.endDate).FirstOrDefault().ACTUALHOURSRUN);
}
else
{
hrsRun = Convert.ToInt32(RsDc.ACTUALHOURSRUN(f.IdLocation, f.startDate, f.endDate).FirstOrDefault().ACTUALHOURSRUN);
}
lblSumGrossHrs.Text = tsGrossHours.TotalHours.ToString();
lblSumRunHours.Text = hrsRun.ToString();
int totalExempts = 0;
int totalNonExempts = 0;
// Loop Grid
foreach (GridViewRow row in gridDowntime.Rows)
{
DropDownList ddl = new DropDownList();
ddl = row.Cells[5].FindControl("ddlDowntimeExempt") as DropDownList;
CheckBox cbx = new CheckBox();
cbx = row.Cells[6].FindControl("chkDowntimeExclude") as CheckBox;
if (!cbx.Checked)
{
if (ddl.SelectedValue == "1")
{
totalExempts += Convert.ToInt32(row.Cells[4].Text);
}
else
{
totalNonExempts += Convert.ToInt32(row.Cells[4].Text);
}
}
}
TimeSpan tsTotalExempts = new TimeSpan(0, totalExempts, 0);
TimeSpan tsTotalNonExempts = new TimeSpan(0, totalNonExempts, 0);
lblSumTotExempts.Text = ((tsTotalExempts.Days * 24 + tsTotalExempts.Hours).ToString().PadLeft(4, '0') + ":" + tsTotalExempts.Minutes.ToString().PadLeft(2, '0'));
lblSumTotNonExempts.Text = ((tsTotalNonExempts.Days * 24 + tsTotalNonExempts.Hours).ToString().PadLeft(4, '0') + ":" + tsTotalNonExempts.Minutes.ToString().PadLeft(2, '0'));
TimeSpan tsHrsRun = new TimeSpan((int)hrsRun, 0, 0);
lblSumDifference.Text = (tsGrossHours.TotalMinutes - (tsHrsRun.TotalMinutes + tsTotalExempts.TotalMinutes + tsTotalNonExempts.TotalMinutes)).ToString();
DowntimeSummaryDiv.Visible = true;
}
protected void gridDowntime_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Once data is loaded into the gv apply the ddl's for the shutdowns
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = (DropDownList)e.Row.FindControl("ddlDowntimeExempt");
//ddl.SelectedIndexChanged += new EventHandler(ddlDowntimeExempt_SelectedIndexChanged);
//ddl.AutoPostBack = true;
Label lbl = (Label)e.Row.FindControl("lblDowntimeExempt");
switch (lbl.Text)
{
case "True":
ddl.SelectedValue = "1";
break;
case "False":
ddl.SelectedValue = "0";
break;
default:
ddl.SelectedValue = "-1";
break;
}
}
}
protected void gridDowntime_SelectedIndexChanged(object sender, EventArgs e)
{
// User selected a shutdown, show its details
bindDowntimeDetail();
showDowntimeDetail(true);
}
protected void ddlDowntimeExempt_SelectedIndexChanged(object sender, EventArgs e)
{
// Applies the values selected in the exempt DDL to the database value
DropDownList ddl = (DropDownList)sender;// <--Breakpoint
GridViewRow gvrow = (GridViewRow)ddl.NamingContainer;
int exempt_id = int.Parse(gridDowntime.DataKeys[gvrow.RowIndex].Value.ToString());
bool? value = new bool?();
if (ddl.SelectedValue.ToString() == "1")
{
value = true;
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, set to Exempt.", exempt_id));
}
else if (ddl.SelectedValue.ToString() == "0")
{
value = false;
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, set to Non-Exempt.", exempt_id));
}
else
{
value = null;
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, set to Unverified.", exempt_id));
}
RsDc.UPDATEISEXEMPT(exempt_id, value);
// Update the gv
BindDowntime();
}
protected void chkDowntimeExclude_CheckedChanged(object sender, EventArgs e)
{
// When the Exclude checkbox is changed, update the Db
CheckBox chk = (CheckBox)sender; // <--Breakpoint
GridViewRow gvrow = (GridViewRow)chk.NamingContainer;
int exempt_id = int.Parse(gridDowntime.DataKeys[gvrow.RowIndex].Value.ToString());
RsDc.updateIsExcluded(exempt_id, chk.Checked);
if (chk.Checked)
{
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, has been Excluded.", exempt_id));
}
else
{
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, has been Included.", exempt_id));
}
BindDowntime();
bindDowntimeSummary();
}
protected void showDowntimeDetail(bool show)
{
// Shows or Hides a specific shutdowns detail
downtimeDiv.Visible = !show;
DowntimeSummaryDiv.Visible = !show;
detailDiv.Visible = show;
notesDiv.Visible = show;
downtimeValueDiv.Visible = show;
}
#endregion
#region Details
protected void bindDowntimeDetail()
{
// Bind the detail for the selected shutdown
// Get the values from the gv's datakeys
int id_location = int.Parse(gridDowntime.SelectedDataKey[1].ToString());
DateTime dtdown = DateTime.Parse(gridDowntime.SelectedDataKey[4].ToString());
DateTime dtup = DateTime.Parse(gridDowntime.SelectedDataKey[5].ToString());
int exempt_id = int.Parse(gridDowntime.SelectedDataKey[0].ToString());
int adjust = int.Parse(ddlAdjust.SelectedValue);
// Get the detail & apply
DB db = new DB();
gridDowntimeDetail.DataSource = db.getAllReasonForDownTimeAppend(id_location, dtdown, dtup, adjust, exempt_id);
gridDowntimeDetail.DataBind();
//CSS Header Sytle
gridDowntimeDetail.UseAccessibleHeader = true;
gridDowntimeDetail.HeaderRow.TableSection = TableRowSection.TableHeader;
//Notes
bindDowntimeNotes(exempt_id);
bindDowntimeDetailsSummary(exempt_id);
}
protected void bindDowntimeDetailsSummary(int id)
{
gridDowntimeRecalc.DataSource = (from s in RsDc.Exempts where s.ID == id select s).ToList();
gridDowntimeRecalc.DataBind();
//CSS Header Sytle
gridDowntimeRecalc.UseAccessibleHeader = true;
gridDowntimeRecalc.HeaderRow.TableSection = TableRowSection.TableHeader;
}
protected void bindDowntimeNotes(int id)
{
var query = (from s in RsDc.Exempts where s.ID == id select s.Details).Single();
if (query != null)
{
tbNotes.Text = query.ToString();
}
}
protected void gridDowntimeDetail_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Highlights the GCB Open & GCB Closed Events
// Also enables the mouse over highlight & click functionality
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[2].Text == "GCB opened")
{
e.Row.CssClass = "danger";
}
else if (e.Row.Cells[2].Text == "GCB closed")
{
e.Row.CssClass = "info";
}
else
{
e.Row.CssClass = "";
e.Row.Attributes.Add("style", "cursor:pointer;");
e.Row.Attributes.Add("onclick", "this.style.backgroundColor='orange';");
e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#c8e4b6'");
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor=''");
}
}
}
protected override void Render(HtmlTextWriter writer)
{
// Trigger an event when a row is clicked
foreach (GridViewRow row in gridDowntimeDetail.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
// Set the last parameter to True
// to register for event validation.
row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(gridDowntimeDetail, "Up$" + row.RowIndex, true);
}
}
base.Render(writer);
}
protected void gridDowntimeDetail_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Handles what will happen when a selected row is clicked
// But first - is this a request to go back?
if (e.CommandName == "Back")
{
// Return to the Downtime View
// Hide the details
showDowntimeDetail(false);
//CSS Header Sytle
gridDowntime.UseAccessibleHeader = true;
gridDowntime.HeaderRow.TableSection = TableRowSection.TableHeader;
}
else if(e.CommandName == "Up")
{
// Get the selected row index
int rowIndex = Convert.ToInt32(e.CommandArgument.ToString());
// Get the user selected new details
int exempt_id = Convert.ToInt32(gridDowntimeDetail.DataKeys[rowIndex].Value);
DateTime newUp = DateTime.ParseExact(gridDowntimeDetail.Rows[rowIndex].Cells[1].Text, "dd/MM/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
string reason = gridDowntimeDetail.Rows[rowIndex].Cells[2].Text;
// Get the original details from db.
var orig = (from t in RsDc.getExemptsUpDown(exempt_id)
select new { DtDown = t.DTDOWN, DtUp = t.DTUP }).SingleOrDefault();
DateTime Down = Convert.ToDateTime(orig.DtDown);
//DateTime Up = Convert.ToDateTime(orig.DtUp);
if (newUp >= Down)
{
int totalmins = Convert.ToInt32((newUp - Down).TotalMinutes);
// Update the DB
RsDc.updateExempt(exempt_id, newUp, totalmins, reason, false);
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, Uptime has been updated. Reason:{1}, Uptime:{2}.", exempt_id, reason, newUp.ToString()));
// Highlight & Refresh times
gridDowntimeDetail.Rows[rowIndex].CssClass = "info";
bindDowntimeDetailsSummary(exempt_id);
bindDowntimeDetail();
showDowntimeDetail(true);
Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "bootstrap_alert.warning('success', 'Success!', 'The record has been updated!');", true);
}
else
{
// User Feedback Error
}
}
}
protected void lnkReset_Click(object sender, EventArgs e)
{
// Reset the shutdown values back to there defaults
int ExemptId = Convert.ToInt32(gridDowntimeDetail.DataKeys[0].Value);
RsDc.resetExempt(ExemptId);
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, has been Reset.", ExemptId));
bindDowntimeDetailsSummary(ExemptId);
bindDowntimeDetail();
showDowntimeDetail(true);
Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "bootstrap_alert.warning('success', 'Success!', 'The record has been reset!');", true);
}
protected void lnkBack_Click(object sender, EventArgs e)
{
// Return to the Downtime View
// Hide the details
showDowntimeDetail(false);
//CSS Header Sytle
gridDowntime.UseAccessibleHeader = true;
gridDowntime.HeaderRow.TableSection = TableRowSection.TableHeader;
}
protected void ddlAdjust_SelectedIndexChanged(object sender, EventArgs e)
{
// Adjust the viewing window (minutes)
bindDowntimeDetail();
showDowntimeDetail(true);
}
protected void lnkSave_Click(object sender, EventArgs e)
{
// Save the Note to the Db
int ExemptId = int.Parse(gridDowntime.SelectedDataKey[0].ToString());
RsDc.setExemptDetails(ExemptId, tbNotes.Text);
LogMe.LogUserMessage(string.Format("Exempt ID:{0}, Notes have been updated '{1}'.", ExemptId, tbNotes.Text));
Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), "bootstrap_alert.warning('success', 'Success!', 'The record has been saved!');", true);
}
#endregion
}
}
Any help is appreciated. Thanks
I believe I have found this answer to this one myself, after further debugging I found that my Control
for changing the date range for the GridView
was being fired when changing the CheckBox
value or the DropDownList
value. Therefore the CheckBox_CheckChanged
and DropDownList_SelectedIndexChanged
events where not being fired.
I found that because I had multiple 'UpdatePanels' on the page all of them where being fired simultaneously. Therefore by adding:
if (Request["__EVENTTARGET"] == UpdatePanelDateChanged.ClientID)
{
// Fire date changed event here..
}
I was able to prevent my 'dateChanged' function from firing except when a specific PostBack
call was being made to the UpdatePanel
in my date selection Control
.
See my question here: C# ASP.NET CheckBox_OnCheckedChanged not firing as expected for more info.