Data in Array from N Textboes using For loop - c#

There are "N" number of Textboxes on a Form,
I want to get the values in the textboxes in an Array.
using "For" loop,
Can any help me out with this.

You can get all the controls on a form by calling this.Controls and loop through those comparing the control to a TextBox, when it is a TextBox you add the value to the array you are mentioning.
I'd use something like this:
List<string> values = new List<string>();
foreach(Control c in this.Controls)
{
if(c is TextBox)
{
/*I didnt need to cast in my intellisense, but just in case!*/
TextBox tb = (TextBox)c;
values.Add(tb.Text);
}
}
string[] array = values.ToArray();

Related

How to access a group of Text Boxes based on the Index Id in their Name

I have 16 text boxes in my Form whose names are suffixed sequentially from 1 to 16 respectively.
i.e. The 16 test boxes are names TextBox1, 'TextBox2, .... all the way until the 16th one, which is namedTextBox16`.
I would like to read the contents of these 16 text boxes in a loop and modify the ith TextBox's contents or properties based on a certain condition.
How do I do this?
If you use WinForms, easiest way is to store text boxes references in array, in constructor of window:
TextBox[] data = new TextBox[16]{textBox1,textBox2, [...],textBox16};
then you can use for loop to access them.
You can try something like this:
Dictionary<string, string> yourValues = new Dictionary<string, string>();
foreach (Control x in this.Controls)
{
if (x is TextBox)
{
yourValues.Add(((TextBox)x).Name, ((TextBox)x).Text);
}
}
NOTE: On your future question please provide more information and make your question more clear.
i would try to find and modify using Linq:
using System.Linq;
//...
int x = 5; //number of textbox to search
var textbox = this.Controls.OfType<TextBox>().Single(tb => tb.Name.EndsWith(x.ToString()));
textbox.Text = "abc";
In case you have to loop thru all the texboxes in form, you can do something like this:
List<TextBox> textboxes = this.Controls.OfType<TextBox>().ToList();
foreach (TextBox box in textboxes)
{
box.Text = "something";
}
Easiest way according to what you specified is to use Linq.
Let's assume you have 3 TextBoxes :
// 1st -> which is named meTextBox1
// 2nd -> which is named meTextBox2
// 3rd -> which is named meTextBox3
As you can see from above every line differs only by the number ( index .. call it whatever you want ).
Now you can make your base "query" which would look like :
const string TB_NAME = "meTextBox{0}";
And as you can presume right now this will be used inside of string.Format method. Now to retrieve desired TextBox all you have to do is to make Linq statement :
string boxName = string.Format(TB_NAME, 7); // retrieve 7th text box
TextBox tBox = Controls.OfType<TextBox>().FirstOrDefault(tb => tb.Name == boxName);
This example does not consider nested Controls but you can make do this recursively which will retrieve nested Controls:
TextBox ByIndex(int idx, Control parent)
{
TextBox result = null;
string searchFor = string.Format(TB_NAME, idx);
foreach(Control ctrl in parent.Controls)
{
if(!(ctrl is TextBox) && ctrl.HasChildren)
{
result = ByIndex(idx, ctrl);
if( result != null)
break;
}
else if(ctrl is TextBox)
{
if(ctrl.Name = searchFor)
{
result = ctrl as TextBox;
break;
}
}
}
return result;
}
To use above method you can just call it like such :
public class MeForm : Form
{
//.. your code here ..
void meImaginaryMethodToRetrieveTextBox()
{
int meRandomIndex = 7;
TextBox tb = ByIndex(meRandomIndex, this);
// rest of the code...
}
}

Find a specific dynamic TextBox in a C# WPF GroupBox

I have added a GroupBox to my main Grid and am populating it dynamically with controls. I need to get a specific textbox within that GroupBox in an onClick event. I am able to loop through the GroupBox and fine, like this...
foreach (Control ctl in ((Grid)gpMccEngineProperties.Content).Children)
{
if (ctl.GetType() == typeof(TextBox))
{
TextBox textbox = (TextBox)ctl;
PropertyValue propertyValue = new PropertyValue();
propertyValue.Value = textbox.Text;
}
}
... but if i just want to access a specific TextBox i keep coming back with a null value. here is how i'm trying to get it...
TextBox txt = ((Grid)gpMccEngineProperties.Content).Children.OfType<TextBox>().Where(t => t.Name == "PropertyId_9") as TextBox;
... where PropertyId_9 is the name of a textbox that i added dynamically to the GroupBox. Any idea how i get that textbox so i can get it's value?
Thanks!
You're using the wrong Linq method. That code returns an IEnumerable of TextBoxes, not just the TextBox. Use Single or SingleOrDefault instead of Where:
TextBox txt = ((Grid)gpMccEngineProperties.Content).Children.OfType<TextBox>().Single(t => t.Name == "PropertyId_9");

