События жизненного цикла клиента AJAX
Обновлен: Ноябрь 2007
Страница ASP.NET с включенной технологией AJAX вызывает те же серверные события жизненного цикла, что и страницы ASP.NET 2.0, и в дополнение к ним вызывает еще и клиентские события жизненного цикла. События на стороне клиента позволяют настроить пользовательский интерфейс как для обратных передач, так и для асинхронных обратных передач (частичных обновлений страницы). События на стороне клиента также помогают управлять компонентами пользовательского сценария в течение всего времени существования страницы в веб-обозревателе.
События на стороне клиента вызываются классами Microsoft AJAX (библиотека). Эти классы создаются автоматически, если страница содержит серверные элементы управления AJAX ASP.NET. Клиентские классы предоставляют API-интерфейсы, позволяющие создавать привязки к событиям, а также предоставлять обработчики для этих событий. Поскольку Microsoft AJAX (библиотека) не зависит от веб-обозревателя, код, созданный для обработчиков, работает одинаково во всех поддерживаемых веб-обозревателях.
Ключевым событием для начальных запросов (запросов GET) и синхронных обратных передач является событие загрузки экземпляра приложения. При выполнении сценария в обработчике событий load все сценарии и компоненты уже загружены и доступны. Когда включена частичная визуализация страниц с элементами управления UpdatePanel, ключевыми событиями на стороне клиента являются события класса PageRequestManager. Эти события позволяют обрабатывать многие распространенные сценарии. В частности, сюда входит возможность отмены обратных передач, повышения приоритета одной обратной передачи над другой и анимации элементов управления UpdatePanel при обновлении их содержимого.
Клиентские события полезны при создании страниц или написании компонентов. Разработчик страницы имеет возможность предоставить пользовательский сценарий, который вызывается при загрузке и выгрузке страницы в веб-обозревателе.
Дополнительные сведения о серверных событиях жизненного цикла страницы содержатся в Общие сведения о жизненном цикле веб-страниц ASP.NET.
Клиентские классы
Microsoft AJAX (библиотека) содержит два основных класса Application и PageRequestManager, которые вызывают события в процессе клиентского жизненного цикла страницы AJAX ASP.NET.
Класс Application создается в веб-обозревателе, когда страница содержит элемент управления ScriptManager. Класс Application имеет сходство с серверным элементом управления Page, который является производным от класса Control, но предоставляет дополнительные функциональные возможности вызова событий сервера. Аналогично, класс Application является производным от класса Sys.Component, но вызывает клиентские события жизненного цикла, которые можно обработать.
Если страница содержит элемент управления ScriptManager и один или несколько элементов управления UpdatePanel, то страница может выполнять частичные обновления (если частичная отрисовка страниц включена и поддерживается в веб-обозревателе). В этом случае экземпляр класса PageRequestManager автоматически становится доступным в веб-обозревателе. Класс PageRequestManager инициирует события на стороне клиента, характерные для асинхронных обратных передач. Дополнительные сведения о частичной отрисовке страниц см. в разделе Общие сведения о частичной отрисовке страниц.
Добавление обработчиков для событий на стороне клиента
Чтобы добавить или удалить обработчики для событий, вызванных классами Application и PageRequestManager, следует использовать методы add_eventname и remove_eventname этих классов. В следующем примере показано, как добавлять обработчик с именем MyLoad к событию init объекта Application.
Sys.Application.add_init(MyInit);
function MyInit(sender) {
}
Sys.Appplication.remove_init(MyInit);
Sys.Application.add_init(MyInit);
function MyInit(sender) {
}
Sys.Appplication.remove_init(MyInit);
Примечание. |
---|
В этом примере показан только синтаксис методов add_eventname и remove_eventname. Далее в этом разделе рассматривается, что именно можно делать с конкретными событиями. |
Обработка событий загрузки и выгрузки приложения
Для обработки событий load и unload объекта Application нет необходимости явно привязывать обработчик к событию. Вместо этого можно создать функции, использующие зарезервированные имена pageLoad и pageUnload. В следующем примере показано, как с помощью этого подхода добавить обработчик для события load объекта Application.
function pageLoad(sender, args) {
}
function pageLoad(sender, args) {
}
События для других клиентских классов
В этом разделе рассматриваются только события, вызываемые классами Application и PageRequestManager. Microsoft AJAX (библиотека) также содержит классы для добавления, очистки и удаления обработчиков событий элемента DOM. Эти классы включают:
метод Sys.UI.DomEvent.addHandler или ярлык $addHandler;
метод Sys.UI.DomEvent.clearHandlers или ярлык $clearHandlers;
метод Sys.UI.DomEvent.removeHandler или ярлык $removeHandler.
События, вызванные элементами DOM, не рассматриваются в данном разделе.
Клиентские события классов Application и PageRequestManager
В следующей таблице перечислены клиентские события классов Application и PageRequestManager, которые можно обрабатывать на страницах с включенной технологией AJAX ASP.NET. Порядок, в котором вызываются события, описывается далее в этом разделе.
Событие |
Описание |
---|---|
Возникает после загрузки всех сценариев, но до создания какого-либо объекта. При написании компонентов событие init обеспечивает точку в жизненном цикле для добавления компонента в страницу. Компонент может затем использоваться с другими компонентами или сценарием далее в жизненном цикле страницы. Разработчику страницы следует использовать событие load вместо события init для большинства сценариев. Событие init вызывается только один раз при первом отображении страницы. Последующие частичные обновления страницы не вызывают событие init. |
|
Возникает после того, как все сценарии загружены, и все объекты приложения, созданные с помощью $create, инициализированы. Событие load вызывается для всех обратных передач на сервер, в том числе и для асинхронных обратных передач. Разработчики страницы могут создать функцию с именем pageLoad, которая автоматически предоставляет обработчик для события load. Обработчик pageLoad вызывается после любого из обработчиков, которые были добавлены для события load с помощью метода add_load. Событие load принимает параметр eventargs, который является объектом Sys.ApplicationLoadEventArgs. С помощью аргументов событий можно определять, отображается ли страница заново при ее частичном обновлении, и какие компоненты были созданы с момента предыдущего возникновения события load. |
|
Вызывается до удаления всех объектов и перед возникновением события окна веб-обозревателя window.unload. Разработчики страницы могут создать функцию с именем pageUnload, которая автоматически предоставляет обработчик для события unload. Событие pageUnload вызывается непосредственно перед выгрузкой страницы из веб-обозревателя. Во время этого события необходимо освобождать все ресурсы, занятые кодом. |
|
Потенциально возникает, когда свойство компонента изменяется. Это событие вызывается, только если разработчик компонента вызвал метод Sys.Component.raisePropertyChange в методе доступа set для свойства. Дополнительные сведения см. в разделе Определение пользовательских свойств компонентов и создание событий PropertyChanged. Событие propertyChanged принимает параметр eventargs, который является объектом Sys.applicationLoadEventArgs. |
|
Возникает при удалении экземпляра Application. |
|
Вызывается до запуска асинхронного запроса. Это событие позволяет отменить обратную передачу, например предоставление приоритета другой асинхронной обратной передаче. Событие initializeRequest принимает параметр eventargs, который является объектом Sys.WebForms.InitializeRequestEventArgs. Этот объект делает доступным элемент, вызвавший обратную передачу, и основной объект запроса. InitializeRequestEventArgs также предоставляет свойство cancel. Если свойству cancel задано значение true, то новая обратная передача отменяется. |
|
Возникает перед запуском асинхронной обратной передачи и отправкой обратной передачи на сервер. Если обратная передача уже обрабатывается, то эта обработка останавливается (с помощью метода abortPostBack). Можно использовать это событие для установки заголовков запросов или для начала анимации на странице, указывающей, что запрос находится в процессе обработки. Событие beginRequest принимает параметр eventargs, который является объектом Sys.WebForms.InitializeRequestEventArgs. Этот объект делает доступным элемент, вызвавший обратную передачу, и базовый объект запроса. |
|
Возникает после ответа сервера на полученную асинхронную обратную передачу, но до обновления содержимого страницы. С помощью этого события можно реализовать пользовательский эффект перехода для обновленного содержимого. Событие pageLoading принимает параметр eventargs, который является объектом Sys.WebForms.InitializeRequestEventArgs. Этот объект делает доступными сведения о том, какие панели будут удалены или обновлены в результате выполнения последней асинхронной обратной передачи. |
|
Возникает после обновления всего содержимого страницы в результате выполнения либо синхронной, либо асинхронной обратной передачи. В результате синхронных обратных передач панели могут быть только созданы, но в результате асинхронных обратных передач панели могут как создаваться, так и обновляться. Это событие можно использовать для управления пользовательским эффектом перехода для обновленного содержимого. Событие pageLoaded принимает параметр eventargs, который является объектом Sys.WebForms.InitializeRequestEventArgs. Этот объект делает доступными данные о том, какие панели были обновлены или созданы в результате последней обратной передачи. |
|
Возникает после обработки ответа на асинхронную обратную передачу и обновления страницы, а также, в случае ошибки, во время обработки ответа. Если ошибка возникает, то страница не обновляется. Это событие следует использовать, чтобы предоставить настраиваемое уведомление об ошибке пользователю или в журнал ошибок. Событие endRequest принимает параметр eventargs, который является объектом Sys.WebForms.InitializeRequestEventArgs. Этот объект делает доступными сведения о произошедших ошибках, а также о том, была ли ошибка обработана. Оно также делает доступным объект Response. |
Пример, показывающий порядок возникновения событий
В следующем примере показаны клиентские события, возникающие на странице, содержащей два вложенных друг в друга элемента управления UpdatePanel. Можно заметить разницу между нажатием кнопки в родительской панели и нажатием кнопки во вложенной панели. Кнопка в родительской панели вызывает обновление родительской панели, а также удаление и повторное создание вложенной панели. Кнопка во вложенной панели вызывает только обновление вложенной панели.
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Client Event Example</title>
<style type="text/css">
#OuterPanel { width: 600px; height: 200px; border: 2px solid blue; }
#NestedPanel { width: 596px; height: 60px; border: 2px solid green;
margin-left:5 px; margin-right:5px; margin-bottom:5px;}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="ClientEventTest.js" />
</Scripts>
</asp:ScriptManager>
<asp:UpdatePanel ID="OuterPanel" UpdateMode="Conditional" runat="server">
<ContentTemplate>
Postbacks from inside the outer panel and inner panel are
asynchronous postbacks. PRM = Sys.WebForms.PageRequestManager. APP = Sys.Application.
<br /><br />
<asp:Button ID="OPButton1" Text="Outer Panel Button" runat="server" />
Last updated on
<%= DateTime.Now.ToString() %>
<br /><br />
<asp:UpdatePanel ID="NestedPanel" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Button ID="NPButton1" Text="Nested Panel 1 Button" runat="server" />
Last updated on
<%= DateTime.Now.ToString() %>
<br />
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</asp:UpdatePanel>
<input type="button" onclick="Clear();" value="Clear" />
<asp:Button ID="FullPostBack" runat="server" Text="Full Postback" />
<a href="https://www.microsoft.com">Test Window Unload</a>
<br />
<span id="ClientEvents"></span>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Client Event Example</title>
<style type="text/css">
#OuterPanel { width: 600px; height: 200px; border: 2px solid blue; }
#NestedPanel { width: 596px; height: 60px; border: 2px solid green;
margin-left:5 px; margin-right:5px; margin-bottom:5px;}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="ClientEventTest.js" />
</Scripts>
</asp:ScriptManager>
<asp:UpdatePanel ID="OuterPanel" UpdateMode="Conditional" runat="server">
<ContentTemplate>
Postbacks from inside the outer panel and inner panel are
asynchronous postbacks. PRM = Sys.WebForms.PageRequestManager. APP = Sys.Application.
<br /><br />
<asp:Button ID="OPButton1" Text="Outer Panel Button" runat="server" />
Last updated on
<%= DateTime.Now.ToString() %>
<br /><br />
<asp:UpdatePanel ID="NestedPanel" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Button ID="NPButton1" Text="Nested Panel 1 Button" runat="server" />
Last updated on
<%= DateTime.Now.ToString() %>
<br />
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</asp:UpdatePanel>
<input type="button" onclick="Clear();" value="Clear" />
<asp:Button ID="FullPostBack" runat="server" Text="Full Postback" />
<a href="https://www.microsoft.com">Test Window Unload</a>
<br />
<span id="ClientEvents"></span>
</div>
</form>
</body>
</html>
// Hook up Application event handlers.
var app = Sys.Application;
app.add_load(ApplicationLoad);
app.add_init(ApplicationInit);
app.add_disposing(ApplicationDisposing);
app.add_unload(ApplicationUnload);
// Application event handlers for component developers.
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm.get_isInAsyncPostBack())
{
prm.add_initializeRequest(InitializeRequest);
prm.add_beginRequest(BeginRequest);
prm.add_pageLoading(PageLoading);
prm.add_pageLoaded(PageLoaded);
prm.add_endRequest(EndRequest);
}
$get('ClientEvents').innerHTML += "APP:: Application init. <br/>";
}
function ApplicationLoad(sender, args) {
$get('ClientEvents').innerHTML += "APP:: Application load. ";
$get('ClientEvents').innerHTML += "(isPartialLoad = " + args.get_isPartialLoad() + ")<br/>";
}
function ApplicationUnload(sender) {
alert('APP:: Application unload.');
}
function ApplicationDisposing(sender) {
$get('ClientEvents').innerHTML += "APP:: Application disposing. <br/>";
}
// Application event handlers for page developers.
function pageLoad() {
$get('ClientEvents').innerHTML += "PAGE:: Load.<br/>";
}
function pageUnload() {
alert('Page:: Page unload.');
}
// PageRequestManager event handlers.
function InitializeRequest(sender, args) {
$get('ClientEvents').innerHTML += "<hr/>";
$get('ClientEvents').innerHTML += "PRM:: Initializing async request.<br/>";
}
function BeginRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Begin processing async request.<br/>";
}
function PageLoading(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdating", args.get_panelsUpdating());
var deletedPanels = printArray("PanelsDeleting", args.get_panelsDeleting());
var message = "-->" + updatedPanels + "<br/>-->" + deletedPanels + "<br/>";
document.getElementById("ClientEvents").innerHTML += message;
}
function PageLoaded(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Finished loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdated", args.get_panelsUpdated());
var createdPanels = printArray("PaneslCreated", args.get_panelsCreated());
var message = "-->" + updatedPanels + "<br/>-->" + createdPanels + "<br/>";
document.getElementById("ClientEvents").innerHTML += message;
}
function EndRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: End of async request.<br/>";
}
// Helper functions.
function Clear()
{
$get('ClientEvents').innerHTML = "";
}
function printArray(name, arr)
{
var panels = name + '=' + arr.length;
if(arr.length > 0)
{
panels += "(";
for(var i = 0; i < arr.length; i++)
{
panels += arr[i].id + ',';
}
panels = panels.substring(0, panels.length - 1);
panels += ")";
}
return panels;
}
// Hook up Application event handlers.
var app = Sys.Application;
app.add_load(ApplicationLoad);
app.add_init(ApplicationInit);
app.add_disposing(ApplicationDisposing);
app.add_unload(ApplicationUnload);
// Application event handlers for component developers.
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm.get_isInAsyncPostBack())
{
prm.add_initializeRequest(InitializeRequest);
prm.add_beginRequest(BeginRequest);
prm.add_pageLoading(PageLoading);
prm.add_pageLoaded(PageLoaded);
prm.add_endRequest(EndRequest);
}
$get('ClientEvents').innerHTML += "APP:: Application init. <br/>";
}
function ApplicationLoad(sender, args) {
$get('ClientEvents').innerHTML += "APP:: Application load. ";
$get('ClientEvents').innerHTML += "(isPartialLoad = " + args.get_isPartialLoad() + ")<br/>";
}
function ApplicationUnload(sender) {
alert('APP:: Application unload.');
}
function ApplicationDisposing(sender) {
$get('ClientEvents').innerHTML += "APP:: Application disposing. <br/>";
}
// Application event handlers for page developers.
function pageLoad() {
$get('ClientEvents').innerHTML += "PAGE:: Load.<br/>";
}
function pageUnload() {
alert('Page:: Page unload.');
}
// PageRequestManager event handlers.
function InitializeRequest(sender, args) {
$get('ClientEvents').innerHTML += "<hr/>";
$get('ClientEvents').innerHTML += "PRM:: Initializing async request.<br/>";
}
function BeginRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Begin processing async request.<br/>";
}
function PageLoading(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdating", args.get_panelsUpdating());
var deletedPanels = printArray("PanelsDeleting", args.get_panelsDeleting());
var message = "-->" + updatedPanels + "<br/>-->" + deletedPanels + "<br/>";
document.getElementById("ClientEvents").innerHTML += message;
}
function PageLoaded(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Finished loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdated", args.get_panelsUpdated());
var createdPanels = printArray("PaneslCreated", args.get_panelsCreated());
var message = "-->" + updatedPanels + "<br/>-->" + createdPanels + "<br/>";
document.getElementById("ClientEvents").innerHTML += message;
}
function EndRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: End of async request.<br/>";
}
// Helper functions.
function Clear()
{
$get('ClientEvents').innerHTML = "";
}
function printArray(name, arr)
{
var panels = name + '=' + arr.length;
if(arr.length > 0)
{
panels += "(";
for(var i = 0; i < arr.length; i++)
{
panels += arr[i].id + ',';
}
panels = panels.substring(0, panels.length - 1);
panels += ")";
}
return panels;
}
Порядок событий для распространенных сценариев
Порядок событий зависит от того, какие элементы управления используются на странице, и какой тип запроса выполняется (начальный запрос, обратная передача или асинхронная обратная передача). В этом разделе описан порядок событий для нескольких наиболее распространенных сценариев.
Начальный запрос
Во время начального запроса страницы вызывается ограниченное число клиентских событий. Предположим следующий сценарий начального запроса:
Страница содержит элемент управления ScriptManager, свойства SupportsPartialRendering и EnablePartialRendering которого имеют значение true.
Запрос представляет собой запрос GET.
Ответ сервера возвращен успешно.
Тогда возникают следующие клиентские события в указанном порядке:
Начальный запрос отправляется на сервер.
Клиент получает ответ.
Экземпляр Application вызывает событие init.
Экземпляр Application вызывает событие load.
Событие init экземпляра Application вызывается только один раз в течение времени жизни страницы в веб-обозревателе. Это событие не вызывается при последующих асинхронных обратных передачах. Во время начального запроса события PageRequestManager не вызываются.
Асинхронная обратная передача
Асинхронная обратная передача отправляет некоторые данные страницы на сервер, получает ответ и обновляет часть страницы. Предположим следующий сценарий для асинхронной обратной передачи:
Страница содержит элемент управления ScriptManager, свойства которого SupportsPartialRendering и EnablePartialRendering имеют значение true.
Страница содержит элемент управления UpdatePanel, свойство которого ChildrenAsTriggers имеет значение true.
Кнопка в элементе управления UpdatePanel инициирует асинхронную обратную передачу.
Ответ сервера возвращен успешно.
Тогда возникают следующие клиентские события в указанном порядке:
Кнопка в панели UpdatePanel нажата, что инициирует асинхронную повторную передачу.
Экземпляр PageRequestManager вызывает событие initializeRequest.
Экземпляр PageRequestManager вызывает событие beginRequest.
Запрос отправляется на сервер.
Клиент получает ответ.
Экземпляр PageRequestManager вызывает событие pageLoading.
Экземпляр PageRequestManager вызывает событие pageLoaded.
Экземпляр Application вызывает событие load.
Экземпляр PageRequestManager вызывает событие endRequest.
Дополнительные сведения см. в разделе Работа с событиями класса PageRequestManager.
Обратите внимание, что событие load экземпляра Application возникает после события PageRequestManagerpageLoaded и до его события endRequest.
Несколько асинхронных обратных передач
Несколько асинхронных обратных передач может произойти, если пользователи начинают новый запрос до окончания обработки на сервере или в веб-обозревателе запроса, инициированного ранее. Предположим следующий сценарий для нескольких асинхронных обратных передач:
Страница содержит элемент управления ScriptManager, свойства SupportsPartialRendering и EnablePartialRendering которого имеют значение true.
Страница содержит элемент управления UpdatePanel.
Кнопка внутри элемента управления UpdatePanel, который инициирует асинхронную обратную передачу, нажата два раза. Второе нажатие происходит, пока сервер обрабатывает запрос, инициированный первым нажатием.
Ответ на первый запрос успешно возвращается сервером.
Тогда возникают следующие клиентские события в указанном порядке:
Кнопка в панели UpdatePanel нажата, что инициирует асинхронную повторную передачу.
Экземпляр PageRequestManager вызывает событие initializeRequest.
Экземпляр PageRequestManager вызывает событие beginRequest.
Запрос отправляется на сервер.
Эта кнопка нажимается снова, что инициирует вторую асинхронную обратную передачу.
Экземпляр PageRequestManager вызывает событие initializeRequest для второго нажатия кнопки.
Экземпляр PageRequestManager вызывает событие endRequest для первого нажатия кнопки.
Экземпляр PageRequestManager вызывает событие beginRequest для второго нажатия кнопки.
Запрос, инициированный вторым нажатием, отправляется на сервер.
Возвращается ответ на второе нажатие кнопки.
Экземпляр PageRequestManager вызывает событие pageLoading.
Экземпляр PageRequestManager вызывает событие pageLoaded.
Экземпляр Application вызывает событие load.
Экземпляр PageRequestManager вызывает событие endRequest.
По умолчанию последняя асинхронная обратная передача имеет больший приоритет. Если две асинхронные обратные передачи возникают последовательно друг за другом, причем первая обратная передача все еще обрабатывается в веб-обозревателе, то первая обратная передача отменяется. Если первая обратная передача была отправлена на сервер, то сервер обрабатывает второй запрос, когда тот поступает, и не возвращает ответ на первый запрос. Сведения о повышении приоритета конкретной асинхронной обратной передачи см. в разделе Предоставление приоритета определенным асинхронным обратным запросам.
Выход из страницы
Когда пользователь покидает страницу, эта страница выгружается из веб-обозревателя, и можно обрабатывать событие unload для освобождения ресурсов. Предположим следующий сценарий выхода со страницы:
Страница содержит элемент управления ScriptManager, свойства SupportsPartialRendering и EnablePartialRendering которого имеют значение true.
Целевая страница существует.
Тогда возникают следующие клиентские события в указанном порядке:
Инициируется запрос новой страницы.
Веб-обозреватель получает ответ новой страницы.
Экземпляр Application вызывает событие unload.
Появляется новая страница.
Если в запросе новой страницы имеется ошибка, то событие unload все равно возникает, но новая страница не отображается.
См. также
Основные понятия
Общие сведения о жизненном цикле веб-страниц ASP.NET
Определение пользовательских свойств компонентов и создание событий PropertyChanged