Wizard is based on TransitioningSelector, which is an ItemsControl and is similar to TabControl in how it works (though it does not derive from System.Windows.Controls.TabControl.) The native container type for Wizard is WizardPage. An object placed into a wizard’s Items collection are wrapped by instances of WizardPage, unless the item itself is a WizardPage. The content displayed by the wizard is defined as the value of the Content property of the current wizard page. The current page is identified by the CurrentPage property and is controlled via the wizard’s SelectedItem property.

Controlling button states

There are 5 buttons that are built-in by default, one for each of the following commands: Help, Back, Next, Finish and Cancel. There is a property of type WizardButtonState for each button. For example: HelpButtonState and NextButtonState. WizardButtonState is an enumeration with the following possible values: Auto, Disabled, Enabled and Hidden. All of the wizard button states are set to Auto by default.

A value of Auto indicates that the buttons actual state should be determined automatically, generally based on the index of the current selected item within the Items collection. Here is a break down of how a value of Auto affects each of the buttons:

  • Help – hidden.
  • Back – enabled if selected item is not at index 0 of Items collection, otherwise disabled.
  • Next – enabled if selected item is not the last item in the Items collection, otherwise hidden.
  • Finish – enabled if the selected item is the last item in the Items collection, otherwise hidden.
  • Cancel – always enabled.

It is apparent that Auto is sufficient for only the simplest of wizards. For more complex scenarios, the programmer will need to exercise direct control over wizard button states. Generally speaking, the best approach is to let each page specify the button states for itself. WizardPage defines the same button state properties as Wizard, and while a page’s value for a button state is inherited from the parent wizard by default, a button’s state is ultimately determined by the current page.

Controlling button content

There is a content property for each of the four buttons Help, Next, Finish and Cancel. For example, both Wizard and WizardPage define a NextButtonContent property. As with button states, button content is determined by the current page, while the page by default inherits its value from the parent wizard, if not explicitly set. The Wizard property ButtonContentTemplate can be used to specify a DataTemplate that shows how to render the content of the buttons. The same template is applied to all 4 buttons.

The one button that does not have a content property associated with it is the Back button. This is because the default back button displays an arrow and has custom handling for mouse over and pressed. But it is possible to override the Style that is used for the Back button. To do so, define a Style as a resource Key equal to the component resource key Wizard.BackButtonStyleKey. For example:

<Style x:Key="{x:Static dc:Wizard.BackButtonStyleKey}" TargetType="Button">    
... </Style
>

Controlling navigation

By default, when the user clicks the Next button, the wizard will show the item which follows the current item in the order in which the items were added to the Items collection. This is ok for the simplest wizards, but not sufficient for more complex wizards that feature branching or intelligent navigation. There are two ways to specify the page that gets selected in response to a navigation request such as when the user clicks the next button. One is through an event handler and the other is a callback delegate.

Navigation events

The following routed events are associated with navigation:

  • public event WizardNavigationRequestEventHandler BackRequested
  • public event WizardEventHandler CancelRequested
  • public event WizardEventHandler FinishRequested
  • public event WizardNavigationRequestEventHandler NextRequested

Setting Handled on the event argument of any of these events will cancel or deny the associated operation.

WizardEventHandler (the handler type for the CancelRequested  and FinishRequested events) is invoked with an instance of WizardEventArgs, which in turn is derived from RoutedEventArgs. WizardEventArgs exposes a single property: CurrentPage.

The event arguments for WizardNavigationRequestEventHandler is an instance of WizardNavigationRequestEventArgs. WizardNavigationRequestEventArgs inherits from WizardEventArgs and adds a single new property: Destination.

When any of the above events is raised, the event args will contain the object associated with the current wizard page.

When either BackRequested or NextRequested is raised, the event args will also contain the object that is associated with the default destination page. To override the default, simply set the value of Destination to the object that is associated with the page you wish to navigate to.

Navigation callbacks

