I have a function that clears a non-MDI child form, but when I apply it to an MDI child it doesn't do anything. I've tried attacking this problem from a few different angles without any luck, was hoping stackoverflow could help!
I've tried the code shown, I've also attempted to reference the child of the parent of the current form (Which is circular I know).
public static void ResetAllControls(Control form)
{
foreach (Control control in form.Controls)
{
if (control is TextBox)
{
TextBox textBox = (TextBox)control;
textBox.Text = "";
}
if (control is ComboBox)
{
ComboBox comboBox = (ComboBox)control;
if (comboBox.Items.Count > 0)
comboBox.SelectedIndex = 0;
}
if (control is CheckBox)
{
CheckBox checkBox = (CheckBox)control;
checkBox.Checked = true;
}
if (control is ListBox)
{
ListBox listBox = (ListBox)control;
listBox.ClearSelected();
}
}
}
I expect that passing this would clear all form controls as it does with standard forms.
I'm pretty sure that you have some kind of container on this for (eg. Panel) and controls are on this panel. Form.Controls will give you only controls that lay directly on the form. So you will have to do it recurrently:
public static void ResetAllControls(Control parent)
{
foreach(var child in parent.Controls)
ResetAllControls(child);
if(parent is TextBox)
{
(parent as TextBox).Text = "";
return;
}
//and so on
}
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;
}
}
I have a form with sixteen combo-boxes, each with the DropDownStyle property set to DropDownList. I am trying to set the form so each control shows its first pre-defined value:
private void Form1_Load(object sender, EventArgs e)
{
foreach (ComboBox DropDown in this.Controls.OfType<ComboBox>())
DropDown.SelectedIndex = 0;
}
This code is not working, although individually assigning each item does. Any ideas why?
My WinForm experience is a bit rusty, but if I remember correctly, this.Controls will only bring you those controls directly under the main Form. If you have any subcontrols, like a Groupbox, they will be under that groupbox's .Controls.
You can either explicitly iterate your Groupbox's controls, or you can use recursion to go over all child controls of the form, like you can see here.
You have to detect the control and its type for ComboBox...
This means you have to deal with nested loop to detect the controls
foreach (Control MyCtrl in this.Controls)
{
DoAllRichTextBoxes(MyCtrl);
}
void DoAllRichTextBoxes(Control control)
{
ComboBox Cmb = control as ComboBox;
TextBox TxtBx = control as TextBox;
if (Cmb == null && TxtBx == null)
{
// deal with nested controls
foreach (Control c in control.Controls) DoAllRichTextBoxes(c);
}
if (Cmb != null)
{
Cmb.GotFocus += new EventHandler(this.Tb_GotFocus);
Cmb.LostFocus += new EventHandler(this.Tb_LostFocus);
Cmb.KeyDown += new KeyEventHandler(this.VehComn_KeyDown);
Cmb.SelectedValueChanged += new EventHandler(this.AllCombos_SelectedValueChanged);
}
if (TxtBx != null)
{
TxtBx.GotFocus += new EventHandler(this.Tb_GotFocus);
TxtBx.LostFocus += new EventHandler(this.Tb_LostFocus);
TxtBx.KeyPress += new KeyPressEventHandler(this.TbCmb_KeyPress);
TxtBx.KeyDown += new KeyEventHandler(this.VehComn_KeyDown);
}
}
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))
{
//...
}