2

I'm writing an application that uses a wizard-like series of 5 simple forms. The first form, NewProfile, is opened from a menu item on the main application, MainForm, so is a subform of MainForm. The second form, TwoProfile, is opened from a button on NewProfile. The third form, ThreeProfile is opened from a button on TwoProfile, and so on for all 5 forms. Here is the sequence: MainForm --> NewProfile <--> TwoProfile <--> ThreeProfile <--> FourProfile <--> FiveProfile. My problem is that when any form (NewProfile, TwoProfile, ThreeProfile, FourProfile or FiveProfile) is open, I don't want a user to be able to create an instance of NewProfile.

I started out by implementing a Singleton pattern, which half-way works. It works if NewProfile is open and I go to MainForm and try to create another instance of NewProfile. It does not work if NewProfile has been destroyed, by advancing to the next form and one of TwoProfile, ThreeProfile, FourProfile or FiveProfile is open. It tells me that NewProfile.IsDisposed is true, giving me a bad reference to the Singleton instance.

What I can't figure out is how to do my logic so that NewProfile won't be created if one of TwoProfile, ThreeProfile, FourProfile or FiveProfile is open or if NewProfile itself is open.

I hope this made sense. I don't really have much code to post, except what I did for my Singleton.

   private static NewProfile _instance = null;
   public static NewProfile Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new NewProfile();
            }
            return _instance
        }
    }

Thank you :)

user1791622
  • 105
  • 1
  • 2
  • 8
  • 2
    Why do you not just use One Form which contains a usercontrol and than you just change the Usercontrol in your Mainform that will secure that you just open "one" form and all your Usercontrols are stored in a List and which you Next or Back buttons you can handel which UC is loaded – Venson Jan 19 '13 at 19:26
  • 1
    Could you simply Hide() the NewProfile instead of destroying it when you open SecondProfile? – Steve Jan 19 '13 at 19:27
  • Have you looked at doing MDI..? – MethodMan Jan 19 '13 at 19:34

2 Answers2

1

As suggested in the comments, each "form" could actually be a usercontrol you swap. That way, you only have one form and multiple pages. Alternatively, you can hide the form.

If you want multiple forms instead, then you could loop through all the open forms and see if the the ones you want to check are open. If not, you can open NewProfile.

bool shouldOpenNewDialog = true;

foreach (Form f in Application.OpenForms)
{       
    //give each dialog a Tag value of "opened" (or whatever name)
    if (f.Tag.ToString() == "opened")
        shouldOpenNewDialog = false;    
}


if(shouldOpenNewDialog)
    np = new NewProfile();

It's untested, but it should loop through all open forms and look for any that has a Tag saying opened. If it comes across one, then it set the shouldOpenNewDialog flag to false and NewProfile won't be called.

keyboardP
  • 68,824
  • 13
  • 156
  • 205
  • Thank you for all of your timely responses! I put a lot of effort into my forms, so I didn't really want to have to do a bunch of rework. What ended up working is a variation of keyboardP's suggestion. I did this in MainForm menu item handler: – user1791622 Jan 19 '13 at 21:24
  • 1
    Whoops, I meant to go to the next line...hehe. if (Application.OpenForms.Count > 1) { shouldOpenDialog = false; } if (shouldOpenDialog) { newProfile.Show(); } – user1791622 Jan 19 '13 at 21:25
  • Feel free to post your final code as an answer and then accept it in a couple of days :) – keyboardP Jan 19 '13 at 21:27
1

The way that we handle this is to have a static window manager class that keeps track of the open form instances. When the user performs an action that would cause a new window to open, we first check the window manager to see if the form is already open. If it is, we set focus on it rather than creating a new instance.

Every form that is opened inherits from a base form implementation that automatically registers itself with the window manager when it is opened and removes its registration when it is closed.

Here is a rough outline of the WindowManager class:

public class WindowManager
{
    private static Dictionary<string, Form> m_cOpenForms = new Dictionary<string, Form>();

    public static Form GetOpenForm(string sKey)
    {
        if (m_cOpenForms.ContainsKey(sKey))
        {
            return m_cOpenForms[sKey];
        }
        else
        {
            return null;
        }
    }
    public static void RegisterForm(Form oForm)
    {
        m_cOpenForms.Add(GetFormKey(oForm), oForm);
        oForm.FormClosed += FormClosed;
    }

    private static void FormClosed(object sender, FormClosedEventArgs e)
    {
        Form oForm = (Form)sender;
        oForm.FormClosed -= FormClosed;
        m_cOpenForms.Remove(GetFormKey(oForm);
    }

    private static string GetFormKey(Form oForm)
    {
        return oForm.Name;
    }
}

And you can use it as follows:

        Form oForm = WindowManager.GetOpenForm("Form1");
        if (oForm != null)
        {
            oForm.Focus();
            oForm.BringToFront();
        }
        else
        {
            oForm = new Form1();
            WindowManager.RegisterForm(oForm);
            // Open the form, etc
        }
competent_tech
  • 44,465
  • 11
  • 90
  • 113