Страницы с множеством представлений

115

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

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

С точки зрения пользователя, вероятно, не имеет особого значения, применяется несколько страниц или одна страница с несколькими представлениями. В хорошо спроектированном сайте пользователь заметит лишь одно отличие - при подходе с множеством представлений сохраняется один и тот же URL-адрес. Главным же отличием является модель написания кода.

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

В ASP.NET 1.x единственный способ моделирования страницы с несколькими представлениями заключался в добавлении на страницу нескольких элементов управления Panel, чтобы каждая панель представляла одно представление или один шаг. После этого свойство Visible каждой панели настраивалось так, чтобы только одна панель была видимой одновременно. Проблема этого подхода в том, что страница засоряется дополнительным кодом, необходимым для управления панелями. Кроме того, такой подход не очень устойчив - при малейшей ошибке могут отображаться две панели одновременно.

В ASP.NET 4 разработчик избавлен от необходимости проектировать собственную систему с несколькими представлениями с нуля. Вместо этого можно воспользоваться одним из двух высокоуровневых элементов управления, которые облегчают процесс проектирования: MultiView и Wizard.

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

Элемент управления MultiView является более простым из двух элементов управления с множеством представлений. По сути, элемент управления MultiView предоставляет способ объявления нескольких представлений с отображением только одного из них в каждый момент времени. Этот элемент не имеет пользовательского интерфейса по умолчанию - вы получаете только HTML-разметку и элементы управления, которые добавили. Элемент управления MultiView аналогичен описанному ранее подходу с применением специальной панели.

Создание этого элемента управления достаточно просто. Достаточно добавить дескриптор <asp:MultiView> в файл страницы .aspx, а в него - по одному дескриптору <asp:View> для каждого отдельного представления. В дескриптор <asp:View> добавляется HTML-разметка и веб-элементы управления для данного представления:

<body>
    <form id="form1" runat="server">
        <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">

            <asp:View ID="View1" runat="server">
                <b>Представление #1</b><br />
                <br />
                <asp:Image ID="Image1" runat="server" ImageUrl="~/cookies.jpg" />
            </asp:View>

            <asp:View ID="View2" runat="server">
                <b>Представление #2</b><br />
                <br />
                Контент страницы.
            </asp:View>

            <asp:View ID="View3" runat="server">
                <b>Представление #3</b><br />
                <br />
                <asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
            </asp:View>

        </asp:MultiView>
    </form>
</body>

Представления можно добавлять и программно (как и любой другой элемент управления), создавая экземпляр объекта нового представления и добавляя его в элемент управления MultiView с помощью методов Add() и AddAt() из коллекции Views.

Среда Visual Studio отображает все представления во время проектирования, одно за другим. Эти области можно редактировать точно так же, как и при проектировании любой другой части страницы:

Проектирование множества представлений

Аналогичного эффекта для MultiView можно добиться с помощью элемента управления Accordion, который является частью инструментального набора ASP.NET AJAX Control Toolkit. С помощью этого элемента управления можно создать группу развертываемых панелей. Чтобы развернуть одну из панелей и закрыть все остальные, пользователь должен щелкнуть на заголовке. Этот элемент управления имеет основу, полностью отличную от основы элемента управления MultiView; большую часть своей работы он выполняет на стороне клиента.

Свойство MultiView.ActiveViewIndex определяет представление, которое будет отображаться. Это единственное представление, визуализируемое на странице.

Значением свойства ActiveViewIndex по умолчанию является -1, которое означает, что ни одного представления не отображается. Один из вариантов предполагает применение спискового элемента управления, с помощью которого пользователь может выбирать представление из полного списка представлений. Ниже приведен пример кода, который связывает список представлений с окном списка (нужно будет добавить элемент DropDownList на страницу):

protected void Page_Load(object sender, System.EventArgs e)
{
        if (!this.Page.IsPostBack)
        {
            DropDownList1.DataSource = MultiView1.Views;
            DropDownList1.DataTextField = "ID";
            DropDownList1.DataBind();
        }
}

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
        MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
}

