Callback и его отличие от Postback
Перед тем как рассмотреть примеры новой возможности обратного вызова, посмотрим на работу механизма возврата данных формы на сервер (Postback) типичной страницы ASP .NET.
Когда на странице инициируется событие отправки данных, запускается большой и сложный механизм.
InitLoad StateProcess Postback DataLoadPostback EventsSave StatePreRenderRenderUnload
В обычной ситуации постбэка событие на странице, например, щелчок на кнопке формы, вызывает отправку запроса HTTP POST web-серверу. Сервер обрабатывает запрос обработчиком IPostbackEvent Handler и запускает весь жизненный цикл страницы заново. Она загружает состояние страницы, обрабатывает введенные данные, обрабатывает события отправки, сохраняет состояние страницы, генерирует страницу заново и отправляет ее браузеру клиента. Страница полностью перезагружается, это занимает время и использует дополнительный трафик.
С другой стороны, можно задействовать возможность обратного вызова, как показано на рисунке.
В этом случае событие (например, нажатие на кнопку) вызывает выполнение скрипта-обработчика у клиента (функция JavaScript), который посылает асинхронный запрос web-серверу.
На сервере обработчик ICallbackEventHandler пропускает запрос через процесс, похожий на тот, который используется при постбэке, но некоторые крупные этапы этого процесса (например, отрисовка страницы) пропускаются. После того как информация загружена, результат возвращается к объекту, вызвавшему обратный вызов. Код скрипта вставляет эти данные в web-страницу, используя возможности JavaScript делать это без обновления страницы. Количество фаз жизненного цикла сокращается до 6:
InitLoad StateProcess Postback DataLoadCallBack EventUnload
Чтобы понять, как это работает, посмотрите на простой пример в следующем разделе.
Callback с параметрами
Теперь создадим страницу, которая использует обратный вызов с параметром. Наверху страницу поставим выпадающий список городов, который заполняется из web-сервиса, кнопку и строку ввода только для чтения для результата обратного вызова.
Страница просит выбрать город и вызывает серверный скрипт, чтобы запустить запрос к XML web-сервису на сервере. Web-сервис возвращает прогноз погоды для данной местности в текстовом формате:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Callback.aspx.cs" Inherits="Callback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Web Service Callback с параметром</title> <script type="text/javascript"> function GetTemp() { var City = document.forms[0].DropDownListCity.value; UseCallback(City, ""); } function GetTempFromServer(TextBox2, context) { document.forms[0].TextBox2.value = "В городе " + document.forms[0].DropDownListCity.value + " температура воздуха " + TextBox2; } </script> </head> <body> <form id="form1" runat="server"> <div> <asp:DropDownList ID="DropDownListCity" runat="server"> </asp:DropDownList> <br /> <input id="Button1" type="button" value="Get Temp" onclick="GetTemp()"/><br /> <asp:TextBox ID="TextBox2" runat="server" Width="634px" BackColor="#FFFFC0" Height="34px" ReadOnly="True"></asp:TextBox></div> </form> </body> </html>
using System; using System.Xml;
public partial class Callback : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler { string _callbackResult; protected void Page_Load(object sender, EventArgs e) { GlobalWeather ws = new GlobalWeather(); string results = ws.GetCitiesByCountry("Russia"); XmlDocument doc = new XmlDocument(); doc.LoadXml(results); XmlNode child = doc.ChildNodes[0]; foreach (XmlElement el in child.ChildNodes) { XmlElement city = el["City"]; DropDownListCity.Items.Add(city.InnerText); } string cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "GetTempFromServer", "context"); string cbScript = "function UseCallback(arg, context)" + "{" + cbReference + ";" + "}"; Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallback", cbScript, true); } public void RaiseCallbackEvent(string eventArg) { GlobalWeather ws = new GlobalWeather(); _callbackResult = ws.GetWeather(eventArg, "Russia").ToString(); XmlDocument doc = new XmlDocument(); doc.LoadXml(_callbackResult); XmlNode child = doc.ChildNodes.Item(1); XmlElement el = child["Temperature"]; _callbackResult = el.InnerText; } public string GetCallbackResult() { return _callbackResult; } }
Для работы этого примера нужно создать web-ссылку на сервис "http://www.webservicex.net/globalweather.asmx". Как работать с web-сервисами, описывалось в лекции 15.
Разница с клиентским обратным вызовом в том, что этот пример отправляет функции обратного вызова параметр.
Это делается в функции JavaScript GetTemp() на странице .aspx:
function GetTemp() { var City = document.forms[0].DropDownListCity.value; UseCallback(City, ""); }
Функция JavaScript читает значение, выбранное в DropDownListCity, и использует в качестве аргумента функции обратного вызова. Этот пример, как и предыдущий, обновляет страницу не полностью, а только необходимые ее части.
Использование JavaScript
В лекции 1 мы создали страницу, которая показывала время на сервере. Если пользователь находится в другом часовом поясе, время на его часах будет другое. Можно ли ее переделать, чтобы время совпадало с часами клиента? Ответ на этот вопрос — положительный. В страницу можно встроить код на JavaScript, который будет работать при загрузке страницы. Текст у метки менять нельзя, поэтому используем TextBox. Так как он — только для чтения и ширина границы равна 0, отличить его от метки сложно:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="time.aspx.cs" Inherits="time" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Время у клиента</title> </head> <body onload="javascript:document.forms[0]['ClientTime'].value=Date();"> <form id="form1" runat="server"> <div> <asp:TextBox ID="ClientTime" runat="server" BorderWidth="0px" ReadOnly="True" Width="500px"></asp:TextBox><br /> <input type="button" id="Button1" runat="server" value="Узнать время" onclick="Show()" /> </div> </form> </body> </html>
Свойство класса Page ClientScript позволяет определять для страницы клиентские сценарии.
Метод RegisterClientScriptBlock задает скрипт, который будет встроен в текст страницы:
protected void Page_Load(object sender, EventArgs e) { string myScript = @"function Show() { document.forms[0]['ClientTime'].value=Date(); }"; if (!Page.ClientScript.IsClientScriptBlockRegistered("MyScript")) Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript", myScript, true); }
<input type="button" ID="Button1" runat ="server" value="Узнать время" OnClick="Show()"/>
Первый аргумент — тип данной страницы, второй — идентификатор скрипта, который позволит отличить его от других скриптов, третий — текст сценария. Четвертый параметр — булевский, если он равен True, то теги <script type="text/javascript"> и </script> будут автоматически окружать текст функции. Страница, которая получится, обновляет время при каждом нажатии на кнопку.
Ее HTML-код выглядит так:
<html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"><title>
</title></head> <body onload="javascript:document.forms[0]['ClientTime'].value=Date();"> <form name="form1" method="post" action="Default2.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMjcxMzU0ODE3ZGQKqi3Rssxd/mXLs5G1HpFSaJ/j1A==" /> </div>
<script type="text/javascript"> <!-- function Show() { document.forms[0]['ClientTime'].value=Date(); }// --> </script>
<div> <input name="ClientTime" type="text" readonly="read- only" id="ClientTime" style="border-width:0px;width:500px;" /><br /> <input name="Button1" type="button" id="Button1" value=" " onclick="Show()" /> </div>
<div>
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALI- DATION" value="/wEWAwLS+f/WBwK8i8+nDwKM54rGBkVGyzaTKHVi8uFS3xL8ule0VqeH" /> </div></form> </body> </html>
Скрипт заключен в комментарии, чтобы все работало на старых браузерах. Он включен в текст до элементов управления.
Метод RegisterStartupScript похож на предыдущий, и отличие заключается в том, что скрипт выполняется при загрузке страницы, но после отображения всех элементов. Сам скрипт находится в конце описания формы. Парсер JavaScript не может обратиться к элементам, если они не описаны до функции. Если мы напишем скрипт, которые читает данные из формы, то попытка отображения страницы вызовет ошибку времени выполнения:
string myScript1 = @"alert(document.forms[0]['ClientTime'].value);"; Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "AlertScript", myScript1, true);
Значение поля в момент отображения скрипта еще не определено.
Поэтому нужно вызывать RegisterStartupScript:
string myScript1 = @"function Message() {alert(document.forms[0]['ClientTime'].value);}"; Page.ClientScript.RegisterStartupScript(this.GetType(), "AlertScript", myScript1, true);
Метод RegisterClientScriptInclude позволяет подключить внешний файл JavaScript. Например,
Page.ClientScript.RegisterClientScriptInclude("myKey", "ExternJavaScriptCode.js");
создает на выданной странице код
<script src="ExternJavaScriptCode.js" type="text/javascript"></script>
В этих примерах мы использовали не серверные командные кнопки, а элементы управления HTML. Причина заключается в том, что нажатие на командную кнопку отправляет форму на сервер. Событие OnClick выполняется на сервере. А в JavaScript существует свой OnClick. Как же его вызвать? Свойство Attributes позволяет обратиться к атрибутам элемента, даже тем, которые не соответствуют встроенным свойствам:
<asp:Button ID="Button2" runat="server" Text="Button" /> protected void Page_Load(object sender, EventArgs e) { Button2.Attributes.Add("onclick", "Show();return false"); }
return false нужно писать обязательно, иначе форма будет отправлена на сервер.
Эти функции можно применить к любым серверным элементам:
public static void AddConfirmMessage(WebControl ctl, string message) { ctl.Attributes.Add("onclick", "if ( ! confirm( '" + message + "' )) return false; "); }
public static void AddPopupMessage(WebControl ctl, string mes- sage) { ctl.Attributes.Add("onclick", "alert( '" + message + "'); "); }
Элемент управления FileUpload
Формы HTML позволяют загружать пользовательские файлы на сервер. Для этого нужно установить атрибут enctype как "multipart/form-data" и в нем должен находиться элемент <input type="file">. Элемент управления FileUpload облегчает эту работу. Нужно вставить его в форму, а enctype установится автоматически. Элемент состоит из строки ввода и кнопки с надписью Browse. Процесс загрузки начинается после подачи формы на сервер, обычно для этого вставляют еще одну кнопку:
<form id="form1" runat="server"> <div> <asp:FileUpload ID="FileUpload1" runat="server" /><br> <asp:Button ID="UploadButton" runat="server" Text="Button" OnClick="UploadButton_Click" /><br><br> <asp:Label ID="Message" runat="server" Text="Label" BackColor="#FFC0C0" Width="354px"></asp:Label> </div> </form>
После того как файл загружен, FileUpload позволяет узнать его свойства. Файл находится в кэше сервера, пока не будет сохранен на диск методом SaveAs:
protected void UploadButton_Click(object sender, EventArgs e) { if (this.FileUpload1.HasFile) { try { FileUpload1.SaveAs("c:\\Uploads\\" + FileUpload1.FileName); Message.Text = "Имя файла: " + FileUpload1.PostedFile.FileName + "<br>" + FileUpload1.PostedFile.ContentLength + " кб<br>" + "Content type: " + FileUpload1.PostedFile.ContentType; } catch (Exception ex) { Message.Text = "Ошибка: " + ex.Message.ToString(); } } }
Процесс сохранения может вызвать исключения, поэтому он заключен в блок try-catch.
Свойство PostedFile имеет тип HttpPostedFile. Можно перенаправить содержимое загруженного файла в файловый поток с помощью свойства InputStream.
MultiView
Элемент управления MultiView позволяет создавать несколько представлений одной страницы и переключаться с одного на другой. MultiView состоит из элементов View, в которых находится часть страницы. В каждый момент времени видимым является один из элементов View. Это определяется свойством ActiveViewIndex.
Например, можно создать многоязычную страницу. Пользователь сам выбирает нужный ему язык:
<asp:RadioButtonList ID="RadioButtonList1" runat="server" OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged" AutoPostBack="True"> <asp:ListItem Value="English"></asp:ListItem> <asp:ListItem Value="German"></asp:ListItem> <asp:ListItem Value="Russian"></asp:ListItem> </asp:RadioButtonList> <asp:MultiView ID="MultiView1" runat="server"> <asp:View ID="View1" runat="server" > <b>We are glad to meet you on our yellow pages.</b> <br /> <i>Information about over 8800 products and services.</i> </asp:View> <asp:View ID="View2" runat="server"> <b>Wir sind erfreut Sie auf unseren Gelb-Seiten zu emp- fangen!</b> <br /> <i>Wir stellen zur Eur VerfЯgung Informationen von Яeber 8800 Waren und Leistungen.</i> </asp:View> <asp:View ID="View3" runat="server"> <b>Мы рады приветствовать вас на нашем сайте.</b> <br /> <i>Предоставляем информацию о свыше чем 8800 товарах и услугах!</i> </asp:View> </asp:MultiView>
Переключение между представлениями происходит в обработчике списка переключателей RadioButtonList1:
protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e) { MultiView1.ActiveViewIndex = RadioButtonList1.SelectedIndex; }
Простой пример использования Callback
Посмотрим на простую страницу ASP .NET, которая использует эту возможность. В этом примере на странице есть кнопка HTML и серверный элемент управления TextBox.
Идея примера в том, что когда пользователь щелкает на кнопке на форме, запускается служба обратного вызова и в текстовое поле записывается случайное число:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SimpleCallback.aspx.cs" Inherits="SimpleCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Callback Page</title>
<script type="text/javascript"> function GetNumber(){ UseCallback(); } function GetRandomNumberFromServer(TextBox1, context){ document.forms[0].TextBox1.value = TextBox1; } </script>
</head> <body> <form id="form1" runat="server"> <div> <input id="Button1" type="button" value="Случайное число" onclick="GetNumber()" /> <br /> <br /> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </div> </form> </body> </html>
Суть происходящего в том, что страница посылает асинхронный запрос функции класса страницы. Получив ответ от этой функции, клиентский скрипт помещает полученное значение в строку ввода, не обновляя при этом страницы.
Запускает весь процесс функция JavaScript GetNumber — обработчик щелчка на кнопке.
Функция GetRandomNumberFromServer() находится на обратном конце процесса и записывает результат обратного вызова в Textbox1.
Класс этой страницы не только наследуется от Page, но и реализует интерфейс System.Web.UI.ICallbackEventHandler:
public partial class SimpleCallback : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler { private string _callbackResult = null; protected void Page_Load(object sender, EventArgs e) { string cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "GetRandomNumberFromServer", "context"); string cbScript = "function UseCallback(arg, context)" + "{" + cbReference + ";" + "}"; Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallback", cbScript, true); } public void RaiseCallbackEvent(string eventArg) { Random rnd = new Random(); _callbackResult = rnd.Next().ToString(); } public string GetCallbackResult() { return _callbackResult; } }
В этом интерфейсе определены 2 метода, которые необходимо реализовать, — RaiseCallbackEvent и GetCallbackResult, обе работают с запросами клиентских скриптов.
RaiseCallbackEvent позволяет получить со страницы данные, правда, только строкового типа. GetCallbackResult возвращает результат клиентскому скрипту, в данном случае GetRandomNumberFromServer — именно она зарегистрирована в качестве получателя результата.
Обработчик Page_Load включает создание функции, которая будет управлять запросами и ответами на стороне клиента.
Функция, которая ставится на клиенте для возможности обратного вызова, называeтся UseCallback(). Эта строка затем помещается на web-страницу, используя функцию Page.ClientScript.RegisterClientScriptBlock. Убедитесь, что имя, которое вы применяете здесь, такое же, как и в клиентской функции JavaScript:
<script type="text/javascript"> <!-- function UseCallback(arg, context) { WebForm_DoCallback('__Page',arg,GetRandomNumberFromServer,con- text,null,false); } // --> </script>
В результате получается страница, которая при нажатии на кнопку обновляет содержание текстовой строки, но не отрисовывает всю страницу. Есть лишь одно ограничение — здесь используется XmlHTTP и поэтому клиентский браузер должен его поддерживать (Internet Explorer 6.0, Mozilla FireFox 1.5 и Opera 9.0 поддерживают). Так это или нет, можно узнать с помощью свойств SupportsCallBack и SupportsXmlHTTP:
if (Page.Request.Browser.SupportsXmlHTTP == true) { }
Wizard
Как и MultiView, элемент управления Wizard (Мастер, Волшебник) может создать последовательность шагов. Элемент управления Wizard позволяет вводить информацию в нескольких формах последовательно. Например, при регистрации основные сведения — имя и пароль — вводятся на первой форме. После того как эти данные успешно введены и прошли проверку на валидность, собираются дополнительные данные — адрес, телефон. На последней форме введенные данные можно показать в обобщенном виде для подтверждения.
Wizard описывается с помощью тега asp:Wizard, в который вложены элементы WizardStep.
Внутри элемента управления Wizard находится MultiView, но в нем есть готовая функциональность по переключению представлений. Это дополнительная панель слева и набор кнопок внизу. В боковой панели находится список заголовков всех шагов, который позволяет произвольно переключаться на любой шаг.
Кнопки для перехода с шага на шаг — First, Next, Previous, Finish. На первой странице отображается только кнопка Next, на следующих — Previous и Next, и на последней — Previous и Finish. Если установить свойство DisplayCancelButton, к ним добавится кнопка отмены Cancel. Можно задать адрес страниц, куда будет перенаправлена форма при нажатии на кнопки Finish и Cancel. Как боковую панель, так и кнопочную панель навигации можно превратить в шаблоны. Показ боковой панели можно отключить свойством DisplaySideBar, установленным в False. Кнопки могут быть обычными или с любым изображением. Текст кнопок можно установить с помощью свойств CancelButtonText, FinishStepButtonText, FinishStepPreviousButtonText, NextStepButtonText, PreviousStepButtonText и the StartStepNextButtonText.
Заголовок тоже можно превратить в шаблон.
Например, превратим простую форму регистрации (из лекции 5) пользователей в мастера. В отличие от предыдущего примера, в форме создавать кнопки не нужно, так как у Wizard кнопки есть. При этом, если в форме поставлены элементы-валидаторы, переход на следующий шаг кнопкой Next невозможен:
<asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0" Height="297px" OnFinishButtonClick="Wizard1_FinishButtonClick" Width="609px" OnActiveStepChanged="Wizard1_ActiveStepChanged" DisplayCancelButton="True" HeaderText="Регистрация" BackColor="#F7F6F3" BorderColor="#CCCC- CC" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em"> <WizardSteps> <asp:WizardStep ID="Step1" runat="server" Title="Информация о пользователе"> <table> <tr> <td style="width: 100px"> <asp:Label ID="Label1" runat="server" Text="Введите имя:" Width="140px"></asp:Label> </td> <td style="width: 100px"> <asp:TextBox ID="txtName" runat="server" CausesValidation="True" Width="160px" /> </td> <td style="width: 29px"> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtName" ErrorMessage="Необходимо ввести имя">*</asp:RequiredFieldValidator> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label2" runat="server" Text="Введите адрес:" Width="140px"></asp:Label> </td> <td colspan="2"> <asp:TextBox ID="txtAddress" runat="server" TextMode="MultiLine" Rows="5" Width="187px" /> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label3" runat="server" Text="Введите пароль:" Width="140px"></asp:Label> </td> <td style="width: 100px"> <asp:TextBox ID="txtPassword1" runat="server" TextMode="Password" Width="145px" /> </td> <td style="width: 29px"> <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="Пароль не должен быть пустым" ControlToValidate="txtPassword1">*</asp:RequiredFieldValidator> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label4" runat="server" Text="Повторите пароль" Width="140px"></asp:Label> </td> <td style="width: 100px"> <asp:TextBox ID="txtPassword2" runat="server" TextMode="Password" Width="145px" /> </td> <td style="width: 34px" colspan="3"> <asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="Пароли должны совпадать!" ControlToValidate="txtPassword1" ControlToCompare="txtPassword2">*</asp:CompareValidator> </td> </tr> <tr> <td style="width: 300px; height: 49px;" colspan="3"> <asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowMessageBox="True" Width="349px" /> </td> </tr> </table> </asp:WizardStep> <asp:WizardStep ID="Step2" runat="server" Title="Контактная информация"> <table style="width: 336px; height: 199px"> <tr> <td style="width: 100px"> <asp:Label ID="Label5" runat="server" Text="Введите e-mail"></asp:Label> </td> <td style="width: 100px"> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> </td> </tr> <tr> <td style="width: 100px; height: 21px"> <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="Введите e-mail" ControlToValidate="TextBox1"></asp:RequiredFieldValidator> </td> <td style="width: 100px; height: 21px"> <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ErrorMessage="Не- правильный адрес" ValidationExpression="\w+([-+.']\w+)*@\w+([- .]\w+)*\.\w+([-.]\w+)*" ControlToValidate="TextBox1"></asp:RegularExpressionValidator> </td> </tr> <tr> <td style="width: 100px; height: 21px"> <asp:Label ID="Label6" runat="server" Text="Введите номер телефона"></asp:Label> </td> <td style="width: 100px; height: 21px"> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> </td> </tr> <tr> <td colspan="2"> <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ErrorMessage="Введите номер телефона" ControlToValidate="TextBox2"></asp:RequiredFieldValidator> </td> </tr> </table> </asp:WizardStep> <asp:WizardStep ID="Step3" runat="server" Title="Подтвержде- ние"> <table> <tr> <td style="width: 100px"> <asp:Label ID="Label7" runat="server" Text="Имя"></asp:Label> </td> <td style="width: 100px"> <asp:Label ID="Label8" runat="server" Text="Label"></asp:Label> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label9" runat="server" Text="E- mail"></asp:Label> </td> <td style="width: 100px"> <asp:Label ID="Label10" runat="server" Text="Label"></asp:Label> </td> </tr> <tr> <td style="width: 100px"> <asp:Label ID="Label11" runat="server" Text="Номер телефона"></asp:Label> </td> <td style="width: 100px"> <asp:Label ID="Label12" runat="server" Text="Label"></asp:Label> </td> </tr> </table> </asp:WizardStep> </WizardSteps> <StepStyle BorderWidth="0px" ForeColor="#5D7B9D" /> <SideBarStyle BackColor="#7C6F57" BorderWidth="0px" Font- Size="0.9em" VerticalAlign="Top" /> <NavigationButtonStyle BackColor="#FFFBFF" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284775" /> <SideBarButtonStyle BorderWidth="0px" Font-Names="Verdana" ForeColor="White" /> <HeaderStyle BackColor="#5D7B9D" BorderStyle="Solid" Font- Bold="True" Font-Size="0.9em" ForeColor="White" HorizontalAlign="Left" /> </asp:Wizard>
Для того чтобы на третьем шаге отображались данные, собранные в предыдущих шагах, перехватывается событие ActiveStepChanged:
protected void Wizard1_ActiveStepChanged(object sender, EventArgs e) { if (Wizard1.ActiveStep.ID == "Step3") { Label8.Text = ((TextBox)Wizard1.Controls[0].FindControl("txtName")).Text; Label10.Text = ((TextBox)Wizard1.Controls[0].FindControl("TextBox1")).Text; Label12.Text = ((TextBox)Wizard1.Controls[0].FindControl("TextBox2")).Text;
} }
Если у шага свойство AllowReturn установлено в False, то возврат к этому шагу будет невозможен. Другое интересное свойство — StepType. Оно позволяет заменить данный по умолчанию набор кнопок навигации. Шаг, у которого StepType равен Complete, не виден в боковой панели и будет показан после того, как в последнем шаге будет нажат Finish:
<asp:WizardStep Runat="server" Title="Final Step" StepType="Complete"> Спасибо за регистрацию.</asp:WizardStep>
В данном шаге какие-либо кнопки отсутствуют.
В этом курсе мы затронули
В этом курсе мы затронули только часть возможностей ASP .NET 2.0. В последнее время широко пропагандируется технология Ajax и основанная на ней технология Atlas от Microsoft. Объявлено о выходе .NET Framework 3.0. Поэтому и мне, и вам предстоит еще многому научиться.