Get text from dynamically created WinForms textbox - c#

I'm making a windowsform with dynamically created textboxes as u see in the method.
public void createPassengerBoxes(int numPassenger)
{
TextBox[] passengerBoxes = new TextBox[numPassenger];
for (int u = 0; u < passengerBoxes.Count(); u++)
{
passengerBoxes[u] = new TextBox();
}
int i = 0;
foreach (TextBox txt in passengerBoxes)
{
string name = "passenger" + i.ToString();
txt.Name = name;
txt.Text = name;
txt.Location = new Point(244, 32 + (i * 28));
txt.Visible = true;
this.Controls.Add(txt);
i++;
}
}
}
How do I access the text from the boxes?

While I'm not sure at what point, or based on what action, you'd like to fetch the data, here's very generic method:
private String[] GetTextBoxStrings()
{
List<String> list = new List<String>();
foreach (Control c in this.Controls)
{
if (c is TextBox)
list.Add(((TextBox)c).Text);
}
return list.ToArray();
}

Move your textbox declaration outside of the function. This makes it accessible from other functions within the class:
class MyFormsClass
{
// declare textboxes at class level
TextBox[] passengerBoxes;
public void createPassengerBoxes(int numPassenger)
{
passengerBoxes = new TextBox[numPassenger];
...
}
public void OnButtonClick(...)
{
if (passengernBoxes != null)
{
foreach (TextBox txt in passengerBoxes)
{
// do something with textboxes
}
}
}
...
}

You could also use Lambda:
var strings = Controls.OfType<TextBox>()
.Select(c => c.Text)
.ToList();
this only work if ou have no nested controls - e.g. a pannel or a group that holds some textBoxes

Related

WinForms - Dynamically create textbox based on ComboBox selection

I am trying to create a TextBox based on the selection on ComboBox dynamically based on the following steps:
First step (Select a source from ComboBox):
Second step (Textbox should appear based on ComboBox.SelectedValue):
Last step (A new ComboBox should appear below):
I have created a createTextBox function using the following code:
public void createTextBox(int numPassenger)
{
TextBox[] passengerBoxes = new TextBox[numPassenger];
for (int u = 0; u < passengerBoxes.Count(); u++)
{
passengerBoxes[u] = new TextBox();
}
int i = 0;
foreach (TextBox txt in passengerBoxes)
{
string name = "passenger" + i.ToString();
txt.Name = name;
txt.Text = name;
txt.Location = new Point(244, 32 + (i * 28));
txt.Visible = true;
this.Controls.Add(txt);
i++;
}
}
Is there a way that I can modify my current function to adapt to the mentioned steps? Additionally, how can I find the dynamically created TextBox?
You can try the following code:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
createTextBox(sender as ComboBox);
}
private void createTextBox(ComboBox cmb)
{
TextBox passengerBoxes = new TextBox();
string name = cmb.Text;
if (Controls.Find(name, true).Length == 0)
{
passengerBoxes.Name = name;
passengerBoxes.Text = name;
int textBoxCount = GetTextBoxCount();
passengerBoxes.Location = new Point(244, 32 + (textBoxCount * 28));
passengerBoxes.Visible = true;
this.Controls.Add(passengerBoxes);
if (cmb.Items.Count != 1)//last item remaining then we should not create new combo box
{
ComboBox newCombo = new ComboBox
{
Location = new Point(cmb.Location.X, 32 + ((textBoxCount + 1) * 28))
};
foreach (string str in cmb.Items)
if (cmb.Text != str)
newCombo.Items.Add(str);
newCombo.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
this.Controls.Add(newCombo);
}
}
else
MessageBox.Show("Textbox Already for the selected source " + name);
}
private int GetTextBoxCount()
{
int i = 0;
foreach (Control ctl in this.Controls)
{
if (ctl is TextBox) i++;
}
return i;
}

How to make if statement for multiple elements? C#