Результат выполнения этого кода показан на рисунке ниже:

Переключение представлений с помощью спискового элемента управления

Чтобы назначить представлениям более понятные имена, достаточно заполнить окно списка вручную. Нужно только убедиться, что порядок следования элементов списка соответствует порядку следования представлений.

В действительности создавать этот код вручную не обязательно, поскольку элемент управления MultiView обладает определенными интеллектуальными возможностями. Как и другие многофункциональные элементы управления данными, MultiView распознает имена отдельных команд в кнопочных элементах управления. (Кнопочный элемент управления - это любой элемент управления, реализующий интерфейс IButtonControl, в том числе Button, ImageButton и LinkButton.)

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

Распознаваемые имена команд элемента управления MultiView
Имя команды Поле MultiView Описание
PrevView PreviousViewCommandName

Переход к предыдущему представлению

NextView NextViewCommandName

Переход к следующему представлению

SwitchViewByID SwitchViewByIDCommandName

Переход к представлению с определенным идентификатором (строковым именем). Идентификатор извлекается из свойства CommandArgument кнопочного элемента управления

SwitchViewByIndex SwitchViewByIndexCommandName

Переход к представлению с определенным числовым индексом. Индекс извлекается из свойства CommandArgument кнопочного элемента управления

Чтобы проверить справедливость сказанного, добавьте следующие кнопки в каждое представление:

<asp:MultiView ... OnActiveViewChanged="MultiView1_ActiveViewChanged">

	<asp:View ID="View1" runat="server">
	    ...
	    <asp:Button ID="cmdNext" runat="server" Text="Next >" CommandName="NextView" />
	</asp:View>

	<asp:View ID="View2" runat="server">
	    ...
	    <asp:Button ID="cmdPrev" runat="server" Text="< Prev" CommandName="PrevView" />
	    <asp:Button ID="cmdNext2" runat="server" Text="Next >" CommandName="NextView" />
	</asp:View>

	<asp:View ID="View3" runat="server">
	    ...
	    <asp:Button ID="Button1" runat="server" Text="< Prev" CommandName="PrevView" />
	</asp:View>

</asp:MultiView>

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

protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
	DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;
}

Теперь из одного представления в другое можно переходить с помощью кнопок:

Переключение представлений с помощью распознаваемых имен команд

Производительность страниц с элементом управления MultiView

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

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

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

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

Конечно, привязка данных необходима не во всех случаях применения элемента управления MultiView. Прекрасным вариантом использования MultiView является расширенный набор элементов управления вводом - например, форма онлайнового опроса, разделенная на отдельные представления просто для того, чтобы избавить пользователя от необходимости слишком часто прибегать к прокрутке. Этот пример хорошо подходит для MultiView, поскольку в самом конце, когда опрос будет завершен, можно будет прочитать все данные из элементов управления каждого представления.

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

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

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

По умолчанию элемент управления Wizard предоставляет навигационные кнопки и боковую панель со ссылками на каждое отображаемое слева действие. Боковую панель можно скрыть, установив свойство Wizard.DisplaySideBar в false. Обычно к этому прибегают в том случае, если нужно обеспечить строгую пошаговую навигацию и предотвратить нарушение заданной последовательности пользователем. Содержимое для каждого шага можно предоставить с помощью любого элемента управления HTML или ASP.NET. Область, в которой можно добавить содержимое в готовый экземпляр элемента управления Wizard, показана на рисунке ниже:

Область для содержимого данного шага

Шаги мастера

Чтобы создать мастер в ASP.NET, нужно просто определить шаги и их содержимое с помощью дескрипторов <asp:WizardStep>. Каждый шаг собирает несколько основных элементов информации. Наиболее важные из них описаны в таблице ниже:

Свойства WizardStep
Свойство Описание
Title

Описательное имя шага. Это имя используется для текста ссылок в боковой панели

