Text from textboxes to list - c#

I'm REALLY new to C# and programming overall, so my question might be stupid in your opinion but here it is.
I have created a form which contains 7 textboxes and i want to collect text from these textboxes and add them to a list. I however get an error saying, System.Windows.Forms.TextBox is a 'type' but is used like a 'variable". What should I do?
for (int i = 1; i < 8; i++)
{
if (TextBox[i].Text == "")
{
days.Add("Restday");
}
else
{
days.Add(TextBox[i].Text);
}
}

TextBox is a type. so TextBox[i] is causing you trouble.
You can alway do something like this
foreach(Control ctrl in yourform.Controls)
{
Textbox = ctrl as TextBox;
if(txtBox != null)
{
if (txtBox.Text == "")
{
days.Add("Restday");
}
else
{
days.Add(txtBox.Text);
}
}
}
This work for a basic form. If you have pannel and other container to organize your controls the approch described in Guffa answer might be better. This could also be rewritten as method who accept a collection of Control recursive use to reach all controls.

Put the textbox references in an array so that you can easily loop through them. If your textboxes are named TextBox1 to TextBox7:
TextBox[] boxes = {
TextBox1, TextBox2, TextBox3, TextBox4, TextBox5, TextBox6, TextBox7
};
foreach (TextBox box in boxes) {
if (box.Text == "") {
days.Add("Restday");
} else {
days.Add(box.Text);
}
}

I guess you don't have an array named TextBox that is why the error. You can try following:
List<strig> days = this.Controls.OfType<TextBox>
.Select(r=> string.IsNullOrWhiteSpace(r.Text)
? "Restday" : r.Text)
.ToList();
But the above would give you the textboxes added on the form directly, If these textboxes are inside other control then you can look for recursively

Go into the form editor and select one of your textboxes. Now find the properties window. If it's not visible then click View->Properties Window
One of the properties in there will be the name of the textbox control. Use that to access it's text value like so:
days.Add(txtMyTextboxName.Text);
If you must iterate through the textboxes you can do this:
foreach(var Textbox in this.Controls.OfType<TextBox>())
{
if (Textbox.Text == "")
{
days.Add("Restday");
}
else
{
days.Add(Textbox.Text);
}
}
But bear in mind this is a pretty non-standard approach and not recommended.

Related

If else statement textbox error

