adding OnClick with a parameter to a button at runtime not working

i have the following code

    public void OnClickMaterialChooserDir(int idx)
    {
        Debug.Log("OnClickMaterialChooserDir "+idx);
    }

    public void PopulateMaterialChooserPanel()
    {
        //Debug.Log("PopulateMaterialChooserPanel");

        string myPath = "Assets/Resources/Materials/";
        DirectoryInfo matdir = new DirectoryInfo(myPath);

        DirectoryInfo[] dirInfo = matdir.GetDirectories();

        //FileInfo[] info = dir.GetFiles("*.*");
        int i = 0;
        foreach (DirectoryInfo dir in dirInfo)
        {
            //ItemGameObject is my prefab pointer that i previous made a public property
            //and  assigned a prefab to it
            DefaultControls.Resources TempResource = new DefaultControls.Resources();
            GameObject buttonGO = DefaultControls.CreateButton(TempResource);
            buttonGO.AddComponent<LayoutElement>();
            Button dirButton = buttonGO.GetComponent<Button>();
            dirButton.onClick.AddListener(() => { OnClickMaterialChooserDir(i); }); //AddListener(delegate { OnClickMaterialChooserDir(i); });
Debug.Log("PopulateMaterialChooserPanel "+i);
            i++;
            Text text = dirButton.transform.GetChild(0).GetComponent<Text>();
            text.text = dir.Name;
            text.fontStyle = FontStyle.Bold;
            text.fontSize = 16;

            dirButton.transform.SetParent(_MaterialChooserScrollViewContent, false);
        }
    }

It creates buttons in a scrollview based on the directories in a resources folder, and it works, the buttons are created, the correct label text is set and i can click.
but when i get the callback to OnClickMaterialChooserDir idx is always 3 (the number of directories in this case)
i got the idea for the code from here

i tried both the delegate method and the one you see here and both give the same result
does anyone know what’s wrong?
thx
PS, PopulateMaterialChooserPanel() is only called from Start

i suspect the problem is the buttons are created at run time, not sure

ok i found it, i think if i had done a ‘new Int()’ instead of ‘i’ it would have worked, anyhow this is want i really wanted and it works

    public void OnClickMaterialChooserDir(string dir)
    {
        Debug.Log("OnClickMaterialChooserDir "+dir);
        //PopulateMaterialChooserPanel(dir);
    }

    public void PopulateMaterialChooserPanel(string baseDir)
    {
        //Debug.Log("PopulateMaterialChooserPanel");

        string myPath = "Assets/Resources/Materials/"+ baseDir;
        DirectoryInfo matdir = new DirectoryInfo(myPath);

        DirectoryInfo[] dirInfo = matdir.GetDirectories();

        FileInfo[] fileInfo = matdir.GetFiles("*.mat");

        foreach (DirectoryInfo dir in dirInfo)
        {
            //ItemGameObject is my prefab pointer that i previous made a public property
            //and  assigned a prefab to it
            DefaultControls.Resources TempResource = new DefaultControls.Resources();
            GameObject buttonGO = DefaultControls.CreateButton(TempResource);
            buttonGO.AddComponent<LayoutElement>();
            Button dirButton = buttonGO.GetComponent<Button>();
            dirButton.onClick.AddListener(() => { OnClickMaterialChooserDir(dir.Name); }); //AddListener(delegate { OnClickMaterialChooserDir(i); });
            Text text = dirButton.transform.GetChild(0).GetComponent<Text>();
            text.text = dir.Name;
            text.fontStyle = FontStyle.Bold;
            text.fontSize = 16;

            dirButton.transform.SetParent(_MaterialChooserScrollViewContent, false);
        }
    }

@steveh2112

I didn’t read your code properly but:

// AddListener(delegate { OnClickMaterialChooserDir(i);

If you want to use this, that “i” must be a local variable in that loop for it to work… it is called C# closure I think.