StepType

Тип шага, выражаемый в виде значения из перечисления WizardStepType.

Это значение определяет тип навигационных кнопок, которые будут отображаться для данного шага. Возможные варианты выбора: Start (отображает кнопку Next), Step (отображает кнопки Next и Previous), Finish (отображает кнопки Finish и Previous), Complete (не отображает никаких кнопок и скрывает боковую панель, если она используется) и Auto (тип шага определяется на основании позиции в коллекции). Значением по умолчанию является Auto, т.е. первым шагом будет Start, последним - Finish, а всеми остальными - Step

AllowReturn

Показывает, может ли пользователь возвращаться к этому шагу. Если это свойство имеет значение false, то после того, как пользователь пройдет этот шаг, он не сможет вернуться назад. Ссылка боковой панели для этого шага будет недоступной, а кнопка Previous следующего шага либо пропустит этот шаг, либо будет полностью скрыта (в зависимости от того, какое значение имеет свойство AllowReturn в предыдущих шагах)

Приведенный ниже код создает мастер с четырьмя шагами, которые вместе представляют простой опрос. Свойство StepType добавляет в конец опроса шаг Complete, отображающий итоговую информацию. Кнопки навигации и ссылки боковой панели добавляются автоматически:

<body>
    <form id="form1" runat="server">
        <asp:Wizard ID="Wizard1" runat="server" Width="448px"
            BackColor="#EFF3FB" BorderColor="#B5C7DE" BorderWidth="1px" Font-Names="Verdana"
            CellPadding="5" ActiveStepIndex="0" Font-Size="Small"
            >
            <WizardSteps>
                <asp:WizardStep ID="WizardStep1" runat="server" Title="Персональные данные">
                    <h3>Язык программирования</h3>
                    Выберите используемый язык программирования:
                  <asp:DropDownList ID="lstLanguage" runat="server">
                      <asp:ListItem>C#</asp:ListItem>
                      <asp:ListItem>VB</asp:ListItem>
                      <asp:ListItem>J#</asp:ListItem>
                      <asp:ListItem>Java</asp:ListItem>
                      <asp:ListItem>C++</asp:ListItem>
                      <asp:ListItem>C</asp:ListItem>
                  </asp:DropDownList>
                    <br />
                </asp:WizardStep>
                <asp:WizardStep ID="WizardStep2" runat="server" Title="Компания">
                    <h3>Данные о компании</h3>
                    Количество сотрудников:
                    <asp:TextBox ID="txtEmpCount" runat="server"></asp:TextBox><br />
                    Количество городов:     
                    <asp:TextBox ID="txtLocCount" runat="server"></asp:TextBox>
                </asp:WizardStep>
                <asp:WizardStep ID="WizardStep3" runat="server" Title="Софт">
                    <h3>Программы</h3>
                    Необходимые лицензии:
                  <asp:CheckBoxList ID="lstTools" runat="server">
                      <asp:ListItem>Visual Studio 2008</asp:ListItem>
                      <asp:ListItem>Office 2012</asp:ListItem>
                      <asp:ListItem>Windows Server 2008</asp:ListItem>
                      <asp:ListItem>SQL Server 2008</asp:ListItem>
                  </asp:CheckBoxList>
                </asp:WizardStep>
                <asp:WizardStep ID="Complete" runat="server" Title="Итог " StepType="Complete">
                    Спасибо что заполнили эту анкету.<br />
                    Ваши продукты будут доставлены в ближайшее время.
                    <br /><br />
                </asp:WizardStep>
            </WizardSteps>
            <SideBarStyle VerticalAlign="Top" />

        </asp:Wizard>
    </form>
</body>

Шаги мастера показаны на рисунке ниже:

Четыре шага мастера Wizard

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

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

События мастера

Можно написать код, который будет поддерживать мастер за счет реакции на события, перечисленные в таблице ниже:

События Wizard
Событие Описание
ActiveStepChanged

