I have an issue with both Checkbox_OnCheckedChanged
and Dropdownlist_OnSelectedIndexChanged
events not triggering the relevant functions in my code behind.
Both Controls are bound to values in a GridView
. On the first OnCheckedChanged
or OnSelectedIndexChanged
event raised from the UI the functions in the code behind fire without error, however if I refresh my UpdatePanel
, for example by changing the date range of the data inside the GridView
and therefore loading more or less records, the OnCheckedChanged
and OnSelectedIndexChanged
functions are no longer called, however a PostBack
occurs.
I believe that the functions are not being called as the function that rebinds the GridView
is called instead:
private void report_DateChanged(object sender, EventArgs e)
{
// Bind GridView here..
}
however I cannot figure out why this happens.
I have a MasterPage:
namespace ReportingSystemV2.Reporting
{
public partial class Reporting : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
// Attach to DateChanged Event on DateChange UserControl to Function
DateRangeSelect.dateChanged += new DateRangeSelect.dateChangedEventHandler(dtRgSel_dateChanged);
}
// Declare an event for the content pages
public event EventHandler reportDateChanged;
// Called on a date change event
protected void dtRgSel_dateChanged(object sender, DateChangedEventArgs e)
{
// Raise the event for content pages
if (reportDateChanged != null)
reportDateChanged(this, EventArgs.Empty);
}
}
This MasterPage
has a Control
for selecting my date range..
The main section of code for my control ascx
code is:
<%--UpdatePanel to trigger datechange--%>
<asp:UpdatePanel runat="server" ID="UpdatePanelDateChanged" OnLoad="UpdatePanelDateChanged_Load" >
</asp:UpdatePanel>
<%--When the date changes in javascript a postback is called in the updatepanel--%>
__doPostBack('<%=UpdatePanelDateChanged.ClientID %>', null);
And the the main section of code behind for this control is:
// Declare a delegate
public delegate void dateChangedEventHandler(object sender, DateChangedEventArgs e);
// Declare an event for any pages that have the control
public event dateChangedEventHandler dateChanged;
protected virtual void OnDateChanged(DateChangedEventArgs e)
{
dateChangedEventHandler handler = dateChanged;
// Raise the event
if (handler != null)
handler(this, e);
}
protected void UpdatePanelDateChanged_Load(object sender, EventArgs e)
{
// Trigger the controls public event
OnDateChanged(new DateChangedEventArgs(DateTime.Parse(dates[0]), DateTime.Parse(dates[1])));
}
In my content page my aspx
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>
<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>
<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>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</asp:Content>
And finally my code behind for my content page is:
protected void Page_PreInit(object sender, EventArgs e)
{
// Attach to UserControl Event on the MasterPage
Master.reportDateChanged += new EventHandler(report_DateChanged);
}
// If the user changes the date lets update the table
private void report_DateChanged(object sender, EventArgs e)
{
// Bind the gridview
}
// Function to be called when the ddl selectedindex is changed, only called on initial page load
protected void ddlDowntimeExempt_SelectedIndexChanged(object sender, EventArgs e)
{
// Applies the values selected in the exempt DDL to the database value
}
// function to be called when the checkbox checked state is change, again only called on the initial page loading - not after a postback
protected void chkDowntimeExclude_CheckedChanged(object sender, EventArgs e)
{
// When the Exclude checkbox is changed, update the Db
}
The code above shows the control
that uses javascript to trigger
a PostBack
on an UpdatePanel
, which triggers
a public event in the Control
. The MasterPage
has a function which is attached to the Control
Event, this MasterPage
functions updates a few values and triggers a new Event which is accessable to my ContentPage
. The ContentPage
attaches a function to this MasterPage
Event and when the DateRange
is changed it will load the data for the GridView
and bind it.
Master pages append extra names at the beginning of controls in "child" pages. Most likely you are expecting the dropdown to have a name but it will have a different longer one like ctrl1$something$dropdown.
Check the ida using inspect in Chrome or dev tools to confirm that this is your problem first.
Problem solved, by modifying the code in my
DateRangeControl
theUpdatePanel
is no longer being triggered on allPostBacks
, only those where it is called by__doPostBack('<%=UpdatePanelDateChanged.ClientID %>', null);
in myJavascript
.Solution reference:
http://encosia.com/are-you-making-these-3-common-aspnet-ajax-mistakes/
I think you're missing async postback triggers. When an update panel partially posts back, it sends back the whole page, does the processing, and then returns only the portion that changed. Probably in that process, slight ID changes have taken place and then there are missed registrations. The
report_DateChanged
is fired most probably because it is the first control on the page that implementsIPostBackEventHandler
(because the postback on the checkbox and dropdown don't work any more)To resolve that, explicitly add each control that should do an async postback to the update panel's triggers. like this: