0

So I have a form that gets dynamically generated by a script to have a label and a text box for every string pulled as an argument. I want the user to fill in each text box then select the OK button. Afterwards I want to process each item of each text box. Before when there was only 1 item, I wrote a very simple property to obtain the value of the text box.

Public string Text { get { return textbox1.Text; } }

I was hoping I could do something equally as elegant with a dynamic number of text boxes.

Public string [] Text { get { return **Each text box text as an array**; } }

I've been thinking about it for a while and I can't think of an elegant way to set this up, here is how the text boxes are added to the form...

string[] keywords = Environment.GetCommandLineArgs();
int placement = 10;
foreach (string keyword in keywords)
{
    if (keyword == keywords[0])
        continue;
    Label lbl = new Label();
    lbl.Text = keyword;
    lbl.Top = placement;
    this.Controls.Add(lbl);
    TextBox txt = new TextBox();
    txt.Top = placement;
    txt.Left = 100;
    this.Controls.Add(txt);

    placement += 20;
}

I could loop through each text box's text upon the form closing and populate the public array with the values, but I would rather come up with something a little more elegant and get out of the habit of doing things by force. Anybody have any cool ideas of how to accomplish this? I'm thinking I could add all the text boxes to an array and then have the string property somehow grab the text of the text box specified, or just make the text box array the public property instead. Is there a way to write something like this...

Public string [] Text { get { return TextBoxArray[**value trying to be gotten**].Text; } }

or is this to much for a property and needs to be a method instead? Any other ideas anybody has? I realize it's a bit of a trivial question and could be solved in any number of ways, I'm just looking to broaden my horizons on cool ways to accomplish something like this.

3 Answers 3

3

Other options might be better, but this is likely the most direct and concise: (uses LINQ, add using System.Linq;, requires .NET 3.5 or higher)

public string[] Text { get { return Controls.OfType<TextBox>().Select(x => x.Text).ToArray(); } }

This is very similar to AlejoBrz's solution, but uses LINQ to be more clear and concise.

Sign up to request clarification or add additional context in comments.

3 Comments

I like this answer the best, very concise and accomplishes exactly what I want with 1 line. Thanks!
@KDiTraglia I like it the best too!
Ah I assumed that you had an argument name/value thing going on but it looks like that's not the case :)
1

Here's an idea:

Public System.Collections.Generic.List<string> Text { 
    get {
        System.Collections.Generic.List<string> returnValue = new string[textBoxCount];
        foreach (Control ctrl in this.Controls)
            if (ctrl.GetType() == typeof(TextBox))
                returnValue.Add(((TextBox)ctrl).Text);
        return returnValue;
   }
}

sure, it goes through all your controls, but at least you don't have to keep them in memory in some kind of variable such as System.Collections.Generic.List. Or you could do that and on this foreach remove the if.

Comments

1

Technically a property is just syntactic sugar for a getter/setter method - so a property can do anythign a method can do (but most of the time it SHOULDNT!)

I'd just add all textboxes to a Dictionary object assuming your command line args can't be duplicated.

Basically on startup:

Create a:

Dictionary<string, TextBox> boxes;

Add the textboxes in your startup code using the command parameter as the key

boxes.Add(commandName, newTextBox);

Then in your getter you can access the dictionary using

boxes[commandName]

which will return the textbox that you can manipulate. This is all strongly typed of course :)

Here's some example code:

string[] keywords = Environment.GetCommandLineArgs(); 
Dictionary<string, TextBox> boxes = new Dictionary<string, TextBox>();
int placement = 10; 

foreach (string keyword in keywords) 
{ 
    if (keyword == keywords[0]) 
        continue; 
    Label lbl = new Label(); 
    lbl.Text = keyword; 
    lbl.Top = placement; 
    this.Controls.Add(lbl); 
    TextBox txt = new TextBox(); 
    txt.Top = placement; 
    txt.Left = 100; 
    this.Controls.Add(txt); 
    placement += 20; 
    boxes.Add(keyword, txt);
} 

Then I suppose you don't need a getter - just make the boxes dictionary visible

public Dictionary<string, TextBox> Boxes { get { return boxes; } }

And if you aren't interested in the textboxes and just want the values:

public Dictionary<string, string> Arguments 
{
  get 
  {
     Dictionary<string, string> vals = new Dictionary<string, string>();

     foreach(KeyValuePair<string, TextBox> kvp in boxes) 
     {
       vals.Add(kvp.Key, kvp.Value.Text);
     }

     return vals;
   }
}

1 Comment

Also check out 'indexed' properties in c# - this is the way the dictionary class allows you to use any templated type for the key (and look up using array syntax to get the value) msdn.microsoft.com/en-us/library/aa288464(v=vs.71).aspx

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.