0

In pushing forward with my application (winforms) and I have found a need to have dynamically generated content to be pushed to a button that then will display that dynamic content in a messagebox.

What I am doing is reading FTP links from a file, based on a product selection, then I want to take each line and have it append a textbox and a button so that they can fill out the file name.

I have it it working where the Label, textbox and button all appear as i would expect. Now what I want is to have the button when clicked display my content that was just generated.

So the code I have right now that generates everything as expected is as follows. I just need to know how to make the button accept my ftpLabel.Text and tb.Text data. I have tried to follow the post here: How can i create dynamic button click event on dynamic button? However, I cannot seem to make it accept any of my dynamic content.

    private void productComboBox_SelectedItemChanged(object sender, EventArgs e)
    {
        // Read from the text file and out put the results
        try
        {
            using (StreamReader sr = new StreamReader(selectedProduct + ".txt"))
            {
                string line;
                int l = 0;

                // build the ftp link records line by line
                while ((line = sr.ReadLine()) != null)
                {
                    Label ftpLabel = new Label();
                    ftpLabel.AutoSize = true;
                    ftpLabel.Text = line;
                    TextBox tb = new TextBox();
                    Button bt = new Button();
                    bt.Text = "Copy Link";
                    bt.Click += bt.Click;
                    flp.Controls.Add(ftpLabel);
                    flp.Controls.Add(tb);
                    flp.Controls.Add(bt);

                    l++;
                }
                ftpGroupBox.Controls.Add(flp);
            }
        }
        // If the read fails then output the error message in the same section
        catch (Exception ex)
        {
            Label ftpErrorLabel = new Label();
            ftpErrorLabel.AutoSize = true;
            ftpErrorLabel.ForeColor = Color.Red;
            ftpErrorLabel.Text = "Error: " + ex.Message;
            flp.Controls.Add(ftpErrorLabel);
            ftpGroupBox.Controls.Add(flp);
        }
    }

    void bt_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Does this work?");
        // this message displays but cannot pass my dynamicly created content to this
    }

Any Advice is appreciated.

Thanks

Community
  • 1
  • 1
jAC
  • 3,155
  • 3
  • 18
  • 29

1 Answers1

1

You need a hook between the button and the corresponding label and textbox. This is probably not the correct way to do this but the easiest way it to induce a naming convention as a hook.

try
    {
        using (StreamReader sr = new StreamReader(selectedProduct + ".txt"))
        {
            string line;
            int l = 0;

            // build the ftp link records line by line
            while ((line = sr.ReadLine()) != null)
            {
                Label lFTPtextext = new Label()
                 {
                    AutoSize = true,
                    Text = line,
                    Tag = l
                 };


                Button bt = new Button()
                 {
                   Text = "Copy Link",
                   Tag = l
                 }

                 bt.Click += bt.Click;

                TextBox tb = new TextBox()
                {
                   Tag = l
                }

                flp.Controls.Add(lFTPtextext);
                flp.Controls.Add(tb);
                flp.Controls.Add(bt);

                l++;
            }
            ftpGroupBox.Controls.Add(flp);
        }
    }
    // If the read fails then output the error message in the same section
    catch (Exception ex)
    {
        Label ftpErrorLabel = new Label();
        ftpErrorLabel.AutoSize = true;
        ftpErrorLabel.ForeColor = Color.Red;
        ftpErrorLabel.Text = "Error: " + ex.Message;
        flp.Controls.Add(ftpErrorLabel);
        ftpGroupBox.Controls.Add(flp);
    }
}

void bt_Click(object sender, EventArgs e)
    {
        string tagNumber = ((Button)sender).Tag.ToString();

        var tbText= this.Controls.OfType<TextBox>()
                           .Where(x => x.Tag.ToString() == tagNumber)
                           .FirstOrDefault()

        var lblText = this.Controls.OfType<Label>()
                           .Where(x => x.Tag.ToString() == tagNumber)
                           .FirstOrDefault()

        MessageBox.Show(tbText.ToString() + " " + lblText.ToString());
    }

Maybe not the best answer, but its how I would solve it.

DidIReallyWriteThat
  • 1,033
  • 1
  • 10
  • 39
  • I think it may be missing something? I get Error Operator '==' cannot be applied to operands of type 'object' and 'int' – jAC Sep 02 '14 at 17:03
  • hmm... now the select does not appear to like the string values: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'string' Sorry for being such a noob here :( – jAC Sep 02 '14 at 17:29
  • Any thoughts on how to fix that last error anyone? If i convert it to an INT then it says it needs to be a string and if i convert it to a string then it says the above error... Any help would be apprecated – jAC Sep 02 '14 at 23:30
  • 1
    `Select` returns an `IEnumerable`. You can wrap the whole thing in `(...).FirstOrDefault();` or you can rewrite it as `var lblText = this.Controls.OfType – Loathing Sep 03 '14 at 03:55
  • @Loathing Ok so i tried both methods and even though I dont get any errors but I also do not get any results (lblText appears empty). Sorry for being a pain. I do get the tag number each time. When I debug, lblText = null and tagNumber = 0 (which is expected). – jAC Sep 03 '14 at 12:46
  • @CalvinSmith The updated version of your answer throws an error "Object reference not set to an object". It really doesn't like us trying to convert this to a string... :( If i take out the .ToString() off the messagebox variables then it works without error but again does not display the data – jAC Sep 03 '14 at 13:10
  • Where does the error occur? is it on the tbText? It sounds like the query is not returning a result for x => x.Tag.ToString() == tagNumber. Can you confirm that it has the correct data coming in? – DidIReallyWriteThat Sep 03 '14 at 13:12
  • If I change MessageBox.Show(tbText.ToString() + " " + lblText.ToString()); to be MessageBox.Show(tbText + " " + lblText); this. Then I no longer get the error. So my guess is when tell tbText and lblText to cast to a string is when it causes the error. The data comes through as null, so its like its not doing anything... – jAC Sep 03 '14 at 13:15
  • Ok, so with some more troubleshooting, it appears you are right, the data does not seem to be passed. Every time it comes over as null for the lblText or tbText. How can we send the rest of the data outside of the button? – jAC Sep 03 '14 at 14:17
  • @jAC So, the label text on the form is not an empty string? – DidIReallyWriteThat Sep 03 '14 at 14:28
  • @CalvinSmith correct, the string is an ftp link as you can see in this screenshot that there is a value there: http://picpaste.com/ftpLinks-mqmTdvGV.png So it is not a null string. Just not sure why that is not being sent over – jAC Sep 03 '14 at 15:59
  • The `NullReferenceExeption` is occurring because `this.Controls` doesn't contain the `TextBox` and `Label` controls. The `ftpGroupBox` variable does. Thus, change `this.Controls.OfType<...>()...` to `ftpGroupBox.Controls.OfType<...>()` for both LINQ expressions. – Loathing Sep 03 '14 at 17:17
  • @Loathing Thanks for the tip! It still gave me errors then i realized that i was pumping this through a dynamic flowlayoutpanel. I made that a static flp and then referenced that. Once I did that it worked. I want to thank you @ CalvinSmith for your help! (and everyone else that gave advice) – jAC Sep 03 '14 at 20:30