How can I read ListView Column Headers and their values?

I've been trying to find out a way to read data from the selected ListView row and display each value in their respected TextBox for easy editing.
The first and easiest way would be something like this:
ListViewItem item = listView1.SelectedItems[0];
buyCount_txtBox.Text = item.SubItems[1].Text;
buyPrice_txtBox.Text = item.SubItems[2].Text;
sellPrice_txtBox.Text = item.SubItems[3].Text;
There is nothing wrong with that code but I have around 40 or more TextBoxes that should display data. Coding all 40 or so would become very tedious.
The solution I've come up with, is to get all TextBox Controls in my User Control like so:
foreach (Control c in this.Controls)
{
foreach (Control childc in c.Controls)
{
if (childc is TextBox)
{
}
}
}
Then I need to loop the selected ListView row column headers. If their column header matches TextBox.Tag then display the column value in their respected TextBox.
The final code would look something like this:
foreach (Control c in this.Controls)
{
foreach (Control childc in c.Controls)
{
// Needs another loop for the selected ListView Row
if (childc is TextBox && ColumnHeader == childc.Tag)
{
// Display Values
}
}
}
So then my question would be: How can I loop through the selected ListView Row and each column header.
Looping over your ColumnHeaders is simply done like this:
foreach( ColumnHeader lvch in listView1.Columns)
{
if (lvch.Text == textBox.Tag) ; // either check on the header text..
if (lvch.Name == textBox.Tag) ; // or on its Name..
if (lvch.Tag == textBox.Tag) ; // or even on its Tag
}
However the way you loop over your TextBoxes is not exactly nice even if it works. I suggest that you add each of the participating TextBoxes into a List<TextBox>. Yes, that means to add 40 items, but you can use AddRange maybe like this:
To fill a list myBoxes:
List<TextBox> myBoxes = new List<TextBox>()
public Form1()
{
InitializeComponent();
//..
myBoxes.AddRange(new[] {textBox1, textBox2, textBox3});
}
Or, if you really want to avoid the AddRangeand also stay dynamic, you can also write a tiny recursion..:
private void CollectTBs(Control ctl, List<TextBox> myBoxes)
{
if (ctl is TextBox) myBoxes.Add(ctl as TextBox);
foreach (Control c in ctl.Controls) CollectTBs(c, myBoxes);
}
Now your final loop is slim and fast:
foreach( ColumnHeader lvch in listView1.Columns)
{
foreach (TextBox textBox in myBoxes)
if (lvch.Tag == textBox.Tag) // pick you comparison!
textBox.Text = lvch.Text;
}
Update: since you actually want the SubItem values the solution could look like this:
ListViewItem lvi = listView1.SelectedItems[0];
foreach (ListViewItem.ListViewSubItem lvsu in lvi.SubItems)
foreach (TextBox textBox in myBoxes)
if (lvsu.Tag == textBox.Tag) textBox.Text = lvsu.Text;
Try this one for greeting all the values.
foreach (ListViewItem lvi in listView.Items)
{
SaveFile.WriteLine(lvi.Text + "_" + lvi.SubItems[1].Text);
}

how to define an array of textboxes in c#?

