Украина, Киев |
Управление состоянием страниц на клиенте
Упражнение 3. Восстановление состояния вида элемента списка через коллекцию запроса
Иногда состояние вида в элементе полезно отключить, чтобы уменьшить нагрузку на каналы связи. Но для некоторых элементов это нарушает их нормальную работу. Возьмем, например, списки ListBox и DropDownList. Когда они заполнены большим количеством элементов, объем пересылаемой информации состояния вида очень большой и это свойство лучше отключить. Для восстановления состояния выделенного элемента списка в этом случае можно воспользоваться информацией из коллекции Request.Form страницы.
- Добавьте к проекту страницу с именем ViewStateList.aspx без файла отделенного кода и назначьте ее стартовой
- Оформите страницу так, чтобы код разметки был следующим
<%@ Page Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div style="text-align: center"> <h2>Отключение состояния вида в списках</h2> <asp:ListBox ID="ListBox1" runat="server" Height="200px" Width="150px" /> <asp:DropDownList ID="DropDownList1" runat="server" Width="150px"> </asp:DropDownList><br /> <br /> <asp:Button ID="Button1" runat="server" Text="Отправить" /></div> </form> </body> </html>Листинг 35.7. Код интерфейсной части страницы ViewStateList.aspx
- Этому коду в режиме проектирования соответствует следующее представление
- Двойным щелчком на свободном месте страницы в режиме Design создайте блок скриптов с заготовкой обработчика Page_Load()
- Поместите в обработчик Page_Load() код заполнения списков видимым содержимым, который будет срабатывать при каждом запросе страницы
<script runat="server"> // Поле класса страницы private const int maxCount = 100; protected void Page_Load(object sender, EventArgs e) { // Заполняем списки программной генерацией значений for (int i = 0; i < maxCount; i++) { ListBox1.Items.Add("Опция " + (i + 1).ToString()); DropDownList1.Items.Add("Опция " + (i + 1).ToString()); } } </script>Листинг 35.8. Обобработчик Page_Load() для заполнения списков
- Выполните страницу и убедитесь, что при каждом новом запросе по щелчку на кнопке Submit отмеченные пользователем опции списков возвращаются сервером сохраненными
- После нескольких обратных отсылок щелкните правой кнопкой мыши в клиентской области окна броузера и выполните команду View Source, чтобы просмотреть HTML-содержимое, присланное сервером
Мы видим большое количество пересылаемой информации в скрытых полях, а также последовательное увеличение содержимого списков. Это происходит потому, что каждое новое состояние списков направляется клиенту для хранения вместе с очередным откликом сервера. При возвращении на сервер последнее состояние списков восстанавливается и к нему добавляется генерация новых значений, выполненных методом Add() в обработчике Page_Load().
Работает механизм автоматического сохранения состояния вида ASP.NET. Чтобы посмотреть, какой при этом получается объем пересылаемой информации, именно касающийся работы этого механизма, нужно включить работу ASP.NET в режиме выдачи трассировки на индивидуальных страницах. Это можно сделать, если добавить атрибут Trace="true" в директиву @ Page страницы, либо через утилиту WAT, запустив ее командой Website/ASP.NET Configuration (или щелкнуть на пиктограмме в панели Solution Explorer ).
- Запустите утилиту WAT, пойдите последовательно по ссылкам Application Configuration/Configure debugging and tracing и включите флажки " Capture tracing information " и " Display tracing information on ondividual pages "
- Закройте утилиту WAT
В результате этих действий файл конфигурации примет вид
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <trace enabled="true" pageOutput="true" /> <compilation debug="true" /> </system.web> </configuration>Листинг 35.9. Файл web.config после включения трассировки утилитой WAT
- Вновь запустите страницу ViewStateList.aspx, поманипулируйте с интерфейсными элементами, выполните обратную отсылку и проанализируйте секцию Control Tree в результатах трассировки, которая будет, примерно, такой
Объем пересылаемой по каналам связи в оба конца информации получается огромным до неприличия. Причем с каждой новой отсылкой он катастрофически нарастает, добавляя к прежним сохраненным значениям сгенерированные в коде новые значения списков. Отключим сохранение состояния вида в списках.
- Перейдите в режим Design редактора страницы ViewStateList.aspx, выделите одновременно оба списка и через панель Properties сбросьте их свойства EnableViewState в значение False
- Запустите страницу ViewStateList.aspx и убедитесь, что объем сохраняемого состояния вида для списков стал нулевым
- Вновь включите сброшенные свойства EnableViewState для списков
- Добавьте в директиву @Page общие для всех элементов страницы атрибуты EnableViewState = "false" и EnableEventValidation = "false"
Замечание. Если количество запросов превысит заданное параметром трассировки requestLimit значение (по умолчанию 10), то ASP.NET при исполнении не будет включать результаты трассировки в страницу. В этом случае нужно при очередном запуске тестового броузера вызвать через строку адреса страницу trace.axd и щелкнуть на ссылке " clear current trace " этой страницы. Включить безлимитную трассировку можно более просто - добавить в директиву @ Page страницы параметр Trace=true
<trace enabled="true" pageOutput="true" />
и добавьте в директиву @Page страницы атрибут Trace = "true", чтобы включить индивидуальную трассировку страницы
Мы видим, что при отключении сохранения состояния вида уменьшился и общий объем страницы. Но зато сервер в своих откликах не стал сохранять выбранные клиентом опции списков. Исправим этот недостаток программно, воспользовавшись тем фактом, что с каждым запросом выбранные значения передаются на сервер в словарь Request.Form объекта страницы.
- Добавьте к странице в конец обработчика Page_Load() код восстановления выбора пользователя в списках
<script runat="server"> // Поле класса страницы private const int maxCount = 100; protected void Page_Load(object sender, EventArgs e) { // Заполняем списки программной генерацией значений for (int i = 0; i < maxCount; i++) { ListBox1.Items.Add("Опция " + (i + 1).ToString()); DropDownList1.Items.Add("Опция " + (i + 1).ToString()); } // Отслеживание выделенных пользователем опций списков if (this.IsPostBack) { string text = this.Request.Form["ListBox1"]; ListBox1.Items.FindByText(text).Selected = true; text = this.Request.Form["DropDownList1"]; DropDownList1.Items.FindByText(text).Selected = true; } else ListBox1.SelectedIndex = DropDownList1.SelectedIndex = 0; } </script>Листинг 35.10. Код восстанавления состояния списков
Броузер с обратной отсылкой присылает на сервер значения выделенных элементов списка, собираемых дескриптором <form> из HTML-кода, представленного примерно таким фрагментом
<select size="4" name="ListBox1" id="ListBox1" style="height:200px;width:150px;"> <option selected="selected" value="Опция 1">Опция1</option> <option value="Опция 2">Опция 2</option> <option value="Опция 3">Опция 3</option> .................................................. </select>
Фактически броузер посылает пару ListBox1=Опция 1, которая попадает в словарь Request.Form, доступный для извлечения и использования в коде страницы на стороне сервера. Мы находим это значение в сгенерированной коллекции значений списка и настраиваем этот элемент коллекции как выделенный. После таких настроек список сгенерирует в текущем отклике сервера нужный HTML-код, соответствующий состоянию списка на клиенте перед обратной отсылкой.
- Запустите страницу ViewStateList.aspx с включенной трассировкой и убедитесь, что выбранные опции списков сохраняют свои позиции и ASP.NET генерирует небольшой объем клиентского кода
Таким образом мы выяснили, что состояние вида элементов управления, которое включено по умолчанию, не всегда является полезным либо просто не используется, и тогда его лучше отключать. Отключить состояние вида можно следующим образом:
- На уровне приложения для всех страниц в файле web.config текущего
узла web-дерева сайта
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <compilation debug="true" /> <pages enableViewState="false" /> </system.web> </configuration>
- На уровне страницы, добавив в директиву @ Page параметр EnableViewState="false" (в коде свойство Page.EnableViewState = false или this.EnableViewState = false )
- На уровне элемента управления, добавив в дескриптор элемента атрибут EnableViewState = "false" (в коде свойство Элемент .EnableViewState = false )
Если более общая настройка сохранения состояния вида выключена, а для каких-то страниц или элементов управления ее нужно включить, то в соответствующее место следует добавить атрибут EnableViewState = "true".