So I have a form with many TextBox-es which all need to be filled in. I have researched textbox validation but I can only find instructions for validating singular text boxes. Below is the code I have for the singular textbox validation. I was just wondering if it possible to hit all of them at once instead of this for each one. Any help would be much appreciated!
private void txtName_Validating(object sender, CancelEventArgs e)
{
if (string.IsNullOrEmpty(txtName.Text.Trim()))
{
epName.SetError(txtName, "Name is required.");
}
else
{
epName.SetError(txtName, string.Empty);
}
}
Assuming you are using WinForms
// Get all the controls of the forms
var controls = this.Controls;
foreach (Control mycontrol in controls)
{
// Check if the Control is a TextBox
if (mycontrol is TextBox)
{
//Perform Operation
}
}
var controls = this.Controls;
foreach (Control mycontrol in controls)
{
// Check if the Control is a TextBox
if (mycontrol is TextBox)
{
epname.seterror(mycontrol, mycontrol+"is required");
}
}
Related
I am trying to implement using error provider to validate that my text boxes are not empty before proceeding with execution.
Error provider works on textboxes on the main form but refuses to work on any textbox or combo box that is in a groupbox or tabcontrol. It doesn't check the text boxes, it doesn't display error or waits until the user enter text/select item for the controls that are being checked.
Sure if I loose the groupbox or tabcontrol I would get the error check working as normal but I will also loose the benefit of using the groupbox and tab control for my application as I intended to.
I am using the code below to check if the textbox or combo box is empty/null.
Some help would be much appreciated, this has made me almost want to throw my computer out of the window.
private void button3_Click(object sender, EventArgs e)
{
//Validate the text box in the form before proceeding to store in Database
// var emptyornull = Controls.OfType<TextBox>().Where(box => box.Name.StartsWith("_")).OrderBy(box => box.TabIndex);
// var emptyornull2 = Controls.OfType<ComboBox>().Where(box => box.Name.StartsWith("_")).OrderBy(box => box.TabIndex);
var boxes = Controls.OfType<TextBox>();
foreach (var testControl in boxes)
{
if (string.IsNullOrEmpty(testControl.Text))
{
this.errorProvider1.SetError((Control)testControl, "error");
return;
}
this.errorProvider1.SetError((Control)testControl, (string)null);
}
}
This is because your code does not check the child controls and only checks the top level ones. You need to iterate through the Form's controls recursively:
private IEnumerable<Control> GetAllControls(Control control)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
}
private void button1_Click(object sender, EventArgs e)
{
errorProvider1.Clear();
foreach (Control c in GetAllControls(this))
{
if (c is TextBox && string.IsNullOrEmpty(c.Text))
errorProvider1.SetError(c, "Error");
}
}
Or, Linq way:
errorProvider1.Clear();
GetAllControls(this).Where(c => c is TextBox && string.IsNullOrEmpty(c.Text))
.ToList()
.ForEach(c => errorProvider1.SetError(c, "Error"));
Good luck.
The picture below represents a plug-in I am building.
Yellow = tabControl1; Orange = tabPage1; Blue = Main Panel (mainPanel); Green = 3 different panels inside the main panel (panel1, panel2 and panel3); White = TextBoxes (that I want to clear); DarkBlue = CheckBoxes corresponsing to the green panels
I am trying to clear any text from the TextBoxes that contain text and reset CheckBoxes when checked, with a button click.
I researched online and tried to accomplish this by the following way but it doesn't seem to be the correct way to handle this problem.
foreach (Control a in tabControl1.Controls)
{
foreach(Control b in tabPage1.Controls)
{
foreach (Control c in mainPanel.Controls)
{
foreach (Control d in panel1.Controls)
{
if (d is TextBox)
{
d.Text = " ";
}
if (d is CheckBox)
{
((CheckBox)d).Checked = false;
}
}
}
}
}
I have only shown panel1 here but tried doing the same thing for panel2 and 3 as well.
What exactly am I doing wrong here? Any help would be greatly appreciated!
You just need a simple recursive method that iterates all controls inside all child containers of a specified parent container, mainPanel, here.
If a control is of type TextBox or CheckBox, set its Text or Checked property accordingly:
(Note that you can also pass tabPage1 to the method, or any other ancestor)
ClearControls(panel1);
// or
ClearControls(tabPage1);
private void ClearControls(Control parent)
{
if ((parent == null) || (!parent.HasChildren))
return;
foreach (var ctl in parent.Controls.OfType<Control>())
{
if (ctl is TextBox txt) {
txt.Clear();
}
if (ctl is CheckBox chk) {
chk.Checked = false;
}
else {
if (ctl.HasChildren) {
ClearControls(ctl);
}
}
}
}
If you want to clear the TextBoxes and ComboBoxes inside of panel1 then you only need to loop through panel1's controls to do it. To handle any panel, you could just write a ClearPanel(Panel) function.
private void ClearPanel(Panel panel)
{
foreach (var ctrl in panel.Controls)
{
if (ctrl is TextBox tb)
{
tb.Clear();
}
else if (ctrl is CheckBox chkBx)
{
chkBx.Checked = false;
}
}
}
private void ClearPanel1Button_Click(object sender, EventArgs e)
{
ClearPanel(panel1);
}
Iterating through the controls in tabControl1, tabPage1, etc, etc adds unnecessary overhead if you already have a reference to the Panel you're dealing with. What's more, if any of the controls in the outer loops have an empty Controls collection then the inner loops won't execute. I suspect this might be why your code isn't working.
Note that the above solution will not handle any TextBox or ComboBox that is inside another container inside panel1. So, if panel1 had a GroupBox inside it which contained TextBoxes or ComboBoxes, they wouldn't be cleared. See the recursive solution below to handle that situation.
EDIT: After re-reading your question I thought maybe you want to clear all TextBox and CheckBox controls on the Form.
If you're needing to clear every TextBox or CheckBox on the Form, you can do this with recursion.
private void Clear(Control ctrl)
{
if (ctrl is TextBox tb)
{
tb.Clear();
}
if (ctrl is CheckBox chkBx)
{
chkBx.Checked = false;
}
foreach (Control child in ctrl.Controls)
{
Clear(child);
}
}
private void ClearButton_Click(object sender, EventArgs e)
{
Clear(this);
}
You could pass any Control to Clear(Control), so if you only wanted to do the TextBoxes and ComboBoxes on tabPage1 you could call Clear(tabPage1). This will clear all the TextBoxes and ComboBoxes on tabPage1, even if they're in a Panel or GroupBox or some other container.
I am a novice to C#.
My application contains Main form and a few usercontrols.
I want the usercontrol named "uc_MainMenu" to be displayed in the panel named "panel2" inside the Main form when I start running the applicaiton.
uc_MainMenu obj_uc_MainMenu = new uc_MainMenu();
private void frmMain_Load(object sender, EventArgs e)
{
this.panel2.Controls.Add(obj_uc_MainMenu);
}
It works.
uc_MainMenu contains a few buttons: btnHeadmaster,btnTeacher,btnStudent,btnAttendance,btnExam and btnLogin.
Each of those buttons' click will bring the corresponding predefined usercontrols.
Here is my question.
I want to disable all the buttons except btnLogin when the form loads.
How can I do that?
I tried this way but it didn't work.
foreach (Control ctrl in panel2.Controls)
{
if (ctrl.GetType() == typeof(Button))
{
((Button)ctrl).Enabled = false;
}
}
I can change each button's enabled properties in the uc_MainMenu, but if so I will have to change them again whenever I switch the usercontrols. That's why I left their enabled property to true when I designed the usercontrols.
Try this:
foreach (Control ctrl in obj_uc_MainMenu.Controls)
{
if (ctrl.GetType() == typeof(Button) && ((Button)ctrl).Name != "btLogin")
{
((Button)ctrl).Enabled = false;
}
}
Notice that I changed panel2 by obj_uc_MainMenu.
Create a property inside user control :
public bool MyButtonEnabled
{
get
{
return anyButtonButNo_btLogin.Enabled;
}
set
{
foreach (Control ctrl in this.Controls)
{
if (ctrl.GetType() == typeof(Button) && ((Button)ctrl).Name != "btLogin")
{
((Button)ctrl).Enabled = value;
}
}
}
}
Now you can use this property anywhere that usercontrol used.
uc_MainMenu obj_uc_MainMenu = new uc_MainMenu();
private void frmMain_Load(object sender, EventArgs e)
{
this.panel2.Controls.Add(obj_uc_MainMenu);
///this property will access the button inside that user control
obj_uc_MainMenu.MyButtonEnabled=false;
}
If your buttons is inside the obj_uc_MainMenu, then you can not retrieve it via panels.Controls. If you want to retrieve them, you should use obj_uc_MainMenu.Controls.
I don't know how did you define the user control obj_uc_MainMenu, then I guest you can do something like this:
foreach (Control ctrl in obj_uc_MainMenu.Controls)
{
if (ctrl.GetType() == typeof(Button))
{
((Button)ctrl).Enabled = false;
}
}
Find will find the panel. If it exists, then iterate through the usercontrol for type button and modify the button/s properties. No need of casting for button within foreach loop (we know its of type Button).
// Get the panel
var panel2 = Controls.Find("YourPanel", true).FirstOrDefault() as Panel;
// If it exists
if (panel2 != null)
{
foreach (var button in panel2.obj_uc_MainMenu.Controls.OfType<Button>())
{
// Set the value of each one
button.Enabled = false;
}
}
I added several textboxes by drag_n_dropping. Now I want to gather them all under a textbox array. I know how to create array of textboxes in code but not how to gather the textboxes created during design. Could anyone help please?
Sometimes the textboxes are not placed on the form directly but on a container control like a tab control or a split container. If you want to find all these textboxes, a recursion will help
private List<TextBox> _textboxes = new List<TextBox>();
private void GetTextBoxes(Control parent)
{
foreach (Control c in parent.Controls) {
var tb = c as TextBox;
if (tb != null) {
_textboxes.Add(tb);
} else {
GetTextBoxes(c);
}
}
}
Then you call GetTextBoxes by passing the form as argument
GetTextBoxes(this);
This is possible, since Form itself derives from Control.
This assumes your TextBoxes are within same GroupBox or Panel.
var groupOfTextBoxes = groupBox1.Controls.OfType<TextBox>();
MessageBox.Show(groupOfTextBoxes.Count().ToString());
var textBoxesWithinForm = this.Controls.OfType<TextBox>();
MessageBox.Show(textBoxesWithinForm.Count().ToString());
Requires using System.Linq;. Please note that textBoxesWithinForm will ignore TextBoxes that are within groupBox and vice versa.
Or like #Jeff suggests but instead of going thru this.Controls and comparing if Control is Textbox:
foreach (TextBox in this.Controls.OfType<TextBox>())
{
//add to your array
}
foreach (Control c in this.Controls)
{
if (c is TextBox)
{
//add to your array
}
}
foreach(textbox t in this.controls)
{
t.text=" ";
}
I want to clear all the textboxes in my page at one time.
I am getting an error:
Unable to cast object of type 'System.Web.UI.LiteralControl' to type
'System.Web.UI.WebControls.TextBox'.
The error is because your controls collection doesn't only contain text boxes. Try this instead.
foreach (Control c in this.Controls)
{
TextBox t = c as TextBox;
if (t != null)
{
t.text=" ";
}
}
You are going through the controls, and not all controls are necessarily textboxes, so the foreach loop cannot be compiled.
The straightforward approach is to do a foreach (Control c in this.Controls) and then check whether the control is a textbox.
You can also try this in later versions of .NET:
foreach(TextBox t in this.Controls.OfType<TextBox>())
Your page probably has child controls that has child controls too. Therefor the best way to do this is with recursion. I have written a function that reset all my controls for a certain page, panel or other control I define as the parent.
/// <summary>
/// Resets all the controls in a parent control to their default values.
/// </summary>
/// <param name="parent">Parent of controls to reset</param>
protected void ResetChildControls(Control parent)
{
if (parent.Controls.Count == 0)
return;
foreach (Control child in parent.Controls)
{
if (child is TextBox)
{
((TextBox)child).Text = "";
}
else if (child is HiddenField)
{
((HiddenField)child).Value = "";
}
else if (child is DropDownList)
{
DropDownList dropdown = (DropDownList)child;
if (dropdown.Items.Count > 0)
{
dropdown.SelectedIndex = 0;
}
}
else if (child is RadioButton)
{
((RadioButton)child).Checked = false;
}
else if (child is RadioButtonList)
{
RadioButtonList rbl = (RadioButtonList)child;
rbl.SelectedIndex = rbl.Items.Count > 0 ? 0 : -1;
}
else if (child is CheckBox)
{
((CheckBox)child).Checked = false;
}
else if (child is CheckBoxList)
{
CheckBoxList cbl = (CheckBoxList)child;
cbl.ClearSelection();
}
else if (child is DataGrid)
{
((DataGrid)child).SelectedIndex = -1;
}
ResetChildControls(child);
}
}
Based on the code that has already been posted on this page I would say the final piece of code to achieve what you asked (reset all text controls on a page) would look like:
protected void ResetTextBoxes(Control parent)
{
if(parent is TextBox)
{
((TextBox)parent).Text = string.Empty;
}
foreach(Control child in parent.Controls)
{
if (child is TextBox)
{
((TextBox)child).Text = string.Empty;
}
ResetTextBoxes(child);
}
}
This method can be used on any control or group of controls to reset all child textboxes. It takes into account:
The control passed (parent) may by a TextBox
That only textboxes being reset was requested in the original question
That the user hasn't specified if linq is allowed
That the control may have child controls.
You could use this like so:
ResetTextBoxes(this); // reset all TextBox's on a page
ResetTextBoxes(somePanel); // reset all TextBox's within a single <asp:Panel>
Other Options
Other options to reset textbox controls are:
Issue a Response.Redirect("~/ThisPageUrl.aspx"); to reload the current page
Disable viewstate on either the page or individual controls so that its state is lost after postback
using LINQ:
foreach (TextBox t in this.Controls.Where(c => c is TextBox))
{
//...
}