Hi when I create textboxes on Windows Application Form I cannot name it as box[0], box[1] and so on. The purpose why I want to do like this is because I want to use them in a loop.
Actually I found TextBox[] array = { firstTextBox, secondTextBox }; works too!
How about making a list of them after you create them? In your form initialization function, you can do something like:
List<TextBox> myTextboxList = new List<TextBox>();
myTextBoxList.Add(TextBox1);
myTextBoxList.Add(TextBox2);
mytextBoxList.Add(TextBox3);
Now you can itterate through with your "myTextboxList" with something like below:
Foreach (TextBox singleItem in myTextboxList) {
// Do something to your textboxes here, for example:
singleItem.Text = "Type in Entry Here";
}
You can create textboxes on runtime and just put them in an array...
If you want to do it in design time, you will have to do some control filtering logic on the whole this.Controls array in order to access only the wanted textboxes. Consider if (currControl is TextBox) if all textboxes in the form are ones you want in the array.
Another option for design time, is putting all wanted textboxes in a panel which will be their parent, and then iterating over the panel's children (controls) and cast them to TextBox.
A runtime solution would be something like:
var arr = new TextBox[10];
for (var i = 0; i < 10; i++)
{
var tbox = new TextBox();
// tbox.Text = i.ToString();
// Other properties sets for tbox
this.Controls.Add(tbox);
arr[i] = tbox;
}
I wouldn't use an array for this, personally. I would use some form of generic collection, like List.
List<TextBox> textBoxList = new List<TextBox>();
//Example insert method
public void InsertTextBox(TextBox tb)
{
textBoxList.Add(tb);
}
//Example contains method
public bool CheckIfTextBoxExists(TextBox tb)
{
if (textBoxList.Contains(tb))
return true;
else
return false;
}
You don't necessarily have to use the Contains method, you could also use Any(), or maybe even find another way- all depends on what you're doing. I just think using a generic collection gives you more flexibility than a simple array in this case.
for C# just use this to create an array of text boxes
public Text [] "YourName" = new Text ["how long you want the array"];
then add the text boxes to the array individually.
TextBox Array using C#
// Declaring array of TextBox
private System.Windows.Forms.TextBox[] txtArray;
private void AddControls(int cNumber)
{
// assign number of controls
txtArray = new System.Windows.Forms.TextBox[cNumber + 1];
for (int i = 0; i < cNumber + 1; i++)
{
// Initialize one variable
txtArray[i] = new System.Windows.Forms.TextBox();
}
}
TextBox[] t = new TextBox[10];
for(int i=0;i<required;i++)
{
t[i]=new TextBox();
this.Controls.Add(t[]);
}

How can I programmatically construct the object reference?

Lets just say that I have three textboxes: TextBox1, TextBox2, TextBox3. Normally if I wanted to change the text for example I would put TextBox1.Text = "Whatever" and so on. For what I'm doing right now I would like to something like (TextBox & "i").Text. That obviously isn't the syntax I need to use I'm just using it as an example for what I need to do. So how can I do something like this? The main reason I'm doing this is to reduce code with a loop.
Please keep in mind that I'm not actually changing the text of the textboxes I'm simply using that as an example to get the point across.
Use an array to access the TextBox objects by index:
TextBox[] textBoxes = new TextBox[3];
textBoxes[0] = textBox1;
textBoxes[1] = textBox2;
textBoxes[2] = textBox3;
for (int i = 0; i < 3; i++)
{
textBoxes[i].Text = "Whatever";
}
this.Controls.OfType<TextBox>().First(r => r.ID == "textbox1").Text = "whatever";
if you know of course, that textbox with id 'textbox1' exists
or
foreach (var tb in this.Controls.OfType<TextBox>()) {
tb.Text ="whatever";
}
When you create your TextBox dynamically you can use an array of TextBoxes which is much easier.
However it is possible to use reflection, too:
var textBoxes = GetType().GetFields( BindingFlags.NonPublic | BindingFlags.Instance )
foreach( var fieldInfo in textBoxes )
{
if( fieldInfo.FieldType == typeof( TextBox ) )
{
var textBox = ( TextBox )fieldInfo.GetValue( this );
textBox.Text = "";
}
}
I would recommend not doing this in general. Often, it's best to put your object references into a collection, and then work on the collection - or to use some other approach along those lines.
However, it is possible to do this (though it's slow) via Reflection:
var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic).Where(f => f.Name.StartsWith("TextBox"));
foreach(var field in fields)
{
TextBox box = field.GetValue(this) as TextBox;
if (box != null)
box.Text = "Whatever";
}
As the goal is to reduce code size, no, you can't do that. Near to what you are trying to achieve would be:
to save the controls in a List or Array
loop the List or Array
List<TextBox> myTxts = new List<TextBox> {textBox1, textBox2, textBox3};
foreach(TextBox txt in myTxts) {
txt.Text = "";
}
Another approach would be to poll the Controls Collection of the Form
foreach(Control ctl in this.Controls) {
var txt = ctl as TextBox;
if (txt != null) {
txt.Text = "";
}
}

Categories