I am using VS2017 and C# on Windows Forms.
I'm creating a little tool and I need some assistance.
I have 10 text boxes, names textGame1, textGame2, textGame3, etc etc
I want to create code, in which if the any of the text boxes are empty, then it will replace the textbox text to "EMPTY".
I could easily do
if (string.IsNullOrWhiteSpace(textGame1.Text))
{
textGame1.Text = "EMPTY";
}
However I would have to create 10 of those for each text box.
Is there a simpler way, than to create 10 of these IF statements?
First, create a collection to store each text box you want to manipulate. You can do this by hand:
var textBoxes = new[] { textGame1, textGame2, textGame3, ... };
Or using the Controls collection (a little Linq can help):
var textBoxes = Enumerable.Range(1, 10).Select(i => (TextBox)Controls[$"textGame{i}"]);
Or if you need to search all children recursively, use the Find method:
var textBoxes = Enumerable.Range(1, 10).Select(i => (TextBox)(Controls.Find($"textGame{i}", true)[0]));
Now, simply use a foreach:
foreach(var tb in textBoxes)
{
if (string.IsNullOrWhiteSpace(tb.Text))
{
tb.Text = "EMPTY";
}
}
You can use generic code:
const string baseName = "textBox";
var names = Enumerable.Range(1, 10).Select(x => baseName + x.ToString()).ToList();
var tbxs = names.Select(name => this.Controls.Find(name, true).FirstOrDefault()).Where(x=> x != null).ToList();
foreach (var txt in tbxs) {
if (string.IsNullOrWhiteSpace(txt.Text))
{
txt.Text = "EMPTY";
}
}
You can create your "own" textbox with a placeholder feature:
public class PlaceHolderTextBox : TextBox
{
bool isPlaceHolder = true;
string _placeHolderText;
public string PlaceHolderText {
get { return _placeHolderText; }
set {
_placeHolderText = value;
setPlaceholder();
}
}
//when the control loses focus, the placeholder is shown
private void setPlaceholder()
{
if (string.IsNullOrEmpty(this.Text)) {
this.Text = PlaceHolderText;
this.ForeColor = Color.Gray;
this.Font = new Font(this.Font, FontStyle.Italic);
isPlaceHolder = true;
}
}
//when the control is focused, the placeholder is removed
private void removePlaceHolder()
{
if (isPlaceHolder) {
this.Text = "";
this.ForeColor = System.Drawing.SystemColors.WindowText;
this.Font = new Font(this.Font, FontStyle.Regular);
isPlaceHolder = false;
}
}
public PlaceHolderTextBox()
{
GotFocus += removePlaceHolder;
LostFocus += setPlaceholder;
}
}
Credit for code: https://gntheprogrammer.blogspot.com/2015/03/how-to-add-placeholder-in-windows-forms.html
I just converted it from VB ;)

how to save data from dynamic textbox?

this code creates a textbox dynamically based on the total number of items in a listview. my problem is how can i access these textboxes so i can save the contents of the textbox to my database?
int f = 24;
int j = 25;
for (int gg = 0; gg < listView1.Items.Count;gg++ )
{
j = f + j;
TextBox txtb = new TextBox();
txtb.Name = "tboxl1"+gg;
txtb.Location = new Point(330,j);
txtb.Visible = true;
txtb.Enabled = true;
txtb.Font = new Font(txtb.Font.FontFamily,12);
groupBox2.Controls.Add(txtb);
}
I'd be more inclined to write you code like this:
var f = 24;
var j = 25;
var textBoxes =
Enumerable
.Range(0, listView1.Items.Count)
.Select(gg =>
{
j = f + j;
var txtb = new TextBox();
txtb.Name = String.Format("tboxl1{0}", gg);
txtb.Location = new Point(330, j);
txtb.Visible = true;
txtb.Enabled = true;
txtb.Font = new Font(txtb.Font.FontFamily, 12);
return txtb;
})
.ToList();
textBoxes.ForEach(txtb => groupBox2.Controls.Add(txtb));
Now you have a variable textBoxes that saves references to the new text boxes. You can use that to get the values from the text boxes to save them to your database.
If you want all TextBox controls then:
foreach (Control control in groupBox2.Controls)
{
if (control is TextBox)
{
string value = (control as TextBox).Text;
// Save your value here...
}
}
But if you want a specific TextBox, you can get it by its name like this:
Control control = groupBox1.Controls.Find("textBox1", false).FirstOrDefault(); // returns null if no control with this name exists
TextBox textBoxControl = control as TextBox; // if you want TextBox control
string value = control.Text;
// Now you can save your value anywhere
You can get the reference to text box as follows,
Control GetControlByName(string Name)
{
foreach(Control c in this.Controls)
if(c.Name == Name)
return c;
return null;
}

How to access multiple buttons or textbox or any control?

