Знакомство с ASP.NET 2.0
Страница 8. Управление страницей


Управление страницей

Установка выделения на элемент управления

Иногда бывает необходимо, чтобы после загрузки страницы выделение было установлено на какой-то определенный элемент управления (например в поисковой форме логично установить фокус ввода на основное поле поиска), для этого можно задать значение атрибута defaultfocus тега form.

<form id="frmMain" runat="server" defaultfocus="txtFirstName">
<asp:TextBox ID="txtFirstName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtSecondName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtLastName" runat="server"></asp:TextBox></form>

Выделением можно управлять программно, вызывая метод SetFocus, в качестве параметра передавая уникальный идентификатор этого элемента:

protected void Page_Load(object sender, EventArgs e)
{ if(isPostBack) { SetFocus("txtLastName"); } else { SetFocus("txtFirstText"); }}

Обновление данных без перезагрузки страницы

В ASP.NET 2.0 стало возможным обновлять данные на странице без отправки страницы на сервер и ее полного обновления. Это стало возможно благодаря появлению клиентских сценариев с обратным вызовом (callback scripts или клиентские коллбэки). После того, как некоторое событие вызывает запрос к серверу, обновленные данные передаются непосредственно в клиентский сценарий в качестве аргументов функции.
   Подобный способ обновления данных на странице удобно и выгодно применять, когда для обновления всей информации требуется много ресурсов и достаточно длительное время, при этом эти часть данных обновляется часто, а остальные данные статичны. Тогда время на обновления данных, например, одного пользовательского элемента, учитывая время запроса к серверу, обработки и получения ответа, будет существенно ниже, чем время обновления всей страницы.
   Допустим, существует страница, на которой находится выпадающий список. Когда пользователь выбирает некоторое значение из списка, в некоторый элемент управления загружается значение, логически связанное с выбранным из списка значением. При этом задача такова, что нельзя хранить все данные на стороне клиента (возможно данных слишком много и страница будет долго передаваться по сети, либо данные генерируются на сервере не только в зависимости от выбранного пользователем элемента выпадающего списка). В ASP.NET 1.x для решения этой задачи необходимо привязать к событию изменения значения в выпадающем списке серверный метод. При этом список должен вызывать отправку страницы на сервер при каждом изменении значения (AutoPostBack="True").

protected void ddStatic_SelectedIndexChanged(object sender, EventArgs e){
// На основании значения ddStatic.Items[ddStatic.SelectedIndex].Value
// метод устанавливает свойства дригих элементов управления}

В ASP.NET 2.0, как уже было сказано выше, существует возможность не обновлять всю страницу целиком. В данном случае разумно обновить только необходимые данные, поскольку обновлять всю страницу только для того, чтобы установить одно значение слишком расточительно.

   Для реализации механизма обновления данных без перезагрузки страницы необходимо создать клиентскую функцию обратного вызова, принимающую переданные с сервера параметры, серверную функцию, принимающую параметры от клиента и возвращающую клиенту значения на основании полученных параметров и связать эти две функции. Мало того, механизм обратного вызова в ASP.NET 2.0 позволяет возвращать результат асинхронно. Для этого в интерфейсе ICallbackEventHandler определены два метода: RaiseCallbackEvent, для получения параметров на сервере и GetCallbackResult для возвращения результата клиенту.Для реализации функциональности предыдущего примера в ASPX файле помещается следующий код.

<script>function UpdateText(result, context) { dSpan.innerText = result;}</script>
<asp:DropDownList ID="ddDynamic" runat="server"></asp:DropDownList><br />
<span id="dSpan" style="font-weight: bold;"></span>

Класс страницы, использующей функции с обратным вызовом должен реализовывать интерфейс ICallbackEventHandler.

public partial class ScriptCallback_aspx : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler { }

Сигнатуры функций, поддерживающие обратный вызов выглядят следующим образом:

public virtual void PrepareCallbackEvent(string Аргументы)public virtual string RenderCallbackResult()
private string EventArgument = "";
public void PrepareCallbackEvent(string eventArgument){ EventArgument = eventArgument;}
public string RenderCallbackResult(){ return EventArgument; // значение типа string}

Последним шагом к поставленной цели является связывание серверной и клиентских функций.

protected void Page_Load(object sender, EventArgs e){ 
// создаем ссылку на функцию обратного вызова 
string callbackFunction = Page.ClientScript.GetCallbackEventReference ( 
this, "document.all['ddDynamic'].value", "UpdateText", "null" ); 
// Привязываем сценарий к событию изменения значения выпадающего 
// списка ddDynamic.Attributes["onchange"] = String.Format("javascript:{0}", callbackFunction);}

Метод GetCallbackEventReference объекта ClientScriptManager принимает в качестве параметров ссылку на объект страницы, строку, указывающую на значение, которое необходимо передавать на сервер при обратном вызове, имя метода на стороне клиента и принимающего ответ сервера. Подробное описание можно получить в документации MSDN или с помощью инструмента Visual Studio - Object Browser.
    Используя эту технологию можно создавать сложные методы обновления данных страницы и позволяющие получить значительный выигрыш в производительности, для этого достаточно разобраться в том, какой код генерирует среда выполнения ASP.NET, реализуя эту функциональность.
 

// Список, вызывающий перезагрузку страницы
<select name="ddStatic"onchange="javascript:setTimeout(
'__doPostBack(\'ddStatic\',\'\')', 0)"id="ddStatic"></select>
// Список вызывающий метод с обратным вызовом
<select name="ddDynamic" id="ddDynamic"onchange="javascript:WebForm_DoCallback(
'__Page',document.all['ddDynamic'].value,UpdateText,null,null,false)">

Стандартная функция doPostBack весьма проста и служит для сохранения данных о событии в скрытые поля формы.

var theForm = document.forms['frmCallBack'];function __doPostBack(eventTarget, eventArgument) 
{ if (theForm.onsubmit == null || theForm.onsubmit()) { 
theForm.__EVENTTARGET.value = eventTarget; 
 theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); }}

