Search code examples
c#wpfstack-overflow

I get stack overflow when instantiate a class inside WPF MainWindow?


When i create an instance of a class and call a method from it, I get stack overflow error! Actually i want to prevent writing whole my code inside the MainWindow, so i need to separate them into different classes.

This is my custom class (class2):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    class Class2
    {
        private string[] names = { "USA", "Canada", "China", "Peru", "Germany" }; // really simple array
        MainWindow mn = new MainWindow(); // Main window instance

        public void lbxm() // this method shows array element inside a listBox
        {
            ListBox lbx = new ListBox() { Width = 200 };
            for (int i = 0; i < names.Length; i++)
            {
                lbx.Items.Add(names[i]);
            }

            mn.grd.Children.Add(lbx); // place the listBox in Main grid layout
        }
    }
}

This is MainWindow:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {


        public MainWindow()
        {
            InitializeComponent(); // here's the problem, i get stackoverflow exception...
            Class2 cl2 = new Class2(); // instance of class2
            cl2.lbxm();// call the method
        }

    }
}

Solution

  • When you create a new instance of Class2, you're also creating a new instance of MainWindow:

    class Class2
    {
        private string[] names = { "USA", "Canada", "China", "Peru", "Germany" }; // really simple array
        MainWindow mn = new MainWindow(); // Main window instance <- this is the problem
        ...
    }
    

    The problem is when Class2 creates a new MainWindow, the new MainWindow then creates a new Class2:

    public MainWindow()
    {
        InitializeComponent(); // here's the problem, i get stackoverflow exception...
        Class2 cl2 = new Class2(); // instance of class2
        ...
    }
    

    This new Class2 then creates ANOTHER MainWindow, and the cycle repeats until stack overflow. Even if this code did not create a loop that caused a stack overflow, this code would still not work the way you want. The MainWindow you're creating in Class2 is not the main window your application created: it's a brand new MainWindow object.

    If you need your Class2 to update objects in MainWindow (which may not be the best way to solve this problem depending on your use case), I would pass the control to the class instead of giving the class a reference to its parent. Something like this would work:

    //In Class2
    public void PopulateListBox(ListBox grd) 
    {
        for (int i = 0; i < names.Length; i++)
        {
            grd.Items.Add(names[i]);
        }
    }
    

    To call the method:

    //In MainWindow
    Class2 cl2 = new Class2();
    cl2.PopulateListBox(grd); // pass the ListBox where you want the items.
    

    As I mentioned, there are likely better ways to solve this problem than passing a control to a class. This couples your classes to your UI, which in general is not desirable. But this basically does what you wanted your original code to do.