Программирование на ASP.NET

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

Разбить на страницы
Показывать лекцию целиком
Файлы к лекции Вы можете скачать здесь

Два высокоразвитых элемента управления MultiView и Wizard позволяют организовать для пользователя имитацию сложного многостраничного просмотра. Они содержат встроенные средства локальной навигации, обеспечивающие смену кадров с разным пользовательским интерфейсом, но единым оформлением.

Элемент управления MultiView

Элемент управления MultiView позволяет организовать страницу в виде множества вкладок. Каждая вкладка может содержать свой пользовательский интерфейс и обеспечивать свою форму представления одной и той же информации пользователя.

  • Создайте новый проект с именем
  • Переименуйте, для тренировки смелости в отношении модификации кода, сгенерированную страницу Default.aspx в MultiViewControl.aspx, в ее декларации @Page введите новое значение параметра Inherits="MultiViewControl", а в файле скрытого кода переименуйте класс в MultiViewControl (или не переименовывайте ни класс и Inherits, ни страницу, но я буду говорить об этих именах и код приводить с их использованием)
  • Поместите на страницу в режиме редактора Design из вкладки Standard компонент-контейнер MultiView
  • Поместите на страницу в режиме редактора Design внутрь созданного объекта MultiView1 из той же вкладки Standard три экземпляра компонента View. Компонент View называют представлением данных
  • В результате оболочка сгенерирует следующий дескрипторный код

    <%@ Page AutoEventWireup="true" 
           CodeFile="MultiViewControl.aspx.cs" 
    	   Inherits="MultiViewControl" 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>
            <asp:MultiView ID="MultiView1" runat="server">
                <asp:View ID="View1" runat="server">
                </asp:View>
                <asp:View ID="View2" runat="server">
                </asp:View>
                <asp:View ID="View3" runat="server">
                </asp:View>
            </asp:MultiView></div>
        </form>
    </body>
    </html>
  • Запустите приложение и вы получите чистый экран броузера, поскольку созданные вкладки - представления еще не были заполнены интерфейсными элементами и показать им нечего
  • Замечание. Представления View можно добавлять и программно по мере необходимости (как и любой другой элемент управления). Для этого нужно создать экземпляр (например, View1 ) нового представления и добавить ссылку на него в коллекцию Views экземпляра (например, MultiView1 ) элемента MultiView с помощью MultiView1.Views.Add(View1) или MultiView1.Views.AddAt(index, View1). Свойство Views определено в классе System.Web.UI.WebControls.ViewCollection, который и имеет указанные методы Add() и AddAt(). Но мы будем для простоты использовать декларативный способ этапа проектирования.

    Web-форма в оболочке после наших действий будет иметь вид

    Visual Studio 2005 во время проектирования показывает все представления View в раскрытом виде, но на этапе выполнения на странице может отображаться только одно из них, которое раскроет пользователь. Каждое представление можно редактировать в оболочке точно также, как любую часть обычной страницы.

    Будет ли при загрузке страницы раскрыто какое-либо представление или нет, определяется свойством MultiView.ActiveViewIndex, доступном и на этапе проектирования и программно. Если значение этого свойства равно "-1", то при начальной загрузке страницы ни одна из вкладок не будет раскрыта. Если свойство установлено в ноль, то будет раскрыта первая вкладка и т.д.

    Давайте продолжим выполнение нашего примера и наполним представления каким-нибудь содержимым.

  • Поместите в корневую папку сайта какой-нибудь рисунок щадящего Web-формата ( *.gif, *.jpg, *.png ). Один из вариантов рисунка, файл MyPhoto.jpg, прилагается...
  • Поместите в представление View1 из вкладки Standard компонент Image (контейнер для рисунка) и декларативно настройте его так:
  • ImageUrl="~/MyPhoto.jpg". Символ ~ (тильда) обозначает корень виртуального каталога сайта
  • Поместите в представление View2 какой-нибудь текст
  • Поместите в представление View3 элемент Calendar из вкладки Standard и настройте его внешний вид
  • Выделите объект MultiView1 и установите его свойство ActiveViewIndex в значение ноль, чтобы при начальной загрузке страницы было открыто первое представление
  • Управление отображением представлений

    Вариант 1

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

  • Поместите на форму страницы впереди элемента MultiView1 компонент DropDownList из вкладки Standard
  • Установите для списка свойство AutoPostBack в значение True, чтобы при выборе нового пункта автоматически выполнялась обратная отсылка
  • Выделите экземпляр DropDownList1 и через панель Properties в режиме Events создайте обработчик события SelectedIndexChanged
  • Дескрипторное представление страницы будет таким

    <%@ Page AutoEventWireup="true" 
        CodeFile="MultiViewControl.aspx.cs" 
        Inherits="MultiViewControl" Language="C#" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления множеством представлений</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:DropDownList ID="DropDownList1" runat="server"
                    AutoPostBack="True"
                    OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
                </asp:DropDownList><br />
                <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
                    <asp:View ID="View1" runat="server">
                        <h1>Мое фото</h1>
                        <asp:Image ID="Image1" runat="server" ImageUrl="~/MyPhoto.jpg" />
                    </asp:View>
                    
                    <asp:View ID="View2" runat="server">
                        <h1>Мои стихи</h1>
                        <p>
                            У Лукоморья дуб зеленый<br />
                            Златая цепь на дубе том<br />
                            И днем и ночью кот ученый<br />
                            Все ходит по цепи кругом
                        </p>
                    </asp:View>
                    
                    <asp:View ID="View3" runat="server">
                        <h1>Мой календарь</h1>
                        <asp:Calendar ID="Calendar1" runat="server" BackColor="#C0FFFF" 
                            BorderColor="Red" BorderStyle="Ridge">
                        </asp:Calendar>
                    </asp:View>
                </asp:MultiView>
            </div>
        </form>
    </body>
    </html>
  • Поместите в файл MultiViewControl.aspx.cs следующий код
  • using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Заполняем список только при первом запросе страницы,
            // а потом все будет сохраняться в состоянии вида.
            // Иначе список всегда будет переустанавливаться в начало
            if (!IsPostBack)
            {
                // Подсоединяем коллекцию с вкладками к списку
                DropDownList1.DataSource = MultiView1.Views;
                // Назначаем идентификатор, значениями которого
                // будут заполнены поля "Text" списка
                DropDownList1.DataTextField = "ID";
                // Заполняем список подсоединенными данными
                DropDownList1.DataBind();
    	
                // Отображаем первое представление
                MultiView1.ActiveViewIndex = 0;
                // Синхронизируем список
                DropDownList1.SelectedIndex = 0;
        
                // Выделяем текущую дату 
                Calendar1.SelectedDate = DateTime.Now.Date;
                Calendar1.SelectedDayStyle.BorderStyle = BorderStyle.Solid;
            }
        }
    	
        // Обработчик события выбора в списке
        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    }
  • Выполните страницу, результат должен быть не менее лучезарным, чем этот...
  • Вариант 2

    В обработчике события Page_Load() мы, для тренировки, вставили код, чтобы при первом запросе страницы список программно заполнялся значениями атрибутов ID представлений. Этого можно и не делать, если вручную на этапе проектирования заполнить свойство Items списка более осмысленными именами.

    Мы, также, назначили для списка AutoPostBack="True", чтобы он индивидуально осуществлял обратную отсылку. Ну, а если на странице будет много интерфейсных элементов с возможностью постинга, которые должен будет настроить пользователь. В этом случае будет расточительно, что каждый элемент интерфейса при настройке индивидуально посылает страницу на сервер для обновления. Лучше предусмотреть отдельную кнопку, которая отдаст команду броузеру на обратную отсылку после настройки всех интерфейсных элементов. Выполним эти модификации на новой странице.

  • Через панель Solution Explorer выполните копию страницы MultiViewControl.aspx и присвойте копии новое имя MultiViewControl1.aspx.
  • Обратите внимание, что файл кода .cs автоматически копируется и переименовывается вместе со страницей. Более того, в оболочке даже не предусмотрена возможность переименовать его отдельно, пока он связан со страницей. Правда, его можно скопировать отдельно, тогда он переименовывается.

  • Выполните команду меню Window/Close All Documents, чтобы закрыть все прежние окна редактирования рабочей области оболочки
  • Откройте новую страницу MultiViewControl1.aspx на редактирование и выполните команду меню Website/Set As Start Page, чтобы сделать теперь ее стартовой при запуске из оболочки
  • Выделите список через панель Properties и сбросьте его свойство AutoPostBack в False
  • Через раскрывающийся список в верхней части панели Properties выделите объект MultiView1 и задайте ActiveViewIndex=-1, чтобы ни одно представление при первой загрузке страницы у пользователя не было раскрыто
  • В файле MultiViewControl1.aspx.cs полностью очистите обработчик события Page_Load(), код которого в предыдущем примере программно заполнял список (можно полностью удалить этот обработчик, нам он здесь не понадобится)
  • Сейчас мы должны заполнить список декларативно (на этапе проектирования).

  • Выделите список и заполните его свойство Items так
    Декларативные настройки объекта DropDownList1
    Items[i] Text Value
    Items[0] Моя фотография не имеет значения ...
    Items[1] Мои стихи не имеет значения ...
    Items[2] Встроенный календарь не имеет значения ...
  • Добавьте на новую страницу справа от списка кнопку Input (Submit) из вкладки HTML панели Toolbox (воспользуемся простой кнопкой) и задайте ей Value=Show; Title=Раскрыть вкладку
  • Запустите приложение и неизменяя список понажимайте кнопку Show.
  • Ничего не происходит, пока в списке мы не выбирем новый пункт. Только после этого свойство MultiView1.ActiveViewIndex примет отличное от -1 значение и представления при обратной отсылке начнут работать. Чтобы исправить это, нужно код присвоения значения свойству ActiveViewIndex переместить в обработчик нажатия кнопки.

  • Создайте обработчик для кнопки ID=Submit1 двойным щелчком на ней мышью
  • Мы видим, что оболочка создала код заготовки JavaScript -сценария, который мы должны заполнить и который страница готова посылать на клиентский броузер. Чтобы не вникать в JavaScript приведем в свое оправдание аргумент, что поддержка сценариев JavaScript - дело ненадежное, поскольку пользователь может в своем броузере ее отключить.

  • Удалите созданный оболочкой предыдущим действием код JavaScript -сценария. Для этого в режиме Source поместите текстовый курсор редактора внутрь блока кода <script language="javascript" type="text/javascript">..|..</script> и в нижней части рамки окна редактора щелкните на кнопке <script>. Весь выделенный код можно удалять
  • Удалите из дескриптора <input> кнопки Submit1 onclick="return Submit1_onclick()", сгенерированный оболочкой
  • Щелкните на Submit1 правой кнопкой мыши и выполните команду Run As Server Control. Этим действием в дескриптор <input> будет добавлен атрибут runat="server", который заставит ASP.NET запускать обработчик кнопки (если мы его предусмотрим), если с броузера с обратной отсылкой будет прислано событие, что клиент щелкал на этой кнопке
  • Выделите список DropDownList1 и через панель Properties в режиме Events очистите поле события SelectedIndexChanged
  • Двойным щелчком на, теперь уже серверной, кнопке Submit1 создайте для нее обработчик в файле MultiViewControl1.aspx.cs
  • Перенесите код обработчика события SelectedIndexChanged в код нового обработчика, а старый обработчик удалите
  • В результате код файла будет таким

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        // Обработчик события на кнопке Submit1
        protected void Submit1_ServerClick(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    }
  • Выполните страницу
  • Теперь по прибытию на сервер обратной отсылки система ASP.NET распознает присланное событие щелчка на кнопке. Свойству MultiView1.ActiveViewIndex в обработчике события кнопки присваивается значение выбранной пользователем опции списка. Клиенту страница отправляет содержимое вкладки, соответствующей его выбору.

    Добавление в представления функций навигации

    В предыдущих примерах мы знакомились с механизмом работы элемента MultiView. Мы использовали для смены вкладок внешний по отношению к MultiView элемент списка. Но MultiView имеет собственные средства для перехода по своим вкладками. Рассмотрим эти возможности.

    Серверные элементы Button, ImageButton, LinkButton реализуют интерфейс System.Web.UI.WebControls.IButtonControl, от которого наследуют способность генерировать не только событие Click, но и событие Command. Такие элементы управления называются кнопочными. Они реализуют ряд полезных свойств интерфейса, таких как CommandArgument, CommandName и др.

    В свою очередь, элемент управления MultiView содержит общедоступные переменные (поля), которые ожидают поступления определенных команд, чтобы MultiView соответствующим образом их исполнил.

    Ниже приведены команды, которые ожидает MultiView.

    Имена команд, которые может распознать MultiView
    Поле Ждет команду Описание действия MultiView
    NextViewCommandName NextView Переход к следующему представлению. Команда является значением свойства CommandName кнопочного элемента
    PreviousViewCommandName PrevView Переход к предыдущему представлению. Команда является значением свойства CommandName кнопочного элемента
    SwitchViewByIDCommandName SwitchViewByID Переход к представлению со значением идентификатора ID, переданным из свойства CommandArgument кнопочного элемента управления
    SwitchViewByIndexCommandName SwitchViewByIndex Переход к представлению с определенным индексом, переданным из свойства CommandArgument кнопочного элемента управления

    Воспользуемся описанным механизмом в нашем примере. Развитие примера выполним на копии.

  • В панели Solution Explorer скопируйте страницу MultiViewControl1.aspx, присвойте копии имя MultiViewControl2.aspx и сделайте эту страницу стартовой
  • Из вкладки Standard панели Toolbox поместите в первое и последнее представления по одной серверной кнопке Button, а в среднее - две кнопки
  • Настройте кнопки как показано в таблице
  • Настройка кнопок навигации на представлениях
    Представление Свойство Значение
    Views[0] ID btnNext0
    Text Next >
    CommandName NextView
    Views[1] ID btnPrev1
    Text < Prev
    CommandName PrevView
    ID btnNext1
    Text Next >
    CommandName NextView
    Views[2] ID btnPrev2
    Text < Prev
    CommandName PrevView

    У нас в обработчике кнопки Submit1 выполняется синхронизация выбранного пункта списка и активного представления. Если теперь осуществлять переход по представлениям введенными кнопками навигации, то обратной синхронизации представлений со списком не будет. Исправим это...

  • Установите редактор страницы в режим Design
  • В панели Properties в верхнем раскрывающемся списке выберите объект MultiView1, переведите панель в режим Events (кнопка с пиктограммой молнии) и двойным щелчком на поле события ActiveViewChanged создайте обработчик, который заполните кодом синхронизации списка
  • В результате файл поддержки страницы должен быть таким

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        // Обработчик события на кнопке Submit1
        // Синхронизация представлений со списком
        protected void Submit1_ServerClick(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    	
        // Синхронизация списка с представлениями
        protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
        {
            DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;
        }
    }

    Файл дескрипторного представления будет таким

    <%@ Page AutoEventWireup="true" 
        CodeFile="MultiViewControl2.aspx.cs" 
        Inherits="MultiViewControl" Language="C#" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления множеством представлений</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:DropDownList ID="DropDownList1" runat="server">
                    <asp:ListItem>Моя фотография</asp:ListItem>
                    <asp:ListItem>Мои стихи </asp:ListItem>
                    <asp:ListItem>Встроенный календарь</asp:ListItem>
                </asp:DropDownList>
                
                <input id="Submit1" type="submit" value="Show" 
                    title="Раскрыть вкладку" runat="server" 
                    onserverclick="Submit1_ServerClick" /><br />
                    
                <asp:MultiView ID="MultiView1" runat="server" 
                    OnActiveViewChanged="MultiView1_ActiveViewChanged">
                    <asp:View ID="View1" runat="server">
                        <h1>
                            Мое фото</h1>
                        <asp:Image ID="Image1" runat="server" 
                            ImageUrl="~/MyPhoto.jpg" /><br />
                        <br />
                        <asp:Button ID="btnNext0" runat="server" 
                            CommandName="NextView" Text="Next >" />
                    </asp:View>
                    
                    <asp:View ID="View2" runat="server">
                        <h1>
                            Мои стихи</h1>
                        <p>
                            У Лукоморья дуб зеленый<br />
                            Златая цепь на дубе том<br />
                            И днем и ночью кот ученый<br />
                            Все ходит по цепи кругом
                        </p>
                        <asp:Button ID="btnPrev1" runat="server" 
                            CommandName="PrevView" Text="< Prev" />
                        <asp:Button ID="btnNext1" runat="server" 
                            CommandName="NextView" Text="Next >" />
                    </asp:View>
                    
                    <asp:View ID="View3" runat="server">
                        <h1>
                            Мой календарь</h1>
                        <asp:Calendar ID="Calendar1" runat="server" 
                            BackColor="#C0FFFF" BorderColor="Red"
                            BorderStyle="Ridge" />
                        <br />
                        <asp:Button ID="btnPrev2" runat="server" 
                            CommandName="PrevView" Text="< Prev" />
                    </asp:View>
                </asp:MultiView>
            </div>
        </form>
    </body>
    </html>
  • Выполните страницу и убедитесь, что все работает как нужно
  • Хороший элемент, что и говорить. Но есть один существенный недостаток. Поскольку хранится несколько представлений, то мы должны быть готовы вернуться к любому представлению, если его повторно вызовет пользователь. Это значит, что мы должны сохранять состояние вида всех представлений, в том числе и невидимых в данный момент. Из-за этого элемент посылает на клиентскую машину большой объем кода состояния вида. От этой неприятности можно избавиться, отключив свойство EnableViewState.

    Еще одна особенность, о которой стоит помнить. Элемент MultiView не является контейнером для имен элементов управления на вкладках. Это значит, что в пределах страницы все элементы управления должны иметь уникальные значения идентификаторов ID, иначе компилятор заблудится.

    Элемент управления Wizard

    Элемент управления Wizard (мастер) является более развитым, чем элемент MultiView. Он имеет богатую настраиваемую функциональность, включающую в себя

  • Возможность последовательного отображения одного или нескольких представлений
  • Встроенные кнопки навигации
  • Встроенное боковое меню со ссылками на выполняемые шаги-вкладки
  • Стили и шаблоны
  • Содержимым шагов -вкладок мастера являются Web- и HTML-элементы управления, обычно используемые при построении страниц. Рассмотрим последовательно свойства элемента управления Wizard на примерах.

  • Добавьте новую страницу с именем WizardControl.aspx и файлом отделенного кода. Назначьте ее стартовой
  • В режиме Design редактора поместите на страницу элемент управления Wizard из вкладки Standard панели Toolbox
  • Будет сгенерирована такая заготовка

    Дескрипторное представление заготовки будет таким

    <%@ Page Language="C#" AutoEventWireup="true" 
        CodeFile="WizardControl.aspx.cs" Inherits="WizardControl" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления Wizard</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0">
                    <WizardSteps>
                        <asp:WizardStep runat="server" Title="Step 1">
                        </asp:WizardStep>
                        <asp:WizardStep runat="server" Title="Step 2">
                        </asp:WizardStep>
                    </WizardSteps>
                </asp:Wizard>
            </div>
        </form>
    </body>
    </html>

    Дальнейшей задачей программиста будет настройка этой заготовки в полноценный элемент управления. Оболочка предоставляет широкие возможности для разработчика на этапе проектирования. Кроме традиционной панели свойств Properties элемент Wizard имеет дополнительную локальную панель задач для оперативных действий по настройке. Чтобы вызвать локальную панель задач элемента Wizard, нужно щелкнуть мышью на пиктограмме в виде треугольника в его правом верхнем углу

    В элементе управления MultiView все представления на этапе проектирования раскрыты для разработчика. Для элемента Wizard оболочка Visual Studio 2005 показывает разработчику представление только одного текущего шага.

    Чтобы создать новые шаги мастера, нужно:

  • просто добавлять в его контейнер дескрипторы <asp:WizardStep>
  • или через локальную панель задач выполнить опцию Add/Remove WizardSteps
  • или в панели Properties вызвать на редактирование свойство WizardSteps
  • Обратите внимание, что по умолчанию дескрипторы <asp:WizardStep> шагов-вкладок не имеют значения идентификатора ID. Здесь подразумевается, что для такого сложного элемента управления разработчику достаточно декларативной настройки. Если же в дальнейшем разработчик предполагает программно управлять шагами мастера, то без атрибутов ID не обойтись.

    В приведенном окне редактирования коллекции шагов-вкладок наиболее существенными являются следующие свойства дескриптора <asp:WizardStep>

    Некоторые свойства дескриптора <asp:WizardStep>
    Свойство Описание
    Title Имя шага, видимое пользователю в ссылках на боковой панели слева
    StepType Это свойство определяет тип кнопок навигации, которые будут предъявлены пользователю данным шагом, и равно одному из значений перечисления System.Web.UI.WebControls.WizardStepType.WizardStepType:
  • Auto - определяется по умолчанию и устанавливает тип кнопки в зависимости от местонахождения шага в коллекции. Если шаг стоит на первом месте, то будет кнопка Start, во всех промежуточных позициях - кнопка Step, если на последнем месте - будет кнопка Finish
  • Complete - не показывает никаких кнопок и скрывает боковую панель
  • Finish - показывает кнопки Finish и Previous
  • Start - показывает кнопку Next
  • Step - показывает кнопки Next и Previous
  • AllowReturn Показывает, может ли пользователь возвращаться к этому шагу после того, как его пройдет. Если это свойство имеет значение false, то как только пользователь пройдет этот шаг, он не сможет вернуться назад. Потому что все ссылки, ведущие к этому пройденному шагу, немедленно будут блокированы.

    Наполним шаги мастера конкретным содержимым - элементами управления, и настроим их свойства. Всего создадим четыре шага, в которых разместим:

  • WizardStep1 - раскрывающийся список DropDownList
  • WizardStep2 - список радиокнопок RadioButtonList
  • WizardStep3 - текстовое поле TextBox
  • WizardStep4 - обычный текст
  • Оболочка Visual Studio 2005 все отличные от значений по умолчанию свойства элементов сохраняет в дескрипторах текстового файла .aspx как дополнительные атрибуты. Более того, при установке значений отдельным свойствам оболочка сама генерирует новые дескрипторы и даже целые блоки кода. Поэтому все декларативные настройки сложных элементов управления нужно выполнять через панель Properties, но для краткости изложения приведем уже готовый код настройки страницы нашего примера.

    <%@ Page Language="C#" AutoEventWireup="true" 
        CodeFile="WizardControl.aspx.cs" Inherits="WizardControl" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления Wizard</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Wizard ID="Wizard1" runat="server" BackColor="#EFF3FB" 
                    BorderColor="#B5C7DE"
                    BorderWidth="1px" Width="100%" ActiveStepIndex="0" 
                    StartNextButtonText="Далее >"
                    StepNextButtonText="Далее >" StepPreviousButtonText="< Назад" 
                    FinishCompleteButtonText="Готово" FinishPreviousButtonText="< Назад" 
                    HeaderText="Жизненно важная анкета!">
                    <WizardSteps>
                        <asp:WizardStep ID="WizardStep1" runat="server" Title="Друзья">
                            <h3>
                                Какой президент самый лучший?</h3>
                            <asp:DropDownList ID="DropDownList1" runat="server">
                                <asp:ListItem>Наш Путин</asp:ListItem>
                                <asp:ListItem>Их Клинтон</asp:ListItem>
                                <asp:ListItem>Похожий на Чингиз-Хана</asp:ListItem>
                                <asp:ListItem>Вы сами</asp:ListItem>
                                <asp:ListItem>Ваша соседка</asp:ListItem>
                            </asp:DropDownList>
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep2" runat="server" Title="Туризм">
                            <h2>
                                Где Вы были с 19 по 21 августа 1991 года?</h2>
                            <asp:RadioButtonList ID="RadioButtonList1" runat="server">
                                <asp:ListItem>На Красной площади</asp:ListItem>
                                <asp:ListItem>На Луне</asp:ListItem>
                                <asp:ListItem>В чужом огороде</asp:ListItem>
                                <asp:ListItem>У тетеньки</asp:ListItem>
                                <asp:ListItem>В ауте</asp:ListItem>
                            </asp:RadioButtonList>
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep3" runat="server" Title="Встречи">
                            <h3>
                                Кайтесь! Место встречи изменить нельзя!</h3>
                            Ваш ИНН:
                            <asp:TextBox ID="TextBox1" runat="server" />
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep4" runat="server" Title="Досуг">
                            <h2>
                                Мера поощрения</h2>
                            Усиленная диета + клизьма ззз перцем!
                        </asp:WizardStep>
                    </WizardSteps>
                    <HeaderStyle BackColor="Blue" Font-Bold="True" Font-Size="X-Large" ForeColor="Yellow" />
                </asp:Wizard>
            </div>
        </form>
    </body>
    </html>

    Несколько замечаний:

  • Такой дурашливый текст Вы должны изменить (Технари могут себе позволить, пока Органы отдыхают, а "Утомленные Солнцем" доценты - тем более)
  • Боковую панель навигационных ссылок можно отключать свойством Wizard.DisplaySideBar="False"
  • Оболочка в режиме проектирования автоматически изменяет значение свойства Wizard.ActiveStepIndex при редактировании текущего шага. Поэтому, чтобы страница при запуске показала первый шаг, небходимо в конце редактирования либо на него перейти, либо установить Wizard.ActiveStepIndex ="0"
  • Мы еще ничего не программировали, а уже успели добиться такой мощной функциональности страницы
  • Последний дескриптор кода <HeaderStyle> определяет стиль заголовочного блока элемента Wizard, о чем мы еще поговорим ниже
  • Запустите страницу с настроенным элементом Wizard и "подывитесь", какой же все-таки Большой Билл умный, да еще так вовремя - какие масштабы и горизонты открывают для нас эти его инструменты (ну, прямо, Эльдорадо!)
  • События элемента Wizard

    До сих пор мы занимались настройками Wizard в режиме проектирования, пришла пора приступить к программированию его времени выполнения. Мы уже говорили, что для разработчика задача управления объектами страницы во время выполнения сводится к созданию и программированию обработчиков событий, на которые могут реагировать эти объекты. Ниже перечислены события, на которые может реагировать экземпляр класса Wizard.

    События, поддерживаемые элементом Wizard
    Событие Описание
    ActiveStepChanged Ага! Пользователь переключился на новый шаг или наш код изменил свойство ActiveStepIndex
    CancelButtonClick Ага! Пользователь щелкнул на кнопке Cancel (Отмена). Кнопка Cancel по умолчанию не отображается, однако ее можно добавить во все представления Step сразу, если установить свойство Wizard.DisplayCancelButton="True". Кнопка Cancel инициирует обратную отсылку, и если не предусмотреть соответствующего обработчика, то ничего не происходит. Но если одновременно определено свойство Wizard.CancelDestinationPageUrl, например, CancelDestinationPageUrl="~/MultiViewControl.aspx", то по щелчку пользователя на этой кнопке ему отправляется другая страница
    FinishButtonClick Ага! Пользователь дошел до последнего шага и щелкнул на кнопке Finish
    NextButtonClick, PreviousButtonClick Эти события возникают при щелчке на кнопке Next или Previous на любом шаге. Но сменить шаг пользователь может и через боковую панель. Чтобы такой момент не упустить и однозначно среагировать на смену шага, лучше вместо этих событий обрабатывать событие ActiveStepIndex
    SideBarButtonClick Ага! Пользователь щелкнул на ссылке в области боковой панели
    Чувствуете?!!! Мы сидим со своим кодом на другом конце провода и ждем очередных пожеланий ненасытного пользователя. При получении от него очередного запроса мы анализируем выбор по присланным событиям и пакуем для него новую посылку, в которую закладываем и требуемый текущий ответ, и интерфейсные элементы для ввода новых пожеланий. Да все это еще должно быть красивым, блестящим и пушистым. Вот Большой Билл нам здесь и помогает - осталось только руки приложить.

    Используем событие FinishButtonClick, чтобы усовершенствовать наш пример. Когда пользователь щелкнет в последнем шаге на кнопке Finish (Готово), соберем его выбор с каждого шага и вернем в раскрытом представлении этого последнего шага.

  • Откройте страницу WizardControl.aspx в режиме Design и перейдите на последний шаг WizardStep4 для его редактирования
  • Поместите в середину контекста текстовую метку
  • Выделите объект Wizard1 и через панель свойств в режиме Events создайте обработчик для события FinishButtonClick
  • Заполните обработчик следующим кодом
    (рис ) Обработчик события FinishButtonClick в файле WizardControl.aspx.csusing System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class WizardControl : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    	
        }
    	
        protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
        {
            // Библиотека Framework 2.0 в нашем распоряжении
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("<h3>");
            sb.Append("Вы выбрали: <br />");
            string title;
    	
            title = WizardStep1.Title;
            sb.Append(title + ": " + DropDownList1.Text + "<br />");
    
            title = WizardStep2.Title;
            int index = RadioButtonList1.SelectedIndex;
            if(index != -1) // Если что-то выбрал
                sb.Append(title + ": " + RadioButtonList1.Items[index].Text + "<br />");
    	
            /*  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
            // Для элемента класса CheckBoxList нужно проверять коллекцию:
            CheckBoxList CheckBoxList1;
            foreach (ListItem item in CheckBoxList1.Items)
            {
                if (item.Selected)
                    sb.Append(item.Text + "; ");
            }
                !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
    	
            title = WizardStep3.Title;
            if (TextBox1.Text.Length > 0)// Если что-то ввел
                sb.Append(title + ": " + TextBox1.Text + "<br /></br />");
    	
            sb.Append("</h3>");
    	
            sb.Append("Вам рекомендуется:");
    	
            // Отображаем собранные данные
            lblSummary.Text = sb.ToString();
        }
    }
  • Перейдите в режиме Design на первый шаг WizardStep1, чтобы автоматически установилось в ноль значение свойства ActiveStepIndex объекта Wizard1 и пользователю вначале отображался первый шаг
  • Выполните страницу, заполните анкету и на последнем шаге щелкните на кнопке
  • Стили элемента Wizard

    Элемент Wizard содержит средства, позволяющие легко менять его внешний вид. В нем можно задавать собственный пользовательский интерфейс, отличный от интерфейса по умолчанию. Через высокоуровневые свойства можно управлять цветами, шрифтами, интервалами и стилями границ, настраивать внешний вид каждой кнопки, добавлять верхний колонтитул и т.д.

    Например, для кнопки StartNext применяются следующие свойства:

    Некоторые свойства для настройки кнопок
    Свойство Описание
    StartNextButtonImageUrl Задает изображение для изображения-кнопки
    StartNextButtonStyle Использует стили внешней каскадной таблицы стилей CSS
    StartNextButtonText Настраивает текст кнопки или ссылки
    StartNextButtonType Определяет кнопку, ссылку или выбираемое изображение-кнопку

    Среди свойств компонента Wizard есть общие стили, затрагивающие настройки всех элементов, а есть индивидуальные для каждой группы элементов. Следует помнить, что если одновременно определены те и другие стили, то конфликта не будет, просто индивидуальные параметры настройки переопределят (отменят) общие стили. В языках программирования используется тот же принцип, переменная локальной области видимости переопределяет (делает недоступной) в текущем блоке кода одноименную переменную внешней области видимости.

    Ниже приведены свойства мастера Wizard, определяющие общие и индивидуальные стили его отдельных областей.

    Свойства Wizard, определяющие стили его элементов
    Стиль Описание
    ControlStyle Наследуется Wizard от класса WebControl и применяется ко всем его разделам
    HeaderStyle Применяется к разделу верхнего колонтитула, который будет отображаться только в том случае, если будет задан какой-нибудь текст в свойстве Wizard.HeaderText
    SideBarStyle Применяется к области боковой панели с кнопками
    SideBarButtonStyle Определяет стиль кнопок боковой панели
    StepStyle Применяется к компонентам представления, включенным в текущий шаг
    NavigationStyle Применяется к нижней области шагов, в которых расположены навигационные кнопки
    NavigationButtonStyle Применяется только к кнопкам навигации в области навигации
    StartNextButtonStyle Применяется к кнопке Next в первом шаге, если ее видимость задана свойством StepType=Start
    StepNextButtonStyle Применяется к кнопке Next в промежуточных шагах, если ее видимость задана свойством StepType=Step
    StepPreviousButtonStyle Применяется к кнопке Previous в промежуточных и последнем шагах, если ее видимость задана свойством StepType=Step
    FinishPreviousButtonStyle Применяется к кнопкам Finish и Previous в последнем шаге, если их видимость задана свойством StepType=Finish
    CancelButtonStyle Применяется к кнопке Cancel во всех шагах, если ее видимость задана свойством DisplayCancelButton=True

    Оболочка Visual Studio 2005 позволяет существенно облегчить жизнь разработчика наличием средств автоматизации по настройке типовых стилей, которых в большинстве случаев будет достаточно. Вернемся к локальной панели задач элемента Wizard, чтобы одним махом присвоить типовой стиль нашей тестовой странице.

  • Откройте страницу WizardControl.aspx в режиме Design и выделите объект Wizard1
  • Откройте локальную панель задач объекта
  • Выполните опцию
  • Окно Auto Format можно вызвать и через контекстное меню элемента Wizard, выполнив одноименную опцию

  • Выполните страницу и убедитесь, что она приобрела профессиональный дизайн
  • Проанализируйте дескрипторное представление страницы, чтобы выяснить, какие свойства дескрипторов стилей позволили добавить такую красоту (у меня бы такое никогда вручную не получилось!!!)
  • Проанализируйте дескрипторное представление страницы, чтобы выяснить, какие свойства дескрипторов стилей позволили добавить такую красоту (у меня бы такое никогда вручную не получилось!!!)

    <HeaderStyle BackColor="#FFCC66" Font-Bold="True" Font-Size="0.9em" ForeColor="#333333" 
        BorderColor="#FFFBD6" BorderStyle="Solid" BorderWidth="2px" HorizontalAlign="Center" />
    <SideBarStyle BackColor="#990000" Font-Size="0.9em" VerticalAlign="Top" />
    <NavigationButtonStyle BackColor="White" BorderColor="#CC9966" BorderStyle="Solid"
        BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#990000" />
    <SideBarButtonStyle ForeColor="White" />

    В приведенном коде каждый дескриптор настраивает свою область элемента Wizard. Обратите внимание, что приведенный блок кода настройки стилей оболочка добавляет в самый конец контейнера <asp:Wizard></asp:Wizard>, чтобы легче было искать. Если этот блок кода удалить, то мы вернемся к почти прежнему варианту стилей по умолчанию (почти, потому, что может потребоваться корректировка атрибутов еще в некоторых других местах, например, в дескрипторе <asp:Wizard> - посмотрите сами!).

  • Налюбовавшись сей красотой, вызовите контекстное меню для элемента Wizard и выполните команду Auto Format/Remove Formating, чтобы вернуться на грешную Землю к стилям по умолчанию
  • Шаблоны элемента Wizard

    Если с помощью свойств-стилей нам не удается добиться желаемого эффекта, то можно воспользоваться свойствами-шаблонами. Ниже приведен полный список шаблонов элемента управления Wizard, выбранный как свойства из панели Object Browser

    Шаблоны элемента управления Wizard
    Шаблон или дескриптор Описание
    HeaderTemplate Определяет содержимое области верхнего колонтитула
    SideBarTemplate Определяет боковую панель, которая обычно включает ссылки навигации для каждого шага
    StartNavigationTemplate Определяет кнопку навигации для первого шага, если ее видимость задана свойством StepType=Start
    StepNavigationTemplate Определяет кнопки навигации в промежуточных и последнем шагах, если их видимость задана свойством StepType=Step
    FinishNavigationTemplate Определяет кнопку навигации Finish для последнего шага, если ее видимость задана свойством StepType=Finish

    Формирование шаблона <HeaderTemplate>

    Дескрипторный блок первого шаблона добавляется опцией Edit Templates через локальную панель задач, либо опцией Edit Template через контекстное меню элемента Wizard (одна и та же команда в разных местах по разному называется - Большой Билл тоже человек!).

  • В режиме Design выполните команду Edit Template/Header Template контекстного меню для элемента управления Wizard страницы WizardControl.aspx
  • В появившемся окне введите текст верхнего колонтитула " Это заголовок шага:" (или любую другую Абру-Кадабру, лишь-бы заготовка шаблона создалась, - все равно потом руками редактировать), после чего щелкните на опции End Template Editing локальной панели задач, чтобы завершить создание шаблона заголовка и вернуться в редактор Design
  • Если ничего в поле текста не ввести, то после выхода по опции End Template Editing дескриптор <HeaderTemplate> создан не будет.

  • Перейдите на странице в режим Source, найдите в конце блока кода созданный оболочкой дескриптор <HeaderTemplate> и отредактируйте его так
  • <HeaderTemplate>
        <h1>
            Это заголовок шага:                        
            <%= Wizard1.ActiveStep.Title %>
        </h1>
    </HeaderTemplate>

    Получается, что мы шаблон заголовка должны заполнять вручную как обычный HTML-текст. Эта возможность оставлена в силу ее простоты (" Уж HTML-то они должны знать!", опрометчиво подумал Большой Билл). И для тренировки мы сами вставили в этот HTML-код операторный исполнимый блок <%=имя_переменной_или_выражение%>. Это обычный прием, применяемый, например, в PHP. При исполнении страницы вместо этого блока в статический текст будет подставлено значение указанной переменной или выражения. Таких блоков в статическом HTML-коде страницы мы можем наставить, сколько угодно. В нашем примере в указанном месте будет подставляться значение атрибута Title текущего шага, которые мы декларативно определили ранее при формировании шагов элемента Wizard.

  • Исполните страницу и вы увидите работу шаблона заголовка в действии
  • Обратите внимание, что хоть ранее мы и задали в панели Properties значение заголовка в свойстве HeaderText="Жизненно важная анкета!" элемента Wizard (этот атрибут и сейчас там присутствует), но как только мы добавили дескриптор шаблона заголовка, оболочка сразу же скрыла это свойство в панели Properties. Отображаться теперь будет именно заголовок шаблона.

    Формирование остальных шаблонов

    Все оставшиеся шаблоны областей элемента Wizard разрешают пользоваться удобствами среды в силу их сложности. Чтобы создать требуемый дескриптор шаблона, нужно выполнить соответствующую команду Convert to... (в контекстном меню элемента Wizard или его локальной панели). После этого можно приступать к редактированию созданного шаблона, выполнив опцию Edit Template (опять вставлю те же самые снимки. Физически они занимают на диске одно место, а отображаться броузером могут хоть в ста местах)

    Команда Edit Template вызывает окно редактора шаблонов, в рабочей области которого находится прямоугольный индикатор настройки со своей локальной панелью. Стоит только выделить этот индикатор, сразу в панели Properties появляются доступные для настройки шаблона свойства.

    Завершение редактирования осуществляется командой End Template Editing контекстного меню или локальной панели

    Обратите внимание, что как только какой-то из шаблонов создан, то в меню соответствующая команда меняется с Conver to..., на Reset... Выполнение команды Reset... начисто удаляет дескрипторы соответствующего шаблона. Дескрипторы любого шаблона можно удалить и вручную в режиме Source, но для шаблона заголовка это можно сделать только вручную.

  • Добавьте к элементу Wizard шаблон <SideBarTemplate> и через панель Properties задайте ему свойство ItemStyle/BorderStyle="Outset"
  • Вернитесь в режим
  • Выполните страницу, все должно работать
  • Следует всегда помнить, что при всем многообразии настроек стилей и шаблонов интерфейс по умолчанию является самым выверенным с точки зрения экономии ресурсов при обмене с клиентом. Поэтому менять настройки нужно разумно, за неординарный интерфейс потребуется дополнительная плата.

    И все же, давайте вернемся к той красоте, которую мы получали для этой страницы применением стандартных стилей.

  • Удалите шаблон <SideBarTemplate>, выполнив в режиме Design команду Reset SideBarTemplat контекстного меню элемента Wizard, и выберите красивый стандартный стиль через опцию Auto Format того же меню
  • Страницы:
    Файлы к лекции Вы можете скачать здесь

    Два высокоразвитых элемента управления MultiView и Wizard позволяют организовать для пользователя имитацию сложного многостраничного просмотра. Они содержат встроенные средства локальной навигации, обеспечивающие смену кадров с разным пользовательским интерфейсом, но единым оформлением.

    Элемент управления MultiView

    Элемент управления MultiView позволяет организовать страницу в виде множества вкладок. Каждая вкладка может содержать свой пользовательский интерфейс и обеспечивать свою форму представления одной и той же информации пользователя.

  • Создайте новый проект с именем
  • Переименуйте, для тренировки смелости в отношении модификации кода, сгенерированную страницу Default.aspx в MultiViewControl.aspx, в ее декларации @Page введите новое значение параметра Inherits="MultiViewControl", а в файле скрытого кода переименуйте класс в MultiViewControl (или не переименовывайте ни класс и Inherits, ни страницу, но я буду говорить об этих именах и код приводить с их использованием)
  • Поместите на страницу в режиме редактора Design из вкладки Standard компонент-контейнер MultiView
  • Поместите на страницу в режиме редактора Design внутрь созданного объекта MultiView1 из той же вкладки Standard три экземпляра компонента View. Компонент View называют представлением данных
  • В результате оболочка сгенерирует следующий дескрипторный код

    <%@ Page AutoEventWireup="true" 
           CodeFile="MultiViewControl.aspx.cs" 
    	   Inherits="MultiViewControl" 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>
            <asp:MultiView ID="MultiView1" runat="server">
                <asp:View ID="View1" runat="server">
                </asp:View>
                <asp:View ID="View2" runat="server">
                </asp:View>
                <asp:View ID="View3" runat="server">
                </asp:View>
            </asp:MultiView></div>
        </form>
    </body>
    </html>
  • Запустите приложение и вы получите чистый экран броузера, поскольку созданные вкладки - представления еще не были заполнены интерфейсными элементами и показать им нечего
  • Замечание. Представления View можно добавлять и программно по мере необходимости (как и любой другой элемент управления). Для этого нужно создать экземпляр (например, View1 ) нового представления и добавить ссылку на него в коллекцию Views экземпляра (например, MultiView1 ) элемента MultiView с помощью MultiView1.Views.Add(View1) или MultiView1.Views.AddAt(index, View1). Свойство Views определено в классе System.Web.UI.WebControls.ViewCollection, который и имеет указанные методы Add() и AddAt(). Но мы будем для простоты использовать декларативный способ этапа проектирования.

    Web-форма в оболочке после наших действий будет иметь вид

    Visual Studio 2005 во время проектирования показывает все представления View в раскрытом виде, но на этапе выполнения на странице может отображаться только одно из них, которое раскроет пользователь. Каждое представление можно редактировать в оболочке точно также, как любую часть обычной страницы.

    Будет ли при загрузке страницы раскрыто какое-либо представление или нет, определяется свойством MultiView.ActiveViewIndex, доступном и на этапе проектирования и программно. Если значение этого свойства равно "-1", то при начальной загрузке страницы ни одна из вкладок не будет раскрыта. Если свойство установлено в ноль, то будет раскрыта первая вкладка и т.д.

    Давайте продолжим выполнение нашего примера и наполним представления каким-нибудь содержимым.

  • Поместите в корневую папку сайта какой-нибудь рисунок щадящего Web-формата ( *.gif, *.jpg, *.png ). Один из вариантов рисунка, файл MyPhoto.jpg, прилагается...
  • Поместите в представление View1 из вкладки Standard компонент Image (контейнер для рисунка) и декларативно настройте его так:
  • ImageUrl="~/MyPhoto.jpg". Символ ~ (тильда) обозначает корень виртуального каталога сайта
  • Поместите в представление View2 какой-нибудь текст
  • Поместите в представление View3 элемент Calendar из вкладки Standard и настройте его внешний вид
  • Выделите объект MultiView1 и установите его свойство ActiveViewIndex в значение ноль, чтобы при начальной загрузке страницы было открыто первое представление
  • Управление отображением представлений

    Вариант 1

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

  • Поместите на форму страницы впереди элемента MultiView1 компонент DropDownList из вкладки Standard
  • Установите для списка свойство AutoPostBack в значение True, чтобы при выборе нового пункта автоматически выполнялась обратная отсылка
  • Выделите экземпляр DropDownList1 и через панель Properties в режиме Events создайте обработчик события SelectedIndexChanged
  • Дескрипторное представление страницы будет таким

    <%@ Page AutoEventWireup="true" 
        CodeFile="MultiViewControl.aspx.cs" 
        Inherits="MultiViewControl" Language="C#" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления множеством представлений</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:DropDownList ID="DropDownList1" runat="server"
                    AutoPostBack="True"
                    OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
                </asp:DropDownList><br />
                <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
                    <asp:View ID="View1" runat="server">
                        <h1>Мое фото</h1>
                        <asp:Image ID="Image1" runat="server" ImageUrl="~/MyPhoto.jpg" />
                    </asp:View>
                    
                    <asp:View ID="View2" runat="server">
                        <h1>Мои стихи</h1>
                        <p>
                            У Лукоморья дуб зеленый<br />
                            Златая цепь на дубе том<br />
                            И днем и ночью кот ученый<br />
                            Все ходит по цепи кругом
                        </p>
                    </asp:View>
                    
                    <asp:View ID="View3" runat="server">
                        <h1>Мой календарь</h1>
                        <asp:Calendar ID="Calendar1" runat="server" BackColor="#C0FFFF" 
                            BorderColor="Red" BorderStyle="Ridge">
                        </asp:Calendar>
                    </asp:View>
                </asp:MultiView>
            </div>
        </form>
    </body>
    </html>
  • Поместите в файл MultiViewControl.aspx.cs следующий код
  • using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Заполняем список только при первом запросе страницы,
            // а потом все будет сохраняться в состоянии вида.
            // Иначе список всегда будет переустанавливаться в начало
            if (!IsPostBack)
            {
                // Подсоединяем коллекцию с вкладками к списку
                DropDownList1.DataSource = MultiView1.Views;
                // Назначаем идентификатор, значениями которого
                // будут заполнены поля "Text" списка
                DropDownList1.DataTextField = "ID";
                // Заполняем список подсоединенными данными
                DropDownList1.DataBind();
    	
                // Отображаем первое представление
                MultiView1.ActiveViewIndex = 0;
                // Синхронизируем список
                DropDownList1.SelectedIndex = 0;
        
                // Выделяем текущую дату 
                Calendar1.SelectedDate = DateTime.Now.Date;
                Calendar1.SelectedDayStyle.BorderStyle = BorderStyle.Solid;
            }
        }
    	
        // Обработчик события выбора в списке
        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    }
  • Выполните страницу, результат должен быть не менее лучезарным, чем этот...
  • Вариант 2

    В обработчике события Page_Load() мы, для тренировки, вставили код, чтобы при первом запросе страницы список программно заполнялся значениями атрибутов ID представлений. Этого можно и не делать, если вручную на этапе проектирования заполнить свойство Items списка более осмысленными именами.

    Мы, также, назначили для списка AutoPostBack="True", чтобы он индивидуально осуществлял обратную отсылку. Ну, а если на странице будет много интерфейсных элементов с возможностью постинга, которые должен будет настроить пользователь. В этом случае будет расточительно, что каждый элемент интерфейса при настройке индивидуально посылает страницу на сервер для обновления. Лучше предусмотреть отдельную кнопку, которая отдаст команду броузеру на обратную отсылку после настройки всех интерфейсных элементов. Выполним эти модификации на новой странице.

  • Через панель Solution Explorer выполните копию страницы MultiViewControl.aspx и присвойте копии новое имя MultiViewControl1.aspx.
  • Обратите внимание, что файл кода .cs автоматически копируется и переименовывается вместе со страницей. Более того, в оболочке даже не предусмотрена возможность переименовать его отдельно, пока он связан со страницей. Правда, его можно скопировать отдельно, тогда он переименовывается.

  • Выполните команду меню Window/Close All Documents, чтобы закрыть все прежние окна редактирования рабочей области оболочки
  • Откройте новую страницу MultiViewControl1.aspx на редактирование и выполните команду меню Website/Set As Start Page, чтобы сделать теперь ее стартовой при запуске из оболочки
  • Выделите список через панель Properties и сбросьте его свойство AutoPostBack в False
  • Через раскрывающийся список в верхней части панели Properties выделите объект MultiView1 и задайте ActiveViewIndex=-1, чтобы ни одно представление при первой загрузке страницы у пользователя не было раскрыто
  • В файле MultiViewControl1.aspx.cs полностью очистите обработчик события Page_Load(), код которого в предыдущем примере программно заполнял список (можно полностью удалить этот обработчик, нам он здесь не понадобится)
  • Сейчас мы должны заполнить список декларативно (на этапе проектирования).

  • Выделите список и заполните его свойство Items так
    Декларативные настройки объекта DropDownList1
    Items[i] Text Value
    Items[0] Моя фотография не имеет значения ...
    Items[1] Мои стихи не имеет значения ...
    Items[2] Встроенный календарь не имеет значения ...
  • Добавьте на новую страницу справа от списка кнопку Input (Submit) из вкладки HTML панели Toolbox (воспользуемся простой кнопкой) и задайте ей Value=Show; Title=Раскрыть вкладку
  • Запустите приложение и неизменяя список понажимайте кнопку Show.
  • Ничего не происходит, пока в списке мы не выбирем новый пункт. Только после этого свойство MultiView1.ActiveViewIndex примет отличное от -1 значение и представления при обратной отсылке начнут работать. Чтобы исправить это, нужно код присвоения значения свойству ActiveViewIndex переместить в обработчик нажатия кнопки.

  • Создайте обработчик для кнопки ID=Submit1 двойным щелчком на ней мышью
  • Мы видим, что оболочка создала код заготовки JavaScript -сценария, который мы должны заполнить и который страница готова посылать на клиентский броузер. Чтобы не вникать в JavaScript приведем в свое оправдание аргумент, что поддержка сценариев JavaScript - дело ненадежное, поскольку пользователь может в своем броузере ее отключить.

  • Удалите созданный оболочкой предыдущим действием код JavaScript -сценария. Для этого в режиме Source поместите текстовый курсор редактора внутрь блока кода <script language="javascript" type="text/javascript">..|..</script> и в нижней части рамки окна редактора щелкните на кнопке <script>. Весь выделенный код можно удалять
  • Удалите из дескриптора <input> кнопки Submit1 onclick="return Submit1_onclick()", сгенерированный оболочкой
  • Щелкните на Submit1 правой кнопкой мыши и выполните команду Run As Server Control. Этим действием в дескриптор <input> будет добавлен атрибут runat="server", который заставит ASP.NET запускать обработчик кнопки (если мы его предусмотрим), если с броузера с обратной отсылкой будет прислано событие, что клиент щелкал на этой кнопке
  • Выделите список DropDownList1 и через панель Properties в режиме Events очистите поле события SelectedIndexChanged
  • Двойным щелчком на, теперь уже серверной, кнопке Submit1 создайте для нее обработчик в файле MultiViewControl1.aspx.cs
  • Перенесите код обработчика события SelectedIndexChanged в код нового обработчика, а старый обработчик удалите
  • В результате код файла будет таким

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        // Обработчик события на кнопке Submit1
        protected void Submit1_ServerClick(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    }
  • Выполните страницу
  • Теперь по прибытию на сервер обратной отсылки система ASP.NET распознает присланное событие щелчка на кнопке. Свойству MultiView1.ActiveViewIndex в обработчике события кнопки присваивается значение выбранной пользователем опции списка. Клиенту страница отправляет содержимое вкладки, соответствующей его выбору.

    Добавление в представления функций навигации

    В предыдущих примерах мы знакомились с механизмом работы элемента MultiView. Мы использовали для смены вкладок внешний по отношению к MultiView элемент списка. Но MultiView имеет собственные средства для перехода по своим вкладками. Рассмотрим эти возможности.

    Серверные элементы Button, ImageButton, LinkButton реализуют интерфейс System.Web.UI.WebControls.IButtonControl, от которого наследуют способность генерировать не только событие Click, но и событие Command. Такие элементы управления называются кнопочными. Они реализуют ряд полезных свойств интерфейса, таких как CommandArgument, CommandName и др.

    В свою очередь, элемент управления MultiView содержит общедоступные переменные (поля), которые ожидают поступления определенных команд, чтобы MultiView соответствующим образом их исполнил.

    Ниже приведены команды, которые ожидает MultiView.

    Имена команд, которые может распознать MultiView
    Поле Ждет команду Описание действия MultiView
    NextViewCommandName NextView Переход к следующему представлению. Команда является значением свойства CommandName кнопочного элемента
    PreviousViewCommandName PrevView Переход к предыдущему представлению. Команда является значением свойства CommandName кнопочного элемента
    SwitchViewByIDCommandName SwitchViewByID Переход к представлению со значением идентификатора ID, переданным из свойства CommandArgument кнопочного элемента управления
    SwitchViewByIndexCommandName SwitchViewByIndex Переход к представлению с определенным индексом, переданным из свойства CommandArgument кнопочного элемента управления

    Воспользуемся описанным механизмом в нашем примере. Развитие примера выполним на копии.

  • В панели Solution Explorer скопируйте страницу MultiViewControl1.aspx, присвойте копии имя MultiViewControl2.aspx и сделайте эту страницу стартовой
  • Из вкладки Standard панели Toolbox поместите в первое и последнее представления по одной серверной кнопке Button, а в среднее - две кнопки
  • Настройте кнопки как показано в таблице
  • Настройка кнопок навигации на представлениях
    Представление Свойство Значение
    Views[0] ID btnNext0
    Text Next >
    CommandName NextView
    Views[1] ID btnPrev1
    Text < Prev
    CommandName PrevView
    ID btnNext1
    Text Next >
    CommandName NextView
    Views[2] ID btnPrev2
    Text < Prev
    CommandName PrevView

    У нас в обработчике кнопки Submit1 выполняется синхронизация выбранного пункта списка и активного представления. Если теперь осуществлять переход по представлениям введенными кнопками навигации, то обратной синхронизации представлений со списком не будет. Исправим это...

  • Установите редактор страницы в режим Design
  • В панели Properties в верхнем раскрывающемся списке выберите объект MultiView1, переведите панель в режим Events (кнопка с пиктограммой молнии) и двойным щелчком на поле события ActiveViewChanged создайте обработчик, который заполните кодом синхронизации списка
  • В результате файл поддержки страницы должен быть таким

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class MultiViewControl : System.Web.UI.Page 
    {
        // Обработчик события на кнопке Submit1
        // Синхронизация представлений со списком
        protected void Submit1_ServerClick(object sender, EventArgs e)
        {
            MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
        }
    	
        // Синхронизация списка с представлениями
        protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
        {
            DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;
        }
    }

    Файл дескрипторного представления будет таким

    <%@ Page AutoEventWireup="true" 
        CodeFile="MultiViewControl2.aspx.cs" 
        Inherits="MultiViewControl" Language="C#" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления множеством представлений</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:DropDownList ID="DropDownList1" runat="server">
                    <asp:ListItem>Моя фотография</asp:ListItem>
                    <asp:ListItem>Мои стихи </asp:ListItem>
                    <asp:ListItem>Встроенный календарь</asp:ListItem>
                </asp:DropDownList>
                
                <input id="Submit1" type="submit" value="Show" 
                    title="Раскрыть вкладку" runat="server" 
                    onserverclick="Submit1_ServerClick" /><br />
                    
                <asp:MultiView ID="MultiView1" runat="server" 
                    OnActiveViewChanged="MultiView1_ActiveViewChanged">
                    <asp:View ID="View1" runat="server">
                        <h1>
                            Мое фото</h1>
                        <asp:Image ID="Image1" runat="server" 
                            ImageUrl="~/MyPhoto.jpg" /><br />
                        <br />
                        <asp:Button ID="btnNext0" runat="server" 
                            CommandName="NextView" Text="Next >" />
                    </asp:View>
                    
                    <asp:View ID="View2" runat="server">
                        <h1>
                            Мои стихи</h1>
                        <p>
                            У Лукоморья дуб зеленый<br />
                            Златая цепь на дубе том<br />
                            И днем и ночью кот ученый<br />
                            Все ходит по цепи кругом
                        </p>
                        <asp:Button ID="btnPrev1" runat="server" 
                            CommandName="PrevView" Text="< Prev" />
                        <asp:Button ID="btnNext1" runat="server" 
                            CommandName="NextView" Text="Next >" />
                    </asp:View>
                    
                    <asp:View ID="View3" runat="server">
                        <h1>
                            Мой календарь</h1>
                        <asp:Calendar ID="Calendar1" runat="server" 
                            BackColor="#C0FFFF" BorderColor="Red"
                            BorderStyle="Ridge" />
                        <br />
                        <asp:Button ID="btnPrev2" runat="server" 
                            CommandName="PrevView" Text="< Prev" />
                    </asp:View>
                </asp:MultiView>
            </div>
        </form>
    </body>
    </html>
  • Выполните страницу и убедитесь, что все работает как нужно
  • Хороший элемент, что и говорить. Но есть один существенный недостаток. Поскольку хранится несколько представлений, то мы должны быть готовы вернуться к любому представлению, если его повторно вызовет пользователь. Это значит, что мы должны сохранять состояние вида всех представлений, в том числе и невидимых в данный момент. Из-за этого элемент посылает на клиентскую машину большой объем кода состояния вида. От этой неприятности можно избавиться, отключив свойство EnableViewState.

    Еще одна особенность, о которой стоит помнить. Элемент MultiView не является контейнером для имен элементов управления на вкладках. Это значит, что в пределах страницы все элементы управления должны иметь уникальные значения идентификаторов ID, иначе компилятор заблудится.

    Элемент управления Wizard

    Элемент управления Wizard (мастер) является более развитым, чем элемент MultiView. Он имеет богатую настраиваемую функциональность, включающую в себя

  • Возможность последовательного отображения одного или нескольких представлений
  • Встроенные кнопки навигации
  • Встроенное боковое меню со ссылками на выполняемые шаги-вкладки
  • Стили и шаблоны
  • Содержимым шагов -вкладок мастера являются Web- и HTML-элементы управления, обычно используемые при построении страниц. Рассмотрим последовательно свойства элемента управления Wizard на примерах.

  • Добавьте новую страницу с именем WizardControl.aspx и файлом отделенного кода. Назначьте ее стартовой
  • В режиме Design редактора поместите на страницу элемент управления Wizard из вкладки Standard панели Toolbox
  • Будет сгенерирована такая заготовка

    Дескрипторное представление заготовки будет таким

    <%@ Page Language="C#" AutoEventWireup="true" 
        CodeFile="WizardControl.aspx.cs" Inherits="WizardControl" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления Wizard</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0">
                    <WizardSteps>
                        <asp:WizardStep runat="server" Title="Step 1">
                        </asp:WizardStep>
                        <asp:WizardStep runat="server" Title="Step 2">
                        </asp:WizardStep>
                    </WizardSteps>
                </asp:Wizard>
            </div>
        </form>
    </body>
    </html>

    Дальнейшей задачей программиста будет настройка этой заготовки в полноценный элемент управления. Оболочка предоставляет широкие возможности для разработчика на этапе проектирования. Кроме традиционной панели свойств Properties элемент Wizard имеет дополнительную локальную панель задач для оперативных действий по настройке. Чтобы вызвать локальную панель задач элемента Wizard, нужно щелкнуть мышью на пиктограмме в виде треугольника в его правом верхнем углу

    В элементе управления MultiView все представления на этапе проектирования раскрыты для разработчика. Для элемента Wizard оболочка Visual Studio 2005 показывает разработчику представление только одного текущего шага.

    Чтобы создать новые шаги мастера, нужно:

  • просто добавлять в его контейнер дескрипторы <asp:WizardStep>
  • или через локальную панель задач выполнить опцию Add/Remove WizardSteps
  • или в панели Properties вызвать на редактирование свойство WizardSteps
  • Обратите внимание, что по умолчанию дескрипторы <asp:WizardStep> шагов-вкладок не имеют значения идентификатора ID. Здесь подразумевается, что для такого сложного элемента управления разработчику достаточно декларативной настройки. Если же в дальнейшем разработчик предполагает программно управлять шагами мастера, то без атрибутов ID не обойтись.

    В приведенном окне редактирования коллекции шагов-вкладок наиболее существенными являются следующие свойства дескриптора <asp:WizardStep>

    Некоторые свойства дескриптора <asp:WizardStep>
    Свойство Описание
    Title Имя шага, видимое пользователю в ссылках на боковой панели слева
    StepType Это свойство определяет тип кнопок навигации, которые будут предъявлены пользователю данным шагом, и равно одному из значений перечисления System.Web.UI.WebControls.WizardStepType.WizardStepType:
  • Auto - определяется по умолчанию и устанавливает тип кнопки в зависимости от местонахождения шага в коллекции. Если шаг стоит на первом месте, то будет кнопка Start, во всех промежуточных позициях - кнопка Step, если на последнем месте - будет кнопка Finish
  • Complete - не показывает никаких кнопок и скрывает боковую панель
  • Finish - показывает кнопки Finish и Previous
  • Start - показывает кнопку Next
  • Step - показывает кнопки Next и Previous
  • AllowReturn Показывает, может ли пользователь возвращаться к этому шагу после того, как его пройдет. Если это свойство имеет значение false, то как только пользователь пройдет этот шаг, он не сможет вернуться назад. Потому что все ссылки, ведущие к этому пройденному шагу, немедленно будут блокированы.

    Наполним шаги мастера конкретным содержимым - элементами управления, и настроим их свойства. Всего создадим четыре шага, в которых разместим:

  • WizardStep1 - раскрывающийся список DropDownList
  • WizardStep2 - список радиокнопок RadioButtonList
  • WizardStep3 - текстовое поле TextBox
  • WizardStep4 - обычный текст
  • Оболочка Visual Studio 2005 все отличные от значений по умолчанию свойства элементов сохраняет в дескрипторах текстового файла .aspx как дополнительные атрибуты. Более того, при установке значений отдельным свойствам оболочка сама генерирует новые дескрипторы и даже целые блоки кода. Поэтому все декларативные настройки сложных элементов управления нужно выполнять через панель Properties, но для краткости изложения приведем уже готовый код настройки страницы нашего примера.

    <%@ Page Language="C#" AutoEventWireup="true" 
        CodeFile="WizardControl.aspx.cs" Inherits="WizardControl" %>
    	
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Элемент управления Wizard</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:Wizard ID="Wizard1" runat="server" BackColor="#EFF3FB" 
                    BorderColor="#B5C7DE"
                    BorderWidth="1px" Width="100%" ActiveStepIndex="0" 
                    StartNextButtonText="Далее >"
                    StepNextButtonText="Далее >" StepPreviousButtonText="< Назад" 
                    FinishCompleteButtonText="Готово" FinishPreviousButtonText="< Назад" 
                    HeaderText="Жизненно важная анкета!">
                    <WizardSteps>
                        <asp:WizardStep ID="WizardStep1" runat="server" Title="Друзья">
                            <h3>
                                Какой президент самый лучший?</h3>
                            <asp:DropDownList ID="DropDownList1" runat="server">
                                <asp:ListItem>Наш Путин</asp:ListItem>
                                <asp:ListItem>Их Клинтон</asp:ListItem>
                                <asp:ListItem>Похожий на Чингиз-Хана</asp:ListItem>
                                <asp:ListItem>Вы сами</asp:ListItem>
                                <asp:ListItem>Ваша соседка</asp:ListItem>
                            </asp:DropDownList>
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep2" runat="server" Title="Туризм">
                            <h2>
                                Где Вы были с 19 по 21 августа 1991 года?</h2>
                            <asp:RadioButtonList ID="RadioButtonList1" runat="server">
                                <asp:ListItem>На Красной площади</asp:ListItem>
                                <asp:ListItem>На Луне</asp:ListItem>
                                <asp:ListItem>В чужом огороде</asp:ListItem>
                                <asp:ListItem>У тетеньки</asp:ListItem>
                                <asp:ListItem>В ауте</asp:ListItem>
                            </asp:RadioButtonList>
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep3" runat="server" Title="Встречи">
                            <h3>
                                Кайтесь! Место встречи изменить нельзя!</h3>
                            Ваш ИНН:
                            <asp:TextBox ID="TextBox1" runat="server" />
                        </asp:WizardStep>
                        <asp:WizardStep ID="WizardStep4" runat="server" Title="Досуг">
                            <h2>
                                Мера поощрения</h2>
                            Усиленная диета + клизьма ззз перцем!
                        </asp:WizardStep>
                    </WizardSteps>
                    <HeaderStyle BackColor="Blue" Font-Bold="True" Font-Size="X-Large" ForeColor="Yellow" />
                </asp:Wizard>
            </div>
        </form>
    </body>
    </html>

    Несколько замечаний:

  • Такой дурашливый текст Вы должны изменить (Технари могут себе позволить, пока Органы отдыхают, а "Утомленные Солнцем" доценты - тем более)
  • Боковую панель навигационных ссылок можно отключать свойством Wizard.DisplaySideBar="False"
  • Оболочка в режиме проектирования автоматически изменяет значение свойства Wizard.ActiveStepIndex при редактировании текущего шага. Поэтому, чтобы страница при запуске показала первый шаг, небходимо в конце редактирования либо на него перейти, либо установить Wizard.ActiveStepIndex ="0"
  • Мы еще ничего не программировали, а уже успели добиться такой мощной функциональности страницы
  • Последний дескриптор кода <HeaderStyle> определяет стиль заголовочного блока элемента Wizard, о чем мы еще поговорим ниже
  • Запустите страницу с настроенным элементом Wizard и "подывитесь", какой же все-таки Большой Билл умный, да еще так вовремя - какие масштабы и горизонты открывают для нас эти его инструменты (ну, прямо, Эльдорадо!)
  • События элемента Wizard

    До сих пор мы занимались настройками Wizard в режиме проектирования, пришла пора приступить к программированию его времени выполнения. Мы уже говорили, что для разработчика задача управления объектами страницы во время выполнения сводится к созданию и программированию обработчиков событий, на которые могут реагировать эти объекты. Ниже перечислены события, на которые может реагировать экземпляр класса Wizard.

    События, поддерживаемые элементом Wizard
    Событие Описание
    ActiveStepChanged Ага! Пользователь переключился на новый шаг или наш код изменил свойство ActiveStepIndex
    CancelButtonClick Ага! Пользователь щелкнул на кнопке Cancel (Отмена). Кнопка Cancel по умолчанию не отображается, однако ее можно добавить во все представления Step сразу, если установить свойство Wizard.DisplayCancelButton="True". Кнопка Cancel инициирует обратную отсылку, и если не предусмотреть соответствующего обработчика, то ничего не происходит. Но если одновременно определено свойство Wizard.CancelDestinationPageUrl, например, CancelDestinationPageUrl="~/MultiViewControl.aspx", то по щелчку пользователя на этой кнопке ему отправляется другая страница
    FinishButtonClick Ага! Пользователь дошел до последнего шага и щелкнул на кнопке Finish
    NextButtonClick, PreviousButtonClick Эти события возникают при щелчке на кнопке Next или Previous на любом шаге. Но сменить шаг пользователь может и через боковую панель. Чтобы такой момент не упустить и однозначно среагировать на смену шага, лучше вместо этих событий обрабатывать событие ActiveStepIndex
    SideBarButtonClick Ага! Пользователь щелкнул на ссылке в области боковой панели
    Чувствуете?!!! Мы сидим со своим кодом на другом конце провода и ждем очередных пожеланий ненасытного пользователя. При получении от него очередного запроса мы анализируем выбор по присланным событиям и пакуем для него новую посылку, в которую закладываем и требуемый текущий ответ, и интерфейсные элементы для ввода новых пожеланий. Да все это еще должно быть красивым, блестящим и пушистым. Вот Большой Билл нам здесь и помогает - осталось только руки приложить.

    Используем событие FinishButtonClick, чтобы усовершенствовать наш пример. Когда пользователь щелкнет в последнем шаге на кнопке Finish (Готово), соберем его выбор с каждого шага и вернем в раскрытом представлении этого последнего шага.

  • Откройте страницу WizardControl.aspx в режиме Design и перейдите на последний шаг WizardStep4 для его редактирования
  • Поместите в середину контекста текстовую метку
  • Выделите объект Wizard1 и через панель свойств в режиме Events создайте обработчик для события FinishButtonClick
  • Заполните обработчик следующим кодом
    (рис ) Обработчик события FinishButtonClick в файле WizardControl.aspx.csusing System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    	
    public partial class WizardControl : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    	
        }
    	
        protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
        {
            // Библиотека Framework 2.0 в нашем распоряжении
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("<h3>");
            sb.Append("Вы выбрали: <br />");
            string title;
    	
            title = WizardStep1.Title;
            sb.Append(title + ": " + DropDownList1.Text + "<br />");
    
            title = WizardStep2.Title;
            int index = RadioButtonList1.SelectedIndex;
            if(index != -1) // Если что-то выбрал
                sb.Append(title + ": " + RadioButtonList1.Items[index].Text + "<br />");
    	
            /*  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
            // Для элемента класса CheckBoxList нужно проверять коллекцию:
            CheckBoxList CheckBoxList1;
            foreach (ListItem item in CheckBoxList1.Items)
            {
                if (item.Selected)
                    sb.Append(item.Text + "; ");
            }
                !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
    	
            title = WizardStep3.Title;
            if (TextBox1.Text.Length > 0)// Если что-то ввел
                sb.Append(title + ": " + TextBox1.Text + "<br /></br />");
    	
            sb.Append("</h3>");
    	
            sb.Append("Вам рекомендуется:");
    	
            // Отображаем собранные данные
            lblSummary.Text = sb.ToString();
        }
    }
  • Перейдите в режиме Design на первый шаг WizardStep1, чтобы автоматически установилось в ноль значение свойства ActiveStepIndex объекта Wizard1 и пользователю вначале отображался первый шаг
  • Выполните страницу, заполните анкету и на последнем шаге щелкните на кнопке
  • Стили элемента Wizard

    Элемент Wizard содержит средства, позволяющие легко менять его внешний вид. В нем можно задавать собственный пользовательский интерфейс, отличный от интерфейса по умолчанию. Через высокоуровневые свойства можно управлять цветами, шрифтами, интервалами и стилями границ, настраивать внешний вид каждой кнопки, добавлять верхний колонтитул и т.д.

    Например, для кнопки StartNext применяются следующие свойства:

    Некоторые свойства для настройки кнопок
    Свойство Описание
    StartNextButtonImageUrl Задает изображение для изображения-кнопки
    StartNextButtonStyle Использует стили внешней каскадной таблицы стилей CSS
    StartNextButtonText Настраивает текст кнопки или ссылки
    StartNextButtonType Определяет кнопку, ссылку или выбираемое изображение-кнопку

    Среди свойств компонента Wizard есть общие стили, затрагивающие настройки всех элементов, а есть индивидуальные для каждой группы элементов. Следует помнить, что если одновременно определены те и другие стили, то конфликта не будет, просто индивидуальные параметры настройки переопределят (отменят) общие стили. В языках программирования используется тот же принцип, переменная локальной области видимости переопределяет (делает недоступной) в текущем блоке кода одноименную переменную внешней области видимости.

    Ниже приведены свойства мастера Wizard, определяющие общие и индивидуальные стили его отдельных областей.

    Свойства Wizard, определяющие стили его элементов
    Стиль Описание
    ControlStyle Наследуется Wizard от класса WebControl и применяется ко всем его разделам
    HeaderStyle Применяется к разделу верхнего колонтитула, который будет отображаться только в том случае, если будет задан какой-нибудь текст в свойстве Wizard.HeaderText
    SideBarStyle Применяется к области боковой панели с кнопками
    SideBarButtonStyle Определяет стиль кнопок боковой панели
    StepStyle Применяется к компонентам представления, включенным в текущий шаг
    NavigationStyle Применяется к нижней области шагов, в которых расположены навигационные кнопки
    NavigationButtonStyle Применяется только к кнопкам навигации в области навигации
    StartNextButtonStyle Применяется к кнопке Next в первом шаге, если ее видимость задана свойством StepType=Start
    StepNextButtonStyle Применяется к кнопке Next в промежуточных шагах, если ее видимость задана свойством StepType=Step
    StepPreviousButtonStyle Применяется к кнопке Previous в промежуточных и последнем шагах, если ее видимость задана свойством StepType=Step
    FinishPreviousButtonStyle Применяется к кнопкам Finish и Previous в последнем шаге, если их видимость задана свойством StepType=Finish
    CancelButtonStyle Применяется к кнопке Cancel во всех шагах, если ее видимость задана свойством DisplayCancelButton=True

    Оболочка Visual Studio 2005 позволяет существенно облегчить жизнь разработчика наличием средств автоматизации по настройке типовых стилей, которых в большинстве случаев будет достаточно. Вернемся к локальной панели задач элемента Wizard, чтобы одним махом присвоить типовой стиль нашей тестовой странице.

  • Откройте страницу WizardControl.aspx в режиме Design и выделите объект Wizard1
  • Откройте локальную панель задач объекта
  • Выполните опцию
  • Окно Auto Format можно вызвать и через контекстное меню элемента Wizard, выполнив одноименную опцию

  • Выполните страницу и убедитесь, что она приобрела профессиональный дизайн
  • Проанализируйте дескрипторное представление страницы, чтобы выяснить, какие свойства дескрипторов стилей позволили добавить такую красоту (у меня бы такое никогда вручную не получилось!!!)
  • Проанализируйте дескрипторное представление страницы, чтобы выяснить, какие свойства дескрипторов стилей позволили добавить такую красоту (у меня бы такое никогда вручную не получилось!!!)

    <HeaderStyle BackColor="#FFCC66" Font-Bold="True" Font-Size="0.9em" ForeColor="#333333" 
        BorderColor="#FFFBD6" BorderStyle="Solid" BorderWidth="2px" HorizontalAlign="Center" />
    <SideBarStyle BackColor="#990000" Font-Size="0.9em" VerticalAlign="Top" />
    <NavigationButtonStyle BackColor="White" BorderColor="#CC9966" BorderStyle="Solid"
        BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#990000" />
    <SideBarButtonStyle ForeColor="White" />

    В приведенном коде каждый дескриптор настраивает свою область элемента Wizard. Обратите внимание, что приведенный блок кода настройки стилей оболочка добавляет в самый конец контейнера <asp:Wizard></asp:Wizard>, чтобы легче было искать. Если этот блок кода удалить, то мы вернемся к почти прежнему варианту стилей по умолчанию (почти, потому, что может потребоваться корректировка атрибутов еще в некоторых других местах, например, в дескрипторе <asp:Wizard> - посмотрите сами!).

  • Налюбовавшись сей красотой, вызовите контекстное меню для элемента Wizard и выполните команду Auto Format/Remove Formating, чтобы вернуться на грешную Землю к стилям по умолчанию
  • Шаблоны элемента Wizard

    Если с помощью свойств-стилей нам не удается добиться желаемого эффекта, то можно воспользоваться свойствами-шаблонами. Ниже приведен полный список шаблонов элемента управления Wizard, выбранный как свойства из панели Object Browser

    Шаблоны элемента управления Wizard
    Шаблон или дескриптор Описание
    HeaderTemplate Определяет содержимое области верхнего колонтитула
    SideBarTemplate Определяет боковую панель, которая обычно включает ссылки навигации для каждого шага
    StartNavigationTemplate Определяет кнопку навигации для первого шага, если ее видимость задана свойством StepType=Start
    StepNavigationTemplate Определяет кнопки навигации в промежуточных и последнем шагах, если их видимость задана свойством StepType=Step
    FinishNavigationTemplate Определяет кнопку навигации Finish для последнего шага, если ее видимость задана свойством StepType=Finish

    Формирование шаблона <HeaderTemplate>

    Дескрипторный блок первого шаблона добавляется опцией Edit Templates через локальную панель задач, либо опцией Edit Template через контекстное меню элемента Wizard (одна и та же команда в разных местах по разному называется - Большой Билл тоже человек!).

  • В режиме Design выполните команду Edit Template/Header Template контекстного меню для элемента управления Wizard страницы WizardControl.aspx
  • В появившемся окне введите текст верхнего колонтитула " Это заголовок шага:" (или любую другую Абру-Кадабру, лишь-бы заготовка шаблона создалась, - все равно потом руками редактировать), после чего щелкните на опции End Template Editing локальной панели задач, чтобы завершить создание шаблона заголовка и вернуться в редактор Design
  • Если ничего в поле текста не ввести, то после выхода по опции End Template Editing дескриптор <HeaderTemplate> создан не будет.

  • Перейдите на странице в режим Source, найдите в конце блока кода созданный оболочкой дескриптор <HeaderTemplate> и отредактируйте его так
  • <HeaderTemplate>
        <h1>
            Это заголовок шага:                        
            <%= Wizard1.ActiveStep.Title %>
        </h1>
    </HeaderTemplate>

    Получается, что мы шаблон заголовка должны заполнять вручную как обычный HTML-текст. Эта возможность оставлена в силу ее простоты (" Уж HTML-то они должны знать!", опрометчиво подумал Большой Билл). И для тренировки мы сами вставили в этот HTML-код операторный исполнимый блок <%=имя_переменной_или_выражение%>. Это обычный прием, применяемый, например, в PHP. При исполнении страницы вместо этого блока в статический текст будет подставлено значение указанной переменной или выражения. Таких блоков в статическом HTML-коде страницы мы можем наставить, сколько угодно. В нашем примере в указанном месте будет подставляться значение атрибута Title текущего шага, которые мы декларативно определили ранее при формировании шагов элемента Wizard.

  • Исполните страницу и вы увидите работу шаблона заголовка в действии
  • Обратите внимание, что хоть ранее мы и задали в панели Properties значение заголовка в свойстве HeaderText="Жизненно важная анкета!" элемента Wizard (этот атрибут и сейчас там присутствует), но как только мы добавили дескриптор шаблона заголовка, оболочка сразу же скрыла это свойство в панели Properties. Отображаться теперь будет именно заголовок шаблона.

    Формирование остальных шаблонов

    Все оставшиеся шаблоны областей элемента Wizard разрешают пользоваться удобствами среды в силу их сложности. Чтобы создать требуемый дескриптор шаблона, нужно выполнить соответствующую команду Convert to... (в контекстном меню элемента Wizard или его локальной панели). После этого можно приступать к редактированию созданного шаблона, выполнив опцию Edit Template (опять вставлю те же самые снимки. Физически они занимают на диске одно место, а отображаться броузером могут хоть в ста местах)

    Команда Edit Template вызывает окно редактора шаблонов, в рабочей области которого находится прямоугольный индикатор настройки со своей локальной панелью. Стоит только выделить этот индикатор, сразу в панели Properties появляются доступные для настройки шаблона свойства.

    Завершение редактирования осуществляется командой End Template Editing контекстного меню или локальной панели

    Обратите внимание, что как только какой-то из шаблонов создан, то в меню соответствующая команда меняется с Conver to..., на Reset... Выполнение команды Reset... начисто удаляет дескрипторы соответствующего шаблона. Дескрипторы любого шаблона можно удалить и вручную в режиме Source, но для шаблона заголовка это можно сделать только вручную.

  • Добавьте к элементу Wizard шаблон <SideBarTemplate> и через панель Properties задайте ему свойство ItemStyle/BorderStyle="Outset"
  • Вернитесь в режим
  • Выполните страницу, все должно работать
  • Следует всегда помнить, что при всем многообразии настроек стилей и шаблонов интерфейс по умолчанию является самым выверенным с точки зрения экономии ресурсов при обмене с клиентом. Поэтому менять настройки нужно разумно, за неординарный интерфейс потребуется дополнительная плата.

    И все же, давайте вернемся к той красоте, которую мы получали для этой страницы применением стандартных стилей.

  • Удалите шаблон <SideBarTemplate>, выполнив в режиме Design команду Reset SideBarTemplat контекстного меню элемента Wizard, и выберите красивый стандартный стиль через опцию Auto Format того же меню
  • Вернуться к учебному плану