Guest mgama Posted February 10, 2005 Report Posted February 10, 2005 I'm trying to get some input from the user, and it makes sense for me to use a wizard. Currently I just chained together 3 separate windows forms, each of them with their own menu bar. My first form has Cancel and Next menu buttons. The second has Back and Next menu buttons. And the final has Back and Finish buttons. This allows the user to navigate forwards and backwards. To cancel, they just need to get back to the first one, and click cancel. It is working pretty well. Going forwards is fine, but when going backwards, I'm getting some unwanted pauses between the current form being closed the next (really previous) one being drawn. The pause allows the homescreen to briefly show through while waiting for the new form to be drawn. I'd like to hear what solutions to the wizard some other people have come up with. I thought about using multiple panels, and placing them all on one form, but the last time I experimented with multiple panels on one form, I had some focus problems (focus could not move between panels). The other option is to just use a cancel button in place of the Back button. That would solve me homescreen showing through problem, but it may inconvenience the user. That’s what the pocket outlook new email account wizard uses.
Guest bdmoore Posted February 11, 2005 Report Posted February 11, 2005 How are you navigating between forms - are you closing them or hiding them?
Guest mgama Posted February 11, 2005 Report Posted February 11, 2005 How are you navigating between forms - are you closing them or hiding them? <{POST_SNAPBACK}> I'm closing them. I return DialogResult.OK for the next/finish buttons, and DialogResult.Cancel on the back/cancel buttons. My wizard function logic then looksl like ShowFirstDialog: if (dlg1.ShowDialog() != DialogResult.OK) return false; ShowSecondDialog: if (dlg2.ShowDialog() != DialogResult.OK) goto ShowFirstDialog; ShowThirdDialog: if (dlg3.ShowDialog() != DialogResult.OK) goto ShowSecondDialog; if (dlg4.ShowDialog() != DialogResult.OK) goto ShowThirdDialog; I'm sure there is a better way of doing this, maybe using Show/Hide, and I would like to hear and learn what route or suggestions other people recommend.
Guest bdmoore Posted February 11, 2005 Report Posted February 11, 2005 (edited) The ShowDialog() method creates a new instance of the form each time it is called. This can cause a delay in your application, especially on slower devices. Instead try creating an instance of each of the forms for your wizard at the start of the process, and use the Form.Show() and Form.Hide() methods when navigating between the forms. This way when moving back to a previous form, your are simply re-using the same instance of the form which is already in memory instead of creating a new instance. This will also mean that the form values will be preserved without you having to re-set them on load. Once the user completes the wizard, you can dispose the forms to free up memory. You'll need to make the Next button on Form1 show Form2 and hide Form1 and the cancel button on Form2 show Form1 etc. Edited February 11, 2005 by bdmoore
Guest mgama Posted February 12, 2005 Report Posted February 12, 2005 Thanks. Thats what I figured. I will just need to come up with a clean way of maintaining that. As it stands now, it is really easy for me to add new "pages" to my wizard, rearange them, etc., without each class having to worry about which one comes before and after it.
Guest bdmoore Posted February 12, 2005 Report Posted February 12, 2005 (edited) One way would be to create a Wizard class which contains an array of forms (_wizardForms), with a private field _currentFormIndex. The form buttons could then call generic methods on the Wizard class (ShowNextPage(), ShowPreviousPage() etc) For example: public class Wizard { private System.Windows.Forms.Form[] _wizardForms; private int _currentFormIndex; public Wizard() { // Initialise the required forms _wizardForms = new System.Windows.Forms.Form[3]; _wizardForms[0] = new MyForm1(); ((MyForm1)_wizardForms[0]).Wizard = this; // Reference back to self - form needs to know it's caller _wizardForms[1] = new MyForm2(); ((MyForm2)_wizardForms[1]).Wizard = this; _wizardForms[2] = new MyForm3(); _((MyForm3)_wizardForms[2]).Wizard = this; } public void StartWizard() { _currentFormIndex = 0; _wizardForms[0].Show(); } public void ShowNextForm() { if(_currentFormIndex < (_wizardForms.Length - 1)) { // More forms to display _wizardForms[_currentFormIndex].Hide(); _currentFormIndex++; _wizardForms[_currentFormIndex].Show(); } else { endWizard(); } } public void ShowPreviousForm() { if(_currentFormIndex > 0) { // More forms to display _wizardForms[_currentFormIndex].Hide(); _currentFormIndex--; _wizardForms[_currentFormIndex].Show(); } else { cancelWizard(); } } private void endWizard() { //TODO: Save settings and tidy up } private void cancelWizard() { //TODO: Tidy up } } Then the menu buttons on your pages can just call this.Wizard.ShowNextPage() or ShowPreviousPage() and the logic is all contained in one place. From the calling application, all you need to do is: Wizard myWizard = new Wizard(); myWizard.StartWizard(); This needs a bit more work to tidy up the form references and back references to the wizard class etc. You could customize it more if needed by passing in parameters to the Wizard constructor saying what forms to use and so on. You could also neaten it up by creating a WizardForm() class which inherits from the Form class and has a Wizard property. Make your input forms inherit this instead of the standard Form class. The Form[] array would then become a WizardForm[] array and you wouldn't need to cast the forms in the constructor. HTH :lol: Ben Edited February 12, 2005 by bdmoore
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now