Генерируется, когда элемент управления переключается на новый шаг (либо вследствие того, что пользователь щелкнул на кнопке навигации, либо потому, что код изменил свойство ActiveStepIndex)

CancelButtonClick

Генерируется при щелчке на кнопке Cancel (Отмена). По умолчанию кнопка Cancel не отображается, однако ее можно добавить к каждому шагу, установив свойство Wizard.DisplayCancelButton. Как правило, кнопка Cancel осуществляет выход из мастера. Если какой-либо код очистки отсутствует, просто установите свойство CancelDestinationPageUrl, и мастер автоматически позаботится о переадресации

FinishButtonClick

Генерируется при щелчке кнопки Finish (Готово)

NextButtonClick и PreviousButtonClick

Эти события генерируются при щелчке на кнопке Next или Previous на любом шаге. Однако, поскольку перейти от одного шага к следующему можно несколькими способами, лучше выполнить обработку события ActiveStepChanged

SideBarButtonClick

Генерируется при щелчке на кнопке в области боковой панели

В целом, существуют две модели программирования мастера:

Фиксация по мере выполнения действий (commit-as-you-go)

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

Фиксация в конце работы (commit-at-the-end)

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

Чтобы реализовать последнюю из описанных моделей в рассматриваемом примере, достаточно реализовать реакцию на событие FinishButtonClick. Ниже приведен пример, который просто отображает на странице сводки каждый выбранный пользователем вариант:

protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
{
        lblSummary.Text = String.Format(
            "<b>Вы выбрали: </b><br>Язык программирования: <em>{0}</em><br>" +
            "Число сотрудников: <em>{1}</em><br>Городов: <em>{2}</em><br>Программы: <em>",
            lstLanguage.Text, txtEmpCount.Text, txtLocCount.Text);
        foreach (ListItem item in lstTools.Items)
        {
            if (item.Selected)
            {
                lblSummary.Text += item + " ";
            }
        }
        lblSummary.Text += "</em><br>";
}

Чтобы этот код мог работать, нужно добавить элемент управления Label по имени lblSurnmary. В данном примере этот элемент управления добавлен к итоговому шагу.

Обработка событий Wizard

Чтобы выяснить, какие шаги пользователь выполнил в процессе работы мастера, можно воспользоваться методом Wizard.GetHistory(). Этот метод возвращает коллекцию объектов WizardStepBase, к которым производился доступ до настоящего времени, упорядоченных в обратном хронологическом порядке. То есть первый элемент в коллекции представляет предыдущий шаг, второй элемент представляет шаг, предшествующий первому, и т.д.

Стили, шаблоны и компоновка элемента управления Wizard

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

В зависимости от того, насколько радикально требуется изменить внешний вид мастера, доступны различные варианты. Если изменений немного, можно воспользоваться различными высокоуровневыми свойствами, которые позволяют управлять цветами, шрифтами, интервалами и стилями границ, как это делается в любом элементе управления ASP.NET. Можно также настраивать внешний вид каждой кнопки.

Например, для изменения кнопки Next (Далее) служат следующие свойства: StepNextButtonType (определяет кнопку, ссылку или изображение, принимающее щелчок), StepNextButtonText (настраивает текст кнопки или ссылки), StepNextButtonUrl (задает изображение для кнопки с изображением) и StepNextButtonStyle (использование стиля из таблицы стилей). Можно также добавить верхний колонтитул с помощью свойства HeaderText.

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

Стили Wizard
Стиль Описание
ControlStyle

Применяется ко всем разделам элемента управления Wizard

HeaderStyle

Применяется к разделу верхнего колонтитула элемента управления Wizard, который будет отображаться только в том случае, если в свойстве HeaderText задан какой-либо текст

SideBarStyle

Применяется к области боковой панели элемента управления Wizard

SideBarButtonStyle

Применяется только к кнопкам на боковой панели

StepStyle

