Introduction
This post is a continuation of [Article] WPF Wizard control with MVVM support. Here I am trying to address some of the concerns people have regarding wizard control. This include1. How to share/collect data from each view.
2. How to control the navigation or how to validate before navigation.
To know more on the basics, please refer to the parent article. Here I have modified the wizard control files. The wizard comes with three files.
This control comes in three files.
1. Wizard.cs
2. WizardItemHeader.cs
3. IWizardItem.cs
You can download this control from Github page. Contribution to this control will be appreciated.
public interface IWizardItem { /// <summary> /// This method should return the header for wizard item to display /// </summary> /// <returns> A string value.</returns> string GetHeader(); /// <summary> /// This method will be the first to get invoked even before the OnViewActivated call. This method will pass a shard object to views in wizard where they can collect the shared object. /// </summary> /// <param name="sharedObject"> /// This is the shared object. This will contain information from other views in the wizard. /// </param> void CollectSharedObject(object sharedObject); /// <summary> /// This method will be invoked to check whether this item can be displayed or not. /// </summary> /// <returns>A boolean value indicating true or false status</returns> bool CanDisplay(); /// <summary> /// This method will get invoked when the wizard item becomes the active item. /// </summary> /// <param name="autoAcknoledgeNext"> /// The auto Acknoledge Next. Setting this to true will help wizard skip this view and take you to the next page automatically. /// </param> void OnWizardItemNavigatedTo(ref bool autoAcknoledgeNext); /// <summary> /// This method will get invoked on the current wizard item when the control is moved to next wizard item. /// </summary> /// <param name="canNavigateAway"> /// The can Navigate Away. This value when set to false, will not allow navigation from this view. You can use this to do some validation before you navigate to next view. /// </param> void OnWizardItemNavigatedFrom(ref bool canNavigateAway); }
IWizardItem is the interface which you need to implement on the viewmodel for the view which you will show in the wizard. Here wizard also exposes a property called “SharedObject” this can be of any type which. The wizard will then pass it to the viewmodel of the view currently displayed. So the viewmodel can collect it and save data on to this and can be used at later stage.
Now you can use this wizard in wpf as shown below.
<wizardView:Wizard CancelCommand="{Binding CancelCommand}" OkCommand="{Binding OkCommand}" SharedObject="{Binding SharedObject}" Orientation="Top" FinalButtonText="Done" WizardItems="{Binding WizardItems}" />
You can download the sample code from Here.
Thanks for providing this great wizard program. Could you please let me know how can i display information say in a 3rd window with the information that was collected in SharedObject. How would you bind a property from the object to a view label control?
ReplyDeletethank you so much for your help
What do you mean by a third control?
Delete1. If the third window a view in wizard
if this is the case then on your viewmodel of the 3rd window, when you implement IWizard item, then you can collect this shared object from CollectSharedObject method. This will be the first to get fired by wizard control before OnWizardItemNavigatedTo. You can then collect information from this shared object and then can show in the third window.
2. If your question is how to show information from shared object on to a different window, then I would say, wizard control will be just like any other control which you will use in a view, which will have a ViewModel as-well, it is from this view model that you will bind all information required for the wizard control, it is from this view model you will have to create an d pass a shared object, and now on the command handler which you have bind to OkCommand collect this shared object and pass it on to the different view.
Hi Jacob. Thank you for your great article and code sample. I've been using it and it works great. I have a quick question for you. How can I disabled the final button? Let's say that there's a process that needs to complete before the "done" or "finish" button is enabled.
ReplyDeleteThank you
David Peterson
I would recommend you rely on CanExecute feature of ICommand. Here the enabled/disabled status of the button which is bind to an ICommand depends on the status of the task which needs to be completed before the final button is enabled. i.e rely on the CanExecute feature of the ICommand.
DeleteI mean to say, The OkCommand (OkCommand="{Binding OkCommand}") which you have to supply, will have to have its CanExecute depending on the status of the task which you have to complete. The canExecute functionality of the ICommand will take care of the enabling and disabling of the final button.
ReplyDeleteJacob would you be able to provide an example to how disable the "done" button?
DeleteIn addition, is there a way that when you are in a view in the wizard and an user clicks on a button that the OnWizardItemNavigatedTo method can be invoked again to skip the current view to the next one automatically without the need to click on the "Next" button on the wizard?
Thank you
The bool CanDisplay(); method will come in handy. Just return false and it will take you to the next page. You can do all necessary activity in this method before returning false.
DeleteHi Jacob,
ReplyDeleteThis is a nice wizard.
what is the best way to change the style of the wizard? e.g. I would like to use the MahApps theme on it and change the tab item template to include icons instead of showing just the Numbers.