I have multiple panels and on each panel I have 2 RadioButtons. I need a way to check if a radiobutton has not been selected within each panel. If the panel contains 2 radiobuttons during a loop and if those 2 radiobuttons are not selected the variable (submit) would then be set to false.
Here is my code so far -
foreach(Panel panels in groupBox2.Controls)
{
foreach (RadioButton radio in panels.Controls)
{
if (!radio.Checked)
{
submit = false;
}
}
}
By default each panel will only contain one radio checked it the radio buttons AutoCheck is true, Anyway to your question:
foreach(Control parent in groupBox2.Controls)
{
Panel panel = parent as Panel;
if (panel != null)
{
foreach (Control child in panel.Controls)
{
RadioBox radio = child as RadioBox;
if (radio != null)
{
if (!radio.Checked)
{
MessageBox.Show(radio.ToString());
break;//if AutoCheck of all radio buttons seted to true
}
}
}
}
}
If you are only interested in one specific radiobutton, it would be easier to keep a global reference to it. That way you can just check the button directly whenever you'd like, rather than go through multiple loops.
Your code won't work because the Container.Controls collection contains "Control" references, so you need to check each control to see if it's the type you're looking for.
foreach(var control1 in groupBox2.Controls)
{
if (control is Panel)
{
foreach (var control2 in control1.Controls)
{
if (control2 is RadioButton)
{
if (!(control2 as RadioButton).Checked)
{
MessageBox.Show(control2.Text);
}
}
}
}
}
That will make your current code work. But I'm not quite sure what you're asking. There can only be one radiobutton selected in each containter.
if (!radM.Checked && !radF.Checked)
{
lblAnswer.Text = "Please Select male or female";
txtHT.Text = null;
}
Related
So I am making a "Disable all checked checkboxes" button for my windows form application in c#. The code I have works fine when set to loop through a specific panel, like so:
private void LockChecked_Click(object sender, EventArgs e)
{
foreach (Control c in block1Panel.Controls)
{
if (c is CheckBox)
{
CheckBox cb = (CheckBox)c;
if (cb.Checked == true)
{
cb.Enabled = false;
}
}
}
}
But what I'd like to do is loop through all the block panels (block1Panel, block2Panel, block3Panel, etc.) that are inside a main panel (Assignments_Panel).
So, how can I iterate through all the checkboxes from all panels, without having to write a loop for each panel? I know it's possible, but since I'm only a beginner I'm not able to figure this one out, even after hours of searching...
Thank you in advance! And if anything in my question is unclear please say so, so I can explain further!
This method may help. It loops through each control from a parent control, which in your case looks as tough it'd be Assignments_Panel, then for each control that belongs to the parent control, it will either loop through all child controls again, or disable the control, if it is a checkbox.
private void DisableCheckboxes(Control parentControl)
{
foreach (Control childControl in parentControl.Controls)
{
if (childControl is Panel childPanel)
{
DisableCheckboxes(childPanel);
}
else if (childControl is CheckBox childCheckBox)
{
childCheckBox.Enabled = false;
}
}
}
Well, we can enumerate all the controls within form while checking if the control is of type CheckBox; there are many implmentations for this, say
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
let's write good old Bread First Search (no Linq, recursion etc.)
private void LockChecked_Click(object sender, EventArgs e) {
Queue<Control> agenda = new Queue<Control>(new [] { this });
while (agenda.Count > 0) {
Control control = agenda.Dequeue();
if (control is CheckBox cb && cb.Checked)
cb.Enabled = false;
foreach (Control child in control.Controls)
agenda.Enqueue(child);
}
}
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;
}
}
For a game I have been developing, I am trying to do presence checks on all text boxes in a panel.
Before we go any further, here is my code:
private void btnCheck_Click(object sender, EventArgs e)
{
foreach (Panel pnl in Controls.OfType<Panel>())
{
foreach (TextBox tb in pnl.Controls.OfType<TextBox>())
{
if (string.IsNullOrEmpty(tb.Text.Trim()))
{
MessageBox.Show("Please give an answer for all questions!");
okFlag = false;
return;
}
else
{
okFlag = true;
}
}
}
if (okFlag == true)
{
//Check answers below
The issue I am having is that even if I have values in all text boxes, the MessageBox will still show, "Please give an answer for all questions.
okFlag is a boolean which I have initialised as true at the top of my code.
I should also note that I have multiple panels with text boxes in them but all other panels are hidden when one panel is showing.
This is the source where I got the code for this from
In conclusion, my issue is that the presence check on my text boxes aren't working as it seems to think that the text boxes are null or empty even when I do have values in them.
When you have got multiple panels and only one is visible your check will exit at the first invisible panel due to the textbox would have no text (it is invisible).
In your code you should check if the panel is visible:
private void btnCheck_Click(object sender, EventArgs e)
{
foreach (Panel pnl in Controls.OfType<Panel>())
{
if(!pnl.Visible)
continue;
foreach (TextBox tb in pnl.Controls.OfType<TextBox>())
{
if (string.IsNullOrEmpty(tb.Text.Trim()))
{
MessageBox.Show("Please give an answer for all questions!");
return;
}
}
...
I have multiple panels with text boxes in them but all other panels are hidden when one panel is showing.
Since your code does not differentiate between visible and hidden panels, the only explanation for getting the message that you see is that some of text boxes in a hidden panel are empty.
You can fix this by checking Panel's visibility in a loop:
foreach (Panel pnl in Controls.OfType<Panel>().Where(p => p.Visible))
{
foreach (TextBox tb in pnl.Controls.OfType<TextBox>())
{
if (string.IsNullOrEmpty(tb.Text.Trim()))
{
MessageBox.Show("Please give an answer for all questions!");
return;
}
}
}
Note that there is no need to use okFlag, because when you set it to false, your loop terminates early on the return statement anyway. In other words, there is no way to reach the end of the outer loop when okFlag is false.
you mentioned:
I have multiple panels with text boxes in them but all other panels
are hidden when one panel is showing
Just because a control is hidden doesn't mean it isn't still available in the Controls collection. Perhaps you should also be checking the visibility state before checking that panel's controls.
foreach (Panel pnl in Controls.OfType<Panel>())
{
if (pnl.Visible) {
foreach (TextBox tb in pnl.Controls.OfType<TextBox>())
{
if (string.IsNullOrEmpty(tb.Text.Trim()))
{
MessageBox.Show("Please give an answer for all questions!");
okFlag = false;
return;
}
else
{
okFlag = true;
}
}
}
}
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))
{
//...
}