Применяется к разделу элемента управления, в котором определяется содержимое шага

NavigationStyle

Применяется к нижней области элемента управления, в которой отображаются кнопки навигации

NavigationButtonStyle

Применяется только к кнопкам навигации в области навигации

StartNextButtonStyle

Применяется к кнопке навигации Next (Далее) на первом шаге (если свойство StepType имеет значение Start)

StepNextButtonStyle

Применяется к кнопке навигации Next на промежуточных шагах (если свойство StepType имеет значение Step)

StepPreviousButtonStyle

Применяется к кнопке навигации Previous (Назад) на промежуточных шагах (если свойство StepType имеет значение step)

FinishPreviousButtonStyle

Применяется к кнопке навигации Previous в последнем шаге (если свойство StepType имеет значение Finish)

CancelButtonStyle

Применяется к кнопке Cancel (Отмена), если свойство Wizard.DisplayCancelButton имеет значение true

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

Полный список шаблонов приведен в таблице ниже:

Шаблоны элемента управления Wizard
Класс шаблона Описание
HeaderTemplate

Определяет содержимое области верхнего колонтитула

SideBarTemplate

Определяет боковую панель, которая обычно включает ссылки навигации для каждого шага

StartNavigationTemplate

Определяет кнопки навигации для первого шага (если свойство StepType имеет значение Start)

StepNavigationTemplate

Определяет кнопки навигации для промежуточных шагов (если свойство StepType имеет значение Step)

FinishNavigationTemplate

Определяет кнопки навигации для последнего шага (если свойство StepType имеет значение Finish)

LayoutTemplate

Определяет общее расположение верхнего колонтитула, боковой панели, области шага и кнопок навигации

Например, ниже показано использование нескольких шаблонов в элементе управления Wizard:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"  %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>Основы ASP.NET</title>
    <style>
        .navigationButton {
            padding: 6px;
            border: 2px solid #29acf7;
            background: white;
            border-radius: 6px;
        }
        .navigationButton:hover {
            background: #29acf7;
            color:white;
            cursor:pointer;
        }
        .sideBar {
            margin-top:20px;
        }
        .navigation {
            padding-top: 10px;
        }
    </style>
</head>