For situations where it is not convenient to handle the navigation events described above, such as in an MVVM based application, Wizard defines delegate properties which serve as callback methods. Below are listed the dependency properties defined that serve as callback delegates. These properties are defined on both Wizard and WizardPage. Values specified directly on a WizardPage take precedence over the Wizard value. Since the properties are defined as dependency properties, they can be data-bound, and can be used by your view model.

  • public WizardNavigationCallback BackRequestedCallback
  • public Predicate<object> CancelRequestedCallback
  • public Predicate<object> FinishRequestedCallback
  • public WizardNavigationCallback NextRequestedCallback

BackRequestedDelegate and NextRequestedDelegate are both defined as WizardNavigationCallback delegates. WizardNavigataionDelegate is defined as follows:

public delegate object WizardNavigationCallback(object currentPageItem, object proposedPageItem);

The first parameter will be the object associated with the current page, while the second parameter will be a reference to the object which is associated with the destination page which the wizard determines by default. Methods which implement the callback should return the object that is associated with the wizard page that should be the next page displayed by the Wizard. A return value of null will cancel the navigation.

The delegates for Cancel and Finish are defined as Predicate<object>. The method implementing this delegate should take an object as parameter and return a Boolean. The parameter will be a reference to the object which is associated with the current page. A return value of false will cancel the navigation request.

Showing help

If you elect to show the Help button, you are responsible for presenting the appropriate help content to the user when the button is clicked. Notification that the Help button was clicked is provided via the HelpRequested routed event. There is also an optional callback delegate defined as a dependency property named HelpRequestedCallback of type Action<object> on both Wizard and WizardPage which you can utilize. The parameter will contain a reference to the object which is associated with the current wizard page.

Controlling the wizard programmatically

Wizard exposes the following methods:

  • public void Back()
  • public void Next(object nextPage = null)
  • public void Finish()
  • public void Cancel()
  • public void Help()

A call to any of the above methods has the same result as if the user clicked the corresponding button.

The dependency property “MethodInvocationTrigger” can be used to trigger a call to any of the above methods. This is useful for scenarios such as an MVVM based application where calling a method on the Wizard control directly is not convenient. The property is an enumeration named WizardMethodInvocationTrigger with the following values: None, Next, Back, Finish, Cancel and Help. The default value  is None. To trigger a method call, set MethodInvocationTrigger to the value which corresponds to the method you wish to be invoked. Once the method has been invoked, the value of MethodInvocationTrigger will automatically be reset to None.

Styling a-la Windows 7

Wizard

The default styling for Wizard is designed to closely emulate the standard Windows 7 (and 8) wizard, such as the one that is used by Windows to set up a new network or network connection. (Although wizards with a completely different look and feel are easily created using the full power of WPF styling and templating.) There are, however, a couple things which you should be aware of when creating a Windows 7 style wizard. Notice first how in a Windows 7 wizard the window chrome extends down past the back button. Also, notice that the wizard window’s icon and title are missing, yet in the Windows task bar there is a button with icon and title for the same window. Achieving both of these effects requires using the low-level API to manipulate the window. But don’t worry, the methods are built-in to the Wizard control, though you do need to enable them and you do that with the properties:

  • ExtendParentWindowFrame – When true, causes the window frame of the wizard’s parent window to be extended down past the back button in the default template. False by default.
  • HideParentWindowIconAndTitle – When true, causes the icon and title of the wizard’s parent window to be hidden.

The other item necessary for a true Windows 7 styled wizard is the WizardButton. WizardButton is a separate control that inherits from Button with three additional properties: Description, DescriptionTemplate and Image. WizardButton is styled to emulate a button in a Windows 7 wizard. Use it just like you would any Button in your wizard pages.

Related posts:

  1. WPF RadialMenu Quick Start Guide
  2. TransitioningSelector Quick Start Guide
  3. ProgressSteps Quick Start Guide, DotNetBar for WPF
  4. WPF AdvToolBar Quick Start Guide
  5. WPF Schedule Quick Start Guide