I want to access multiple textbox name textbox1,textbox2,textbox3, etc.. by loop not by individual name. For that reason I created one function which create this var names.
public string[] nameCre(string cntrlName, int size)
{
string[] t = new string[size];
for (int i = 0; i < size; i++)
{
t[i] = cntrlName.ToString() + (i + 1);
}
return t;
}
for nameCre("Textbox",5); So this,function successfully returning me TextBox1, TextBox2 ... TextBox5.
But when I am trying to convert this string to TextBox control by
string[] t = new string[50];
t= nameCre("TextBox",5);
foreach (string s in t)
{
((TextBox) s).Text = "";
}
it giving me error :
Cannot convert type 'string' to 'System.Windows.Forms.TextBox'....
How can I accomplish this job?
var t = nameCre("TextBox",5);
foreach (var s in t)
{
var textBox = new TextBox {Name = s, Text = ""};
}
string[] t= new string[50];
t= nameCre("TextBox",5);
foreach (string s in t){
TextBox tb = (TextBox)this.Controls.FindControl(s);
tb.Text = "";
}
if you have many text boxes
foreach (Control c in this.Controls)
{
if (c.GetType().ToString() == "System.Windows.Form.Textbox")
{
c.Text = "";
}
}
Perhaps you need this -
string[] t = new string[50];
t = nameCre("TextBox", 5);
foreach (string s in t)
{
if (!string.IsNullOrEmpty(s))
{
Control ctrl = this.Controls.Find(s, true).FirstOrDefault();
if (ctrl != null && ctrl is TextBox)
{
TextBox tb = ctrl as TextBox;
tb.Text = "";
}
}
}
This post is quite old, anyway I think I can give you (or anyone else with a problem like that) an answer:
I think using an Array (or List) of TextBoxs would be the best solution for doing that:
// using an Array:
TextBox[] textBox = new TextBox[5];
textBox[0] = new TextBox() { Location = new Point(), /* etc */};
// or
textBox[0] = TextBox0; // if you already have a TextBox named TextBox0
// loop it:
for (int i = 0; i < textBox.Length; i++)
{
textBox[i].Text = "";
}
// using a List: (you need to reference System.Collections.Generic)
List<TextBox> textBox = new List<TextBox>();
textBox.Add(new TextBox() { Name = "", /* etc */});
// or
textBox.Add(TextBox0); // if you already have a TextBox named TextBox0
// loop it:
for (int i = 0; i < textBox.Count; i++)
{
textBox[i].Text = "";
}
I hope this helps :)

dynamically call a control

Let's say I have 30 controls, all lbls, all called "lblA" with a number after.
I also have 30 textboxes, same thing - called "txtB" with a number after.
How exactly would I formated this.
for (i = 1; i < this.controls.count;i++)
{
if ("lblA"+i=null)
{
break;
}
string A = string A + ("lblA" + i).Text
string B = string B + ("txtB" + i).Text
}
I've tried a few different things like calling the object with this.controls[i] but it's not exactly what I want. What I am doing is I have a lot of labels and text boxes in a form that are added at run time. I need to loop through the form to get them all. I'm writting it as a for each with quite a few ifs, but I'm curious if there's a dynamic way to do it.
I've looked for about 1-1:30 hours online and found nothing close to, thanks for the help all.
var labels = new Dictionary<int, string>();
for (i = 1; i < this.controls.count;i++)
{
var label = FindControl("lblA" + i) as Label;
if (label == null)
{
break;
}
labels.Add(i, label.Text);
}
What you want to use is the FindControl method.
Example in VB:
Dim txtMileage As TextBox = CType(cphLeft.FindControl("txtMileage" & iControlCountDays.ToString()), TextBox)
Maybe this will solve what you're after:
void GetSpecialControls() {
const string TXT_B = "txtB";
const string LBL_A = "lblA";
List<TextBox> textBoxList = new List<TextBox>();
List<Label> labelList = new List<Label>();
foreach (Control ctrl in this.Controls) {
Label lbl = ctrl as Label;
if (lbl != null) {
if (lbl.Text.IndexOf(LBL_A) == 0) {
labelList.Add(lbl);
}
} else {
TextBox txt = ctrl as TextBox;
if (txt != null) {
if (txt.Text.IndexOf(TXT_B) == 0) {
textBoxList.Add(txt);
}
}
}
}
Console.WriteLine("Found {0} TextBox Controls.", textBoxList.Count);
Console.WriteLine("Found {0} Label Controls.", labelList.Count);
}

Categories