Example E3403
Visible to All Users

Page Control for ASP.NET MVC - How to create a wizard interface

This example demonstrates how to use the PageControl extension to create a wizard interface.

Create a Wizard

In the example, every wizard step is a tab page that displays multiple fields. Fill in all fields and click the Next button at the bottom of the current page to proceed to the next step, or click the Personal, Date, or Contact tab to navigate to the corresponding step.

Unobtrusive client-side validation occurs before you proceed to the next step. Fix all validation errors to move forward.

Files to Review

Documentation

More Examples

Example Code

E3403/Controllers/HomeController.cs
C#
using E3403.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Drawing; using System.Web.UI.WebControls; using DevExpress.Web.Mvc; namespace E3403.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(new Account()); } } }
E3403/Global.asax
Code
<%@ Application Codebehind="Global.asax.cs" Inherits="E3403.MvcApplication" Language="C#" %>
E3403/Global.asax.cs
C#
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; namespace E3403 { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder(); DevExpress.Web.ASPxWebControl.CallbackError += Application_Error; } protected void Application_Error(object sender, EventArgs e) { Exception exception = System.Web.HttpContext.Current.Server.GetLastError(); //TODO: Handle Exception } } }
E3403/Models/Account.cs
C#
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace E3403.Models { public class Account { [Required(ErrorMessage = "First Name is required")] public string FirstName { get; set; } [Required(ErrorMessage = "Last Name is required")] public string LastName { get; set; } [Required(ErrorMessage = "This checkbox is required")] public bool? IAgree { get; set; } [Required(ErrorMessage = "Any Date is required")] public DateTime? AnyDate { get; set; } [Required(ErrorMessage = "States is required")] public string States { get; set; } [Required(ErrorMessage = "E-mail is required")] [RegularExpression("\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*", ErrorMessage = "Invalid E-Mail")] public string Email { get; set; } } }
E3403/Views/Home/Index.cshtml
Razor
@model E3403.Models.Account @{ ViewBag.Title = "Home Page"; } <script> var form; $(function () { form = $("#validateForm"); }); function onButtonClick(s, e) { var indexTab = (pageControl.GetActiveTab()).index; if (form.valid()) pageControl.SetActiveTab(pageControl.GetTab(indexTab + 1)); } function onFinishClick(s, e) { if (form.valid()) { var str = '<b>Personal Info:</b><br />' + FirstName.GetValue() + '<br />' + LastName.GetValue() + '<hr />'; str += '<b>Date Info:</b><br />' + getShortDate(AnyDate.GetValue().toString()) + '<br />' + States.GetValue() + '<hr />'; str += '<b>Contact Info:</b><br />' + Email.GetValue(); popupControl.SetContentHtml(str); popupControl.ShowAtElement(pageControl.GetMainElement()); popupControl.UpdatePositionAtElement(pageControl.GetMainElement()); var progressBar = ASPxClientControl.GetControlCollection().GetByName("progressBar" + pageControl.GetActiveTabIndex()); progressBar.SetPosition(100); updateLastTabContent(true); } } function updateLastTabContent(isVisible) { panel.SetVisible(!isVisible); repeatButton.SetVisible(isVisible); } function onActiveTabChanged(s, e) { var tabIndex = s.GetActiveTabIndex(); var tabCount = s.GetTabCount(); var progressBar = ASPxClientControl.GetControlCollection().GetByName("progressBar" + tabIndex); progressBar.SetPosition(100 * tabIndex / tabCount); } function onTabClick(s, e) { var activeTabIndex = s.GetActiveTabIndex(); if (e.tab.index < activeTabIndex) return; e.cancel = !form.valid(); } function onRepeatButtonClick(s, e) { ASPxClientEdit.ClearEditorsInContainer(null, '', true); updateLastTabContent(false); pageControl.SetActiveTabIndex(0); popupControl.Hide(); } function getShortDate(longDate) { var date = new Date(longDate); var month = date.getMonth() + 1; var str = month.toString() + '/' + date.getDate().toString() + '/' + date.getFullYear().toString(); return str; } </script> <style> .center { align-items: center; display: flex; justify-content: center; } </style> <div class="center"> @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "validateForm" })) { @Html.DevExpress().PageControl(settings => { settings.Name = "pageControl"; settings.EnableClientSideAPI = true; settings.Width = Unit.Pixel(350); settings.Theme = "Office365"; settings.ClientSideEvents.ActiveTabChanged = "onActiveTabChanged"; settings.ClientSideEvents.TabClick = "onTabClick"; settings.TabPages.Add("Personal").SetContent(() => { Html.RenderPartial("_PersonalPartial", Model); }); settings.TabPages.Add("Date").SetContent(() => { Html.RenderPartial("_DatePartial", Model); }); settings.TabPages.Add("Contact").SetContent(() => { Html.RenderPartial("_ContactPartial", Model); }); }).GetHtml() } </div> @Html.DevExpress().PopupControl( settings => { settings.Name = "popupControl"; settings.HeaderText = "Summary"; settings.PopupElementID = "popupAnchor"; settings.ShowOnPageLoad = false; settings.CloseAction = CloseAction.CloseButton; settings.PopupHorizontalAlign = PopupHorizontalAlign.OutsideRight; settings.PopupHorizontalOffset = 10; }).GetHtml()
E3403/Views/Home/_ContactPartial.cshtml
Razor
@model E3403.Models.Account <div id="ContactContent"> @Html.DevExpress().ProgressBar(settings => { settings.Name = "progressBar2"; settings.Theme = "iOS"; settings.Width = Unit.Percentage(100); settings.Properties.IndicatorStyle.BorderBottom.BorderColor = (Color)ColorTranslator.FromHtml("#F87C1D"); settings.Properties.Minimum = 0; settings.Properties.Maximum = 100; settings.Position = 0; }).GetHtml() <br /> @Html.DevExpress().Button(buttonSettings => { buttonSettings.Name = "repeatButton"; buttonSettings.Text = "Repeat"; buttonSettings.ClientVisible = false; buttonSettings.ClientSideEvents.Click = "onRepeatButtonClick"; buttonSettings.UseSubmitBehavior = false; }).GetHtml() @Html.DevExpress().Panel(settings => { settings.Name = "panel"; settings.EnableClientSideAPI = true; settings.FixedPosition = DevExpress.Web.PanelFixedPosition.None; settings.SettingsCollapsing.ExpandEffect = DevExpress.Web.PanelExpandEffect.Auto; settings.SetContent(() => { @Html.DevExpress().TextBox(editorSettings => { editorSettings.Name = "Email"; editorSettings.Properties.Caption = "E-Mail"; editorSettings.Properties.CaptionSettings.Position = EditorCaptionPosition.Top; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; }).Bind(Model.Email).GetHtml(); ViewContext.Writer.Write("<hr />"); @Html.DevExpress().Button(buttonSettings => { buttonSettings.Name = "btnFinish;"; buttonSettings.Text = "Finish"; buttonSettings.ClientSideEvents.Click = "onFinishClick"; buttonSettings.UseSubmitBehavior = false; }).GetHtml(); }); }).GetHtml() </div>
E3403/Views/Home/_DatePartial.cshtml
Razor
@model E3403.Models.Account <div id="DateContent"> @Html.DevExpress().ProgressBar(settings => { settings.Name = "progressBar1"; settings.Theme = "iOS"; settings.Width = Unit.Percentage(100); settings.Properties.IndicatorStyle.BorderBottom.BorderColor = (Color)ColorTranslator.FromHtml("#F87C1D"); settings.Properties.Minimum = 0; settings.Properties.Maximum = 100; settings.Position = 0; }).GetHtml() @Html.DevExpress().DateEdit(editorSettings => { editorSettings.Properties.Caption = "Any Date"; editorSettings.Properties.CaptionSettings.Position = EditorCaptionPosition.Top; editorSettings.Name = "AnyDate"; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; }).Bind(Model.AnyDate).GetHtml() <hr /> @Html.DevExpress().ComboBox(editorSettings => { editorSettings.Name = "States"; editorSettings.Properties.Caption = "States"; editorSettings.Properties.CaptionSettings.Position = EditorCaptionPosition.Top; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; editorSettings.Properties.ValueType = typeof(string); editorSettings.Properties.Items.Add("Alaska", "Alaska"); editorSettings.Properties.Items.Add("Indiana", "Indiana"); editorSettings.Properties.Items.Add("Kentucky", "Kentucky"); editorSettings.Properties.Items.Add("Minnesota", "Minnesota"); editorSettings.Properties.Items.Add("Nevada", "Nevada"); }).Bind(Model.States).GetHtml() <hr /> @Html.DevExpress().Button(buttonSettings => { buttonSettings.Name = "btnGoToMoreTab;"; buttonSettings.Text = "Next"; buttonSettings.ClientSideEvents.Click = "onButtonClick"; }).GetHtml() </div>
E3403/Views/Home/_PersonalPartial.cshtml
Razor
@model E3403.Models.Account <div id="PersonalContent"> @Html.DevExpress().ProgressBar(settings => { settings.Name = "progressBar0"; settings.Theme = "iOS"; settings.Width = Unit.Percentage(100); settings.Properties.IndicatorStyle.BorderBottom.BorderColor = (Color)ColorTranslator.FromHtml("#F87C1D"); settings.Properties.Minimum = 0; settings.Properties.Maximum = 100; settings.Position = 0; }).GetHtml() @Html.DevExpress().TextBox(editorSettings => { editorSettings.Name = "FirstName"; editorSettings.Properties.Caption = "First Name"; editorSettings.Properties.CaptionSettings.Position = EditorCaptionPosition.Top; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; }).Bind(Model.FirstName).GetHtml() <hr /> @Html.DevExpress().TextBox(editorSettings => { editorSettings.Name = "LastName"; editorSettings.Properties.Caption = "Last Name"; editorSettings.Properties.CaptionSettings.Position = EditorCaptionPosition.Top; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; }).Bind(Model.LastName).GetHtml() <hr /> @Html.DevExpress().CheckBox(editorSettings => { editorSettings.Name = "IAgree"; editorSettings.Text = "I agree"; editorSettings.ShowModelErrors = true; editorSettings.Properties.ValidationSettings.ErrorDisplayMode = ErrorDisplayMode.ImageWithText; }).Bind(Model.IAgree).GetHtml() <hr /> @Html.DevExpress().Button(buttonSettings => { buttonSettings.Name = "btnGoToContactTab;"; buttonSettings.Text = "Next"; buttonSettings.ClientSideEvents.Click = "onButtonClick"; }).GetHtml() </div>

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.