logo

C# How to use a singleton pattern as a sequeway between Windows in WPF

Overview: I use a Singleton pattern to instantiate all forms in my application. I can access the form by its type. This model does not allow for multiple forms to be instantiated of the same type. The form type and the instance of the form are stored into a static dictionary. The Activator.CreateInstance will instantiate an instance of the form using its type. The owner is passed by argument as a parameter to the FormSingleton class. When the instance of the form is closed, a delegate function is callbacked an the form is removed from the static dictionary called dictForms.

WPF uses the app.xaml to launch the mainwindow.xaml using a starturi. Remove the starturi application attribute and replace it with an override method of OnStartup. In OnStartup use the extension class FormSingleton to invoke the instance of the MainWindow form and then display with the .Show method. Pass null as an owner since MainWindow is the root window. On the MainWindow I created a button for launching a child window form.

In the child window, I use the SingletonForm GetInstance to get the MainWindow instance by type and access its controls by name retrieving a combo box item data by using the comboboxitem class.

Form Singleton Class Pattern


   public class FormSingleton
    {
        static Dictionary<Type, Window> dictForms = new Dictionary<Type, Window>();

        static public T GetInstance<T>(Window owner) where T : Window
        {
            if (!dictForms.ContainsKey(typeof(T)))
            {
                Window form = (Window)Activator.CreateInstance(typeof(T), null);
                form.Owner = owner;
                dictForms.Add(typeof(T), form);
                form.Closing += new CancelEventHandler(MainWindow_Closing);

            }

            return (T)dictForms[typeof(T)];

        }
        static void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            Window form = sender as Window;
            if (form == null) return;

            dictForms.Remove(form.GetType());
        }

    }

MainWindow ChildForm button Click


 private void cmdForm_Click(object sender, RoutedEventArgs e)
        {
            if (cboMammalType.SelectedItem == null)
            {
                MessageBox.Show("Please select an animal");
                return;
            }
            ChildForm childForm = FormSingleton.GetInstance<ChildForm>(this);
            childForm.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            childForm.Show();
        }

The Singleton sequeway between forms

 public ChildForm()
        {
            InitializeComponent();

            MainWindow mainWindow = FormSingleton.GetInstance<MainWindow>(this);

            ComboBoxItem selectedItem = (ComboBoxItem)(mainWindow.cboMammalType.SelectedValue);
            txtAnimal.Text = (string)(selectedItem.Content);


        }

App.xaml

1. Remove the StartupUri="MainWindow.xaml" xml application attribute from the app.xml.  This prevents the automatic load of the MainWindow.xaml
2. Override the abstract method OnStartup using the formSingleTon.

protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            MainWindow mainWindow = FormSingleton.GetInstance<MainWindow>(null);
            mainWindow.Show();

        }
In short, I have shown you how to use a Singleton pattern to pass data between WPF forms. The singleton is a persistent object in memory.
s