0

I have a winform C# app, in which i have a issues. First here is a image of my form.(it is not final yet. So alignment is not set properly.) Image.

here is my problem. there are 36 textboxes (enclosed within the red area.) They will hold max 12 values but not sequentially i.e one after the other. Now in the Blue Area is How i want the 12 values which will be filled in the red area.

I've searched thoroughly, but could not find anything concrete. i wrote a code that will first check if the textbox is free or not, if free copy the textbox value from red area to the blue(in a broad way.), under the switch button event. it only copies the last few textboxes from here to there.

that there are 36 textboxs in red area and only 12 in the blue, i have no idea how to go about further.

Any and all help is appreciated.

REZR.AMX
  • 59
  • 5
  • 20

2 Answers2

1

There at least two ways to achieve that result.

1) You can group your text boxes using panels, one panel for text boxes filled by user and another one for text boxes with copied values. First get values from first group:

private static IEnumerable<string> GetValues(Panel container)
{
    return container.Controls
        .OfType<TextBox>()
        .Select(x => x.Text)
        .Where(x => !String.IsNullOrWhiteSpace(x));
}

Now you have an enumeration with strings from first group, let's put them in target controls:

private static void FillWith(Panel container, IEnumerable<string> values)
{
    Queue<string> queue = new Queue<string>(values);
    foreach (var textbox in container.Controls.OfType<TextBox>())
    {
        // Not enough values to fill all textboxes
        if (queue.Count == 0)
            return;

        textbox.Text = queue.Dequeue();
    }
}

Used like this:

FillWith(pnlTarget, GetValues(pnlInputs));

2) Use some convention for names (for example name all textboxes with user inputs as txtInputXYZ, where XYZ is an incrementing number, and all outputs with txtOutputXYZ). Just loop thorugh them like this:

for (int inputIndex = 0, outputIndex = 0; inputIndex < numberOfInputs; ++inputIndex)
{
    string value = ((TextBox)Controls[String.Format("txtInput{0}", inputIndex)]).Text;
    if (String.IsNullOrWhiteSpace(value))
        continue;

    var target = (TextBox)Controls[String.Format("txtOutput{0}", outputIndex++)];
    if (target == null)
        break; // No more targets

    target.Text = value;
}

If you don't know number of input and output textboxes (because they're dynamically added) or simply because you don't want to hard-code that (good) then:

for (int inputIndex = 0, outputIndex = 0; ; ++inputIndex)
{
    var source = Controls[String.Format("txtInput{0}", inputIndex)];
    if (source == null)
        break; // No more sources

    string value = ((TextBox)source).Text;
    if (String.IsNullOrWhiteSpace(value))
        continue;

    var target = (TextBox)Controls[String.Format("txtOutput{0}", outputIndex++)];
    if (target == null)
        break; // No more targets

    target.Text = value;
}

Both methods can be used as idea, you don't actually need to use LINQ (in case you're running on older .NET version, for example). In first method you can also skip Queue (but it's such micro-optimization...) and you may manually iterate through the enumeration (returning when end is reached). Moreover second method isn't tied to names, you can decorate them somehow (an object in the Tag property?) to understand who is who then names can be anything you want.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • even using the second method you wrote, it still does not copy the data to "Blue Area." i had a group box around it, removed now, still no output – REZR.AMX Apr 27 '14 at 18:59
  • also while in your second method, if i put a breakpoint on each of the three declarations, as soon as the first breakpoint is reached, the control is returned. meaning, the loop does not go forward. – REZR.AMX Apr 27 '14 at 19:06
  • @REZR.AMX I can't post designer code (then you have to put it in your context according to your visual tree) anyway: 1st) keep group box, just replace `Panel` with `GroupBox` in that functions (parameter must be the **direct** container of that input boxes. 2) Very first line inside the loop: you have to replace `Controls` with proper container! If they're inside a `GroupBox `(let's say `grpFirst`) you can't use `Controls `(equals to `this.Controls`) but `grpFirst.Controls`. Also you may consider to replace `Controls["..."]` with `Find("...", true)` that will search through all visual tree. – Adriano Repetti Apr 27 '14 at 21:06
0

You can use LINQ to get your textboxes.

First you need to give names to your Textboxes then identify them and distinguish between red area and blue area using their name.

For example, the name of the textboxes in red area could start with Red, blue are start with Blue.(this is horrible of course, I'm saying for example, you don't do that give more meaningful names to your textboxes).

After you do that here is the solution:

var values = this.Controls
            .OfType<TextBox>()
            .Where(x => x.Name.StartsWith("Red") && x.Text != string.Empty)
            .Select(x => x.Text)
            .ToList();

int i = 0;
foreach (var txtBox in this.Controls.OfType<TextBox>()
            .Where(x => x.Name.StartsWith("Blue")))
{
    txtBox.Text = values[i++];
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • No output from this code, did exactly as you said, still the data is not arranged to the "blue area.." is there any thing besides this that i have to do? – REZR.AMX Apr 27 '14 at 18:48
  • the "blue area" controls were enclosed withing a group box. i took them out of it, but still it doesnot work. – REZR.AMX Apr 27 '14 at 18:57