При использовании функций с обратным вызовом механизм значительно сложнее. Код функции WebForm_DoCallback гораздо больше, чем doPostBack, поскольку эта функция определяет тип объектной модели браузера, после чего загружает необходимый для передачи данных с модуль. Например, для браузера поддерживающего DOM это будет Microsoft.XMLHTTP.
   Посмотреть код различных клиентских функций, используемых средой ASP.NET 2.0 можно сохранив страницу, поддерживающую функции с обратным вызовом на жесткий диск и открыв в текстовом редакторе файл WebResource.axd, ссылка на который имеется в HTML странице.
    Более подробное описание возможностей и области применения клиентских функций обратного вызова описано встатье Дино Эспозито.

Отправка данных формы другой странице ASP.NET

Существенное ограничением серверных форм в ASP.NET 1.0 – отсутствие возможности непосредственно передавать данные, введенные в форме, другой странице. Чтобы отправить значения элементов форму другой странице необходимо использовать простою HTML форму и в атрибуте action указать путь к странице, которая должна получить данные. При этом теряются преимущества использования серверных форм.
   В ASP.NET 2.0 тег элемента управления может иметь дополнительный атрибут PostBackUrl, позволяющий указать какой странице система должна передать Web-форму, если отправление данных на сервер инициировано этим элементом управления.

<form id="frmTest" runat="server"><asp:textbox id="txtFirstName" runat="server" /><br />
<asp:textbox id="txtLastName" runat="server" /><br />
<asp:button id="btnSend" Text="Post Data" PostBackUrl="crosspost.aspx"runat="server" /></form>

После щелчка по кнопке, браузер пользователя будет переадресован на страницу crosspost.aspx, при этом вся информация об элементах управления формы, с которой произошло отправление данных, будет также передано.
   Чтобы реализовать эту возможность, среда ASP.NET 2.0 осуществляет проверку ASPX страниц на предмет наличия элементов управления с заданным атрибутом PostBackUrl и, при наличии таковых, создает на странице дополнительное скрытое поле __PREVIOUSPAGE, которое и содержит информацию о состоянии элементов формы. Эта информация доступна странице-получателю через свойство PreviousPage.
 

void Page_Load(object sender, EventArgs e){ if (PreviousPage != null) {
// Получаем объекты отправленной формы 
TextBox txtFirstName =(TextBox)PreviousPage.FindControl("txtFirstName");
TextBox txtLastName =(TextBox)PreviousPage.FindControl("txtLastName");
// Используем данныеtxtInfo.Text = "Добрый день, " + txtFirstName.Text + "!";}}

На уровне HTML кода, отправка данных другой форме выглядит следующим образом.

<form method="post" action="GetValues.aspx" id="frmTest">
<input type="submit" name="btnSend" 
value="Post Data"onclick="javascript:WebForm_DoPostBackWithOptions(
new WebForm_PostBackOptions("btnSend", "", false,"", 
"CrossPage.aspx", false, false))" id="btnSend" /></form>

Из чего можно заключить, что данные формы не направляются из браузера непосредственно странице CrossPage.aspx, а предварительно направляются все той же странице GetValues.aspx, которая содержит форму frmTest. Это необходимо для поддержки серверной проверки (validation) введенных данных с использованием элементов управления RequiredFieldValidation, RangeValidation и других.Ознакомиться с методом WebForm_DoPostBackWithOptions можно в файле WebResource.axd, упомянутом в предыдущем параграфе этой статьи.

 
« Предыдущая статья   Следующая статья »