I am trying to create an if else statement to show a message box if no input.
If(textbox1.text==false)
{
messagebox.show("please fill in the boxes")
}
I have 16 different text box currently out, do i need to use an if else statement for each?
Pass all TextBoxes in the list and loop it
//Create list once in the constructor of main form or window
List<TextBox> list = new List<TextBox>()
//...
list.Add(textbox1);
list.Add(textbox2);'
//...
Then loop it
foreach(TextBox txt in list)
{
if(String.IsNullOrWhiteSpace(txt.Text))
{
messagebox.Show("please fill in the boxes");
break;
}
}
Update
If all textboxes expecting only number/double input then use TryParse for checking if value is valid
foreach(TextBox txt in list)
{
Double temp;
if(Double.TryParse(txt.Text, temp) == true)
{
//save or use valid value
Debug.Print(temp.ToString());
}
else
{
messagebox.Show("please fill in the boxes");
break;
}
}
You can not compare string with Boolean. textbox.text is a string data type.
try this, if you want to show different message for different textbox, you must use if-else statement for all texboxes.
If(textbox1.text=="")
{
messagebox.show("please fill in the boxes")
}
or
If(string.IsNullOrEmpty(textbox1.text) == true)
{
messagebox.show("please fill in the boxes")
}
for multiple textbox validation
Adding the handler to the textboxes is easily done with a foreach loop in the form constructor:
foreach(TextBox tb in this.Controls.OfType<TextBox>().Where(x => x.CausesValidation == true))
{
tb.Validating += textBox_Validating;
}
use validating event to handle it
private void textBox_Validating(object sender, CancelEventArgs e)
{
TextBox currenttb = (TextBox)sender;
if(currenttb.Text == "")
MessageBox.Show(string.Format("Empty field {0 }",currenttb.Name.Substring(3)));
e.Cancel = true;
else
{
e.Cancel = false;
}
}
String and Boolean aren't comparable, also you can check if all the textfields are empty like described in this post
if(this.Controls.OfType<TextBox>().Any(t => string.IsNullOrEmpty(t.Text)) {
//Textfield is empty
}
First of all, you have a type mismatch error in your question. The Text property of a TextBox is of string type, while the keyword false is of bool type. You can read more on types in here.
The fix to this issue would be:
If (!string.IsNullOrEmpty(textbox1.Text))
{
Messagebox.Show("please fill in the boxes")
}
Secondly, modern programming is all about DRY principle. So, the answer is no, you do not need to write the same piece of code for each of them.
You could actually do it at least two ways.
The first way would be to create some sort of collection of your textboxes (an array, for example). Then you would create a method to iterate over this collection like this:
private bool AllTextboxesAreFilled()
{
var textboxes = new TextBox[] { textBox1, textBox2, textBox3 };
return textboxes.All(textbox => !string.IsNullOrEmpty(textbox.Text));
}
And then call it like:
if (!AllTextboxesAreFilled())
{
MessageBox.Show("please fill in the boxes");
}
The second way would be to make these textboxes children of some control (a Panel, for example) and then iterate over these children. This way you don't need to create an additional collection (and to remember to add elements in it in case you need more textboxes):
private bool AllTextboxesAreFilled()
{
return holderPanel.Controls.OfType<TextBox>().All(textbox => !string.IsNullOrEmpty(textbox.Text));
}
The usage is the same as in the previous example.

Finding which textbox is empty

I have short windows program I use to add information quickly. But now I'm trying to enhance it.
Was looking for a more efficient want to check for empty text boxes and if the box was empty to find which one it was and set the focus back to only that box. Currently I loop through all of them and check to see if any box was empty if it is just display a message. But have to look to see which box is missing text. Heres the code:
bool txtCompleted = true;
string errorMessage = "One or more items were missing from the form";
foreach(Control c in Controls)
{
if (c is TextBox)
{
if (String.IsNullOrEmpty(c.Text))
{
txtCompleted = false;
}
}
}
if (txtCompleted == false)
{
MessageBox.Show(errorMessage);
}
Your approach using foreach looks promising to me. Howver you can use LINQ as well
if(this.Controls.OfType<TextBox>().Any(t => string.IsNullOrEmpty(t.Text)) {
...
}
You can use the focus() method to set the focus to the empty text box.
Set the focus on the control while in your loop, then break when done.
foreach(Control c in Controls)
{
if (c is TextBox)
{
if (String.IsNullOrEmpty(c.Text))
{
txtCompleted = false;
c.Focus();
MessageBox.Show(errorMessage);
break;
}
}
}
To get a reference to the empty textbox you use almost the same solution as R.T. presents, but use FirstOrDefault instead:
var emptyTextBox = Controls.OfType<TextBox>().FirstOrDefault(t => string.IsNullOrEmpty(t.Text)
if (emptyTextBox != null)
{
// there is a textbox that has no Text set
// set focus, present error message etc. on emptyTextBox
}

Looping throughTextBoxes in a Panel

I have a panel that contains 5 textboxes, I am trying to loop through the Panel and insert the value of the textbox into the database if it is not 0.
my panel name is Panel1
I honestly do not know from where to start or how to loop in a Panel that contains textfields, any suggestions are appreciated:
Here is my try which it does not compile (I am not sure how to write a loop that loops through a panel)
const string query = "INSERT INTO deductible (number) VALUES (#yes)";
using (var command = new SqlCommand(query, conn))
{
foreach (Panel1 c in this.Controls)
{
if (c.ToString() != "0")
{
command.Parameters.AddWithValue("#yes", c.Text);
command.ExecuteNonQuery();
}
}
I also attached a screenshot of my Panel1.
Thank you.
The simple answer is
foreach(Control control in this.Controls) {
if (control is TextBox) {
// The code here ...
}
}
The problem though is that you then need to make sure that the order the textboxes are looped over is correct, which adds more maintenance work that is entirely unnecessary. A better approach would be to learn about data binding. Or even more simply, just name your textboxes and assign them directly. Either of those is preferable to using a loop I think.
One way is to iterate each control within your Panel that is a TextBox.
foreach (TextBox tb in Panel1.Controls.OfType<TextBox>())
{
if (tb.Text != "0")
{
}
}
You're trying to loop through items of type Panel1 in this.Controls. What you want to do is loop through items of type TextBox in Panel1.Controls.
foreach(Control c in Panel1.Controls) {
var textbox = Control As TextBox;
if(textbox != null){
// do stuff...
}
}
You also want to look at the Text property of the TextBox, not call ToString on it.
if(textbox.Text != "0"){ //do stuff... }
And you add a #yes parameter to the same command multiple times within the loop, without clearing out the parameters list. I'm not certain if that will work, but if it causes a problem, you should just be able to call command.Parameters.Clear to clear the old parameter before adding the new one.

Clearing all data on tab page when clicking No Button

in my application im submitting a data to the db on a tabControls page(page:tabPage2) and i want when hitting the submit button first saving data to db(im achieving this) the a question will ask anything will be done? if the user hit the no button all fields on tabpage2 will reset. so i wrote a script like below but it is not clearing fields.
if (dr == DialogResult.Yes)
{
for (int i = 0; i < this.tabControl1.Controls.Count; i++)
{
if (this.tabControl1.SelectedTab == tabPage2)
{
if (tabPage2.Controls[i] is TextBox)
{
tabPage2.Controls[i].Text = "";
}
if (tabPage2.Controls[i] is ComboBox)
{
tabPage2.Controls[i].Text = "";
}
if (tabPage2.Controls[i] is PictureBox)
{
tabPage2.Controls[i].Text = "";
}
if (tabPage2.Controls[i] is RadioButton)
{
tabPage2.Controls[i].Text = "";
}
}
}
}
If you control the class for the page layout within the specific tab page you want to clear, it's probably best to create a public or internal method in that class (such as Clear()) which can access each of its member controls and clear them directly. That's the easiest approach, and it should usually apply.
If you instead need it to handle a page with an unknown structure, you might need an approach like:
private void ClearControls(Control parentControl)
{
foreach (Control ctrl in parentControl.Controls)
{
TextBox ctrlText;
ComboBox ctrlCombo;
PictureBox ctrlPicture;
RadioButton ctrlRadio;
// Pay careful attention to the parentheses...
if ((ctrlText = ctrl as TextBox) != null)
{
ctrlText.Text = string.Empty;
}
else if ((ctrlCombo = ctrl as ComboBox) != null)
{
ctrlCombo.SelectedIndex = -1;
}
else if ((ctrlPicture = ctrl as PictureBox) != null)
{
// Logic to clear a PictureBox called ctrlPicture
}
else if ((ctrlRadio = ctrl as RadioBox) != null)
{
// Logic to clear a RadioButton called ctrlRadio
}
else if (ctrl.Controls.Count > 0)
{
ClearControls(ctrl); // Recursively clear contained controls.
}
}
}
With a call to start it off from the original handler:
if (dr == DialogResult.Yes)
ClearControls(this.tabControl1);
You are itering over the collection of TabControl child controls, not actual TabPage's.
Change your code to this instead:
if (dr == DialogResult.Yes && this.tabControl1.SelectedTab == tabPage2)
{
foreach (var ctrl in tabPage2.Controls)
{
if (ctrl is TextBox || ctrl is ComboBox || ctrl is PictureBox || ctrl is RadioButton)
{
ctrl.Text = "";
}
}
}
I should say though than setting the Text property to "" for controls other than TextBox feels rather wrong to me. As you'll find out, this won't work for combos, images and radio buttons.
Also if you have controls nested into panels or the like they won't be cleared. Containers have their own nested collection of controls, which in turn can also be containers, and so on and on.
IMHO it would be far better for you to explicitely reset form controls one by one rather than trying to find them dynamically on your form. This way you'll be free to move your controls around at design time without ever worrying about breaking the resetting logic.
Additional suggestion: you can also attach your controls at design time to an instance of your own IExtenderProvider component which will take care of resetting controls appropriately based on their type.

How can I check multiple textboxes if null or empty without a unique test for each?

I have about 20 text fields on a form that a user can fill out. I want to prompt the user to consider saving if they have anything typed into any of the text boxes. Right now the test for that is really long and messy:
if(string.IsNullOrEmpty(txtbxAfterPic.Text) || string.IsNullOrEmpty(txtbxBeforePic.Text) ||
string.IsNullOrEmpty(splitContainer1.Panel2) ||...//many more tests
Is there a way I could use something like an Array of any, where the array is made of the text boxes and I check it that way? What other ways might be a very convenient way in which to see if any changes have been made since the program started?
One other thing I should mention is there is a date time picker. I don't know if I need to test around that as the datetimepicker will never be null or empty.
EDIT:
I incorporated the answers into my program, but I can't seem to make it work correctly.
I set up the tests as below and keep triggering the Application.Exit() call.
//it starts out saying everything is empty
bool allfieldsempty = true;
foreach(Control c in this.Controls)
{
//checks if its a textbox, and if it is, is it null or empty
if(this.Controls.OfType<TextBox>().Any(t => string.IsNullOrEmpty(t.Text)))
{
//this means soemthing was in a box
allfieldsempty = false;
break;
}
}
if (allfieldsempty == false)
{
MessageBox.Show("Consider saving.");
}
else //this means nothings new in the form so we can close it
{
Application.Exit();
}
Why is it not finding any text in my text boxes based on the code above?
Sure -- enumerate through your controls looking for text boxes:
foreach (Control c in this.Controls)
{
if (c is TextBox)
{
TextBox textBox = c as TextBox;
if (textBox.Text == string.Empty)
{
// Text box is empty.
// You COULD store information about this textbox is it's tag.
}
}
}
Building on George's answer, but making use of some handy LINQ methods:
if(this.Controls.OfType<TextBox>().Any(t => string.IsNullOrEmpty(t.Text)))
{
//Your textbox is empty
}
public void YourFunction(object sender, EventArgs e) {
string[] txtBoxArr = { textBoxOne.Text, textBoxTwo.Text, textBoxThree.Text };
string[] lblBoxArr = { "textBoxOneLabel", "textBoxTwoLabel", "textBoxThreeLabel" };
TextBox[] arr = { textBoxOne, textBoxTwo, textBoxThree };
for (int i = 0; i < txtBoxArr.Length; i++)
{
if (string.IsNullOrWhiteSpace(txtBoxArr[i]))
{
MessageBox.Show(lblBoxArr[i] + " cannot be empty.");
arr[i].Focus();
return;
}
}
}

Categories