<body>
    <form id="form1" runat="server">
        <asp:Wizard ID="Wizard1" runat="server" Width="448px"
            BackColor="#EFF3FB" BorderColor="#B5C7DE" BorderWidth="1px" Font-Names="Verdana"
            CellPadding="5" ActiveStepIndex="2" Font-Size="Small" OnFinishButtonClick="Wizard1_FinishButtonClick">

            <HeaderTemplate>
                <h3 style="color:green"><%= Wizard1.ActiveStep.Title %></h3>
            </HeaderTemplate>
            <SideBarTemplate>
                <div class="sideBar">
                    <asp:DataList runat="server" ID="SideBarList">
                        <ItemTemplate>
                            <asp:Button runat="server" ID="SideBarButton" />
                        </ItemTemplate>
                        <SelectedItemStyle Font-Bold="True" />
                    </asp:DataList>
                </div>
            </SideBarTemplate>
            <NavigationStyle CssClass="navigation" />
            <StartNavigationTemplate>
                <asp:Button runat="server" Text="Далее" CommandName="MoveNext" CssClass="navigationButton" />
            </StartNavigationTemplate>
            <StepNavigationTemplate>
                <asp:Button runat="server" Text="Назад" CommandName="MovePrevious" CssClass="navigationButton" />
                <asp:Button runat="server" Text="Далее" CommandName="MoveNext" CssClass="navigationButton" />
            </StepNavigationTemplate>
            <FinishNavigationTemplate>
                <asp:Button runat="server" Text="Назад" CommandName="MovePrevious" CssClass="navigationButton" />
                <asp:Button runat="server" Text="Добавить заказ" 
                    CommandName="MoveComplete" CssClass="navigationButton" />
            </FinishNavigationTemplate>

            <WizardSteps>
                <asp:WizardStep ID="WizardStep1" runat="server" Title="Язык программирования">
                    Выберите используемый язык программирования:
                  <asp:DropDownList ID="lstLanguage" runat="server">
                      <asp:ListItem>C#</asp:ListItem>
                      <asp:ListItem>VB</asp:ListItem>
                      <asp:ListItem>J#</asp:ListItem>
                      <asp:ListItem>Java</asp:ListItem>
                      <asp:ListItem>C++</asp:ListItem>
                      <asp:ListItem>C</asp:ListItem>
                  </asp:DropDownList>
                    <br />
                </asp:WizardStep>
                <asp:WizardStep ID="WizardStep2" runat="server" Title="Данные о компании">
                    Количество сотрудников:
                    <asp:TextBox ID="txtEmpCount" runat="server"></asp:TextBox><br />
                    Количество городов:     
                    <asp:TextBox ID="txtLocCount" runat="server"></asp:TextBox>
                </asp:WizardStep>
                <asp:WizardStep ID="WizardStep3" runat="server" Title="Программы">
                    Необходимые лицензии:
                  <asp:CheckBoxList ID="lstTools" runat="server">
                      <asp:ListItem>Visual Studio 2008</asp:ListItem>
                      <asp:ListItem>Office 2012</asp:ListItem>
                      <asp:ListItem>Windows Server 2008</asp:ListItem>
                      <asp:ListItem>SQL Server 2008</asp:ListItem>
                  </asp:CheckBoxList>
                </asp:WizardStep>
                <asp:WizardStep ID="Complete" runat="server" Title="Итог " StepType="Complete">
                    <br />
                    <asp:Label ID="lblSummary" runat="server"></asp:Label>
                    <br /><br />
                    Спасибо что заполнили эту анкету.<br />
                    Ваши продукты будут доставлены в ближайшее время.
                    <br /><br />
                </asp:WizardStep>
            </WizardSteps>
            <SideBarStyle VerticalAlign="Top" />

        </asp:Wizard>
    </form>
</body>
</html>

Результат показан на рисунке ниже:

Шаблоны и стили в Wizard

При использовании шаблонов крайне важно задавать корректные имена команд, чтобы элемент управления Wizard мог подключать стандартную логику. В противном случае придется реализовывать код навигации и упорядочения, который является очень громоздким и подверженным ошибкам. Например, щелчок на кнопке с именем команды MoveNext ведет к автоматическому переходу к следующему шагу. Если вы не уверены, какое имя команды нужно указать, воспользуйтесь удобным методом ускоренного создания шаблона. Выберите элемент управления Wizard в Visual Studio, затем одну из ссылок генерации шаблонов в смарт-теге, например, Convert to StartNavigationTemplate (Преобразовать в StartNavigationTemplate). В результате Visual Studio вставит шаблон, который дублирует внешний вид и поведение кнопки по умолчанию.

В элементе управления wizard легко применять элементы управления проверкой достоверности. Если такие элементы управления обнаружат недопустимые данные, они не позволят пользователю щелкать на какой-либо ссылке в боковой панели (для перехода к следующему шагу) или продолжить с помощью кнопки Next. Однако по умолчанию свойство CausesValidation кнопки Previous установлено в false, вследствие чего пользователь сможет вернуться к предыдущему шагу. Если такое поведение не устраивает, можете создать собственный специальный шаблон и соответствующим образом установить свойство CausesValidation элементов управления.

И, наконец, с помощью шаблона LayoutTemplate можно построить структуру Wizard, указав местоположение панелей навигации и т.д. По сути, LayoutTemplate позволяет указать ASP.NET позиции других шаблонов относительно друг друга. Вставка каждого шаблона выполняется посредством элемента управления PlaceHolder с соответствующим именем (headerPlaceholder, sideBarPlaceholder, wizardStepPlaceholder и navigationPlaceholder).

Пройди тесты
Лучший чат для C# программистов