This question already has answers here:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
(28 answers)
Closed 2 years ago.
I created a form with multiple panel over it and I use panel control to display relevant information. Third panel have 20 text boxes and I want to check whether all the details are filled. So I simply used this code below.
private void Calculatebutton_Click(object sender, EventArgs e)
{
foreach(Control c in Controls)
{
if(c is TextBox)
{
Console.Beep();
if (!String.IsNullOrWhiteSpace(textbox.Text) &&
!String.IsNullOrEmpty(textbox.Text))
{
SaveToDatabaseButton.Enabled = true;
}
}
}
}
The problem is that the condition in the if statement is getting false, I cannot hear any beep sound or the other button enabled. if I changed from "c is TextBox" to "c is Panel" i can hear the beep sound for three times. I also tried the code like this
if(c is TextBox)
{
c.Text = " ";
}
But nothing works. Please help me to overcome this problem. Thanks in advance.
I tested your code and it entered the beep just fine, consider Ahmed's comments about the text boxes being in another container or form.
Not related to your question directly but, the logic of when to enable the button is incorrect as far as I can tell, because only one of the text boxes being not empty will suffice to enable the button to save to database, I assume you want all text boxes not empty for that to happen.
I would suggest something like this if that's the case:
private void Calculatebutton_Click(object sender, EventArgs e)
{
var isThereEmptyTextBox = false;
foreach(Control c in Controls)
{
if(c is TextBox)
{
Console.Beep();
if (!String.IsNullOrWhiteSpace(textbox.Text) &&
!String.IsNullOrEmpty(textbox.Text))
{
isThereEmptyTextBox = true;
}
}
}
SaveToDatabaseButton.Enabled = !isThereEmptyTextBox;
}
As soon as just one text box is empty that flag will be set to true and will stay that way whether more empty text boxes appear or not, then you use that flag to enable/disable the button.
Related
For instance, I want all my text boxes to respond to Ctrl-A by selecting all text. I see several options:
Add an event handler to all the text boxes that takes care of the keyboard shortcuts
Subclass TextBox and replace all my text boxes with it
Create a user control that wraps TextBox and replace all my text boxes with it
However all of these involve changing each and every text box in the app. Is there any sort of thing I could do globally to all text boxes via one action to accomplish this? I kind of doubt it but I thought it wouldn't hurt to ask! (I mean, I suppose now that .NET is open source I could build a custom framework, but that's definitely overkill!)
I have a idea about that. The first step is get all controls of a control. Like this method:
public static IEnumerable<Control> GetAllControls(Control container)
{
List<Control> controlList = new List<Control>();
foreach (Control c in container.Controls)
{
controlList.AddRange(GetAllControls(c));
controlList.Add(c);
}
return controlList;
}
You can improve this method to get just the TextBox's.
So, now you have all the TextBoxes that you want. You can add a event for each, something like that:
foreach( var textBox in textBoxList )
{
textBox.KeyPress += MeyKeyPressEvento_KeyPress;
}
Or you can put that event int your form and select all TextBoxes.
I hope you can get a mindset with my answer. Good luck 🖖🏻
Dynamically attach your events when you load your form.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// iterate all controls on the form
foreach (Control control in this.Controls)
{
if (control is TextBox textBox)
{
// attach your event's method
textBox.KeyDown += OnKeyDown_SelectAllText;
}
}
}
private void OnKeyDown_SelectAllText(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.A)
{
TextBox textBox = (TextBox) sender;
textBox.SelectAll();
}
}
// be sure to detach all events when done with form
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (Control control in this.Controls)
{
TextBox textBox = control as TextBox;
if (textBox != null)
{
textBox.KeyDown -= OnKeyDown_SelectAllText;
}
}
}
}
Picture of my program
This program has a bunch of buttons of produce items. When the user clicks a button it automatically copies the bar-code of that item. For example if the user clicks the "Apples" button it will copy 43490905, aka the bar-code for apples. The user can then paste this number anywhere they want.
This produce list will get VERYY long, like 1000+ items. I don't want to navigate through all the items just to find apples.
How do I add a "Find" functionality? Like in google chrome I can just hit ctrl+f and type in apples and boom I can get all the results highlighted on the page.
Thank you.
For convenience, you should choose the TextChanged function for your TextBox, or if you still want to use the button, let copy these code and paste into your Button_Click function
private void textBox1_TextChanged(object sender, EventArgs e)
{
string text = textBox1.Text;
foreach (Control c in this.Controls)
{
if (c is Button)
{
if (!c.Text.ToUpper().Contains((text.ToUpper())))
{
//You can set the hightlight, or anything here
c.Visible = false;
}
else
{
//You can set the hightlight, or anything here
c.Visible = true;
}
}
}
}
I'm trying to program a matching game. My idea is:
(1). When a certain pictureBox1 is clicked, it becomes invisible
(2). A MessageBox shows up, prompting "Pick another box."
(3). Finally, I need to program an if/else statement where if pictureBox13 is clicked it becomes invisible; else, (if another pictureBox is clicked) a MessageBox prompts "Try again." And both picture boxes become invisible, but I don't know what I am doing wrong:
// Program From Below
private void pictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("Now Pick Another Hidden Picture!");
pictureBox1.Visible = false;
if (pictureBox13_Click)
{
MessageBox.Show("Great!");
pictureBox13.Visible = false;
}
else
{
MessageBox.Show("Try Again!");
}
}
There is a red squiggly line under if (pictureBox13_Click)
It would be better if every PictureBox had it's a state, that you would then manipulate using a Click_Event. Microsoft has a comprehensive tutorial for a matching game here: https://msdn.microsoft.com/en-us/library/dd553235.aspx
As other suggested, you can use same event handler for all your pictureBoxes and cast sender to PictureBox to see what PB was clicked :
List<string> selectedPictureBoxes;
public MyForm() // ctor
{
selectedPictureBoxes = new List<string>();
foreach(Control c in this.Controls)
if(c is PictureBox) c.Click += pictureBox_Click;
}
private void pictureBox_Click(object sender, EventArgs e)
{
PictureBox _clicked = sender as PictureBox;
if(!selectedPictureBoxes.Contains(_clicked.Name))
selectedPictureBoxes.Add(_clicked.Name);
else ....
}
You could create an int for the selected boxes (in this example, box1 and box2) which are both set to 0 and then create an on click event which sets the int to the clicked box.
if(box1 != 0)
{
box2 = 'insert selected box number'
}
else
{
box1 = 'insert selected box number'
}
After two boxes have been selected, both integers can be set to false, this allows for you to use a switch instead of if, which could shorten the code substantially if a separate if statement is required for each pair of pictures.
I'm pretty stuck here and I need help.
I got a lot of text boxes in my form, some visible and some invisible.
I want that Button2 will be active only when all text boxes (that are not hidden) are not empty (At least one character or number)
I saw all kinds of codes, but I could not figure out how to do it. (and it's not working for me)
For example here's a code that I tried, but it did not work out.
bool invalid = this.Controls.OfType<TextBox>()
.Where(t => t.Visible)
.Any(t => string.IsNullOrWhiteSpace(t.Text));
if (invalid)
button2.Enabled = false;
I would also like an explanation if it possible.
Thank you!
Well, I would use this procedure to set the button's availability (imagine there are only three textboxes):
private void SetButton()
{
button2.Enabled = (textBox1.Text != "" || textBox1.Visible == false) && (textBox2.Text != "" || textBox2.Visible == false) && (textBox3.Text != "" || textBox3.Visible == false);
}
For each textbox, it returns a true boolean if the textbox is filled or is invisible. In order to make sure it takes effect immediately, I would double click each textbox on the designer file to get the "textBox(number)_TextChanged" eventhandler, and then call the procedure that I just made. For example:
private void textBox1_TextChanged(object sender, EventArgs e)
{
SetButton();
}
Hope this helps ^_^
A recursive method that iterates over all controls on the form and looks for visible / enabled Textboxes is how I'd do it:
private void AreControlsValid(Control.ControlCollection controls)
{
foreach (Control c in controls)
{
if (c is Textbox && c.Visible)
{
if (String.IsNullOrEmpty(((Textbox)c).Text))
return false;
}
if (c.HasChildren)
AreControlsValid(c.Controls);
}
return true;
}
*Didn't test, this is an adaptation of an answer I posted in another thread: Ability to find WinForm control via the Tag property
edit: Also you'd probably want an generic event that all your textboxes subscribe to along the lines of:
textbox_TextChanged(object sender, EventArgs e)
{
button2.Enabled = AreControlsValid(this.Controls);
}
As Steve mentioned in a comment, the problem with MyForm.Controls is that it only gets direct children controls on your form, it does not get those children's children. So if you have a form, with a groupbox, with textboxes, MyForm.Controls will get you the groupbox and not the textboxes. That's why mine is recursive; it goes all the way down.
I'm trying to use this custom method for user input validation in text boxes. But I feel something missing in this approach. Now use cant move to next text box if the validation failed. Is this a good thing or bad thing to do?
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;
}
}
Adding the handler to the textboxes 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;
}
How about using Error Provider, it will display exclamation if validation fail
I thought it would be a bad user experience if you popup too much message box. May be you should consider use labels to display error message beside each text box. In your programm, I can't even close the window by clicking the close button if I left the text box empty.