I have a C# form with some types of controls, i throught this code for loop all Labels and re-parent:
private void MakeAllLabelTrans(Control frm, Control parent)
{
foreach (Control ctl in frm.Controls)
{
if (ctl is Label)
{
ctl.Parent = parent;
// ctl.BackColor = Color.Transparent;
}
else if (ctl.HasChildren)
{
MakeAllLabelTrans(ctl, parent);
}
}
}
and call as: MakeAllLabelTrans(this, picBackground); in Form_Load event, but some label was missed (i have puted a messagebox in the loop body - it really not in the loop), but i don't know why?
You're changing the collection while enumerating it. This leads to some items being skipped.
You should rewrite this to first build a list of controls that will need to be reparented, and then reparent them in a second pass.
You should not modify the collection on which you are iterating.
private static IEnumerable<Labels> FindAllLabels(Control container)
{
foreach (Control ctl in container.Controls)
{
var lbl = ctl as Label;
if (lbl != null)
{
yield return ctl;
}
else if (ctl.HasChildren)
{
foreach (var innerResult in FindAllLabels(ctl))
yield return innerResult;
}
}
}
// now call the method like this if you want to change a property on the label
foreach (var label in FindAllLabels(theForm))
label.BackgroundColor = Color.White;
// or like this (note the .ToList()) if you want to move the labels around:
foreach (var label in FindAllLabels(theForm).ToList())
label.Parent = someOtherControl;
Related
I have 2 listviews in tab page. however I am looking for a function to find the right control by name:
I have
foreach (Control c in form.Controls) // loop through form controls
{
if (c is TabControl)
{
TabControl f = (TabControl)c;
foreach (Control tab in f.Controls)
{
TabPage tabPage = (TabPage)tab;
foreach (Control control in tabPage.Controls)
{
MessageBox.Show(control.Name);
// code to go here
}
}
}
}
The Controls collection has a Find function that returns an array:
Control[] ctrls = this.Controls.Find("listView1", true);
if (ctrls.Length == 1) {
MessageBox.Show("Found " + ctrls[0].Name);
}
This will search for a control with the specified name in the controls of the specified control and all his sons.
public Control findControlbyName(String name, Control parent){
foreach (Control ctr in parent.Controls)
{
if (ctr.Name.Equals(name)) return ctr;
else return findControlbyName(name, ctr);
}
return null;
}
You just need to do:
findControlbyName("NameOfTheListView",this);
I was wondering why below did not work as expected...
if if-statement changed to (!ctrl.checked) it returns all radio-button's names)
myForm f = new myForm();
foreach (RadioButton ctrl in f.Controls.OfType<RadioButton>())
{
if (ctrl.Checked)
MessageBox.Show(ctrl.Name);
}
I also tried
foreach (Control c in f.controls)
if (c is radiobutton)
{
if (c.Checked)
{
messagebox.show(c.name);
}
when I then put all radio-buttons in a group-box and used below code:
foreach (RadioButton c in groupBox1.Controls)
{
if (c.Checked)
{
MessageBox.Show(c.Name);
}
}
it worked fine.
what's the difference here.
any help appreciated
I'm guessing that your radio button is the child of a control other than the form. You need to recursively search for the radio buttons.
public void DisplayRadioButtons()
{
Form f = new Form();
RecursivelyFindRadioButtons(f);
}
private static void RecursivelyFindRadioButtons(Control control)
{
foreach (Control childControl in control.Controls)
{
RecursivelyFindRadioButtons(childControl);
if (childControl is RadioButton && ((RadioButton) childControl).Checked)
{
MessageBox.Show(childControl.Name);
}
}
}
I have a groupbox in my application which contains child controls.(As seen in the attchached pic). I want to enumerate through all the textboxes for performing some validation using a simple foreach loop.
This document outline would give a fair idea of the housing of the controls
foreach (Control control in grpBxTargetSensitivity.Controls)
{
if (control is FlowLayoutPanel && control.HasChildren)
{
foreach (Control ctrl in control.Controls)
{
if (ctrl is Panel && ctrl.HasChildren)
{
foreach (Control tbox in ctrl.Controls)
{
if (tbox is TextBox)
{
TextBox textbox = tbox as TextBox;
validData &= !string.IsNullOrWhiteSpace(textbox.Text);
}
}
}
}
}
}
My question is, Is there a better way (possibly through LINQ) to get all the controls including the textboxes housed inside the panels than the above method.?
I don't know that this is any better.. whether it's easier to read is a matter of opinion:
var validData
= grpBxTargetSensitivity.Controls.OfType<FlowLayoutPanel>()
.SelectMany(c => c.Controls.OfType<Panel>())
.SelectMany(c => c.Controls.OfType<TextBox>())
.All(textbox => !string.IsNullOrWhiteSpace(textbox.Text));
This'll grab all TextBoxes inside of all Panels in all FlowLayoutPanels in your GroupBox, and return true if all of those TextBoxes have a value in them.
A one liner slution,
IEnumerable<TextBox> collection = grpBxTargetSensitivity.Children.OfType<TextBox>(); //assuming you are looking for TextBox
or
You can try following generic method,
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
then enumerate over the controls as follows,
foreach (TextBox tb in FindVisualChildren<TextBox>(grpBxTargetSensitivity)) //assuming you are looking for TextBox
{
// do something
}
I create one method by the ability to find any controls (or T type) and any inherited object from Control (or T type) for you:
public static List<T> GetSubControlsOf<T>(Control parent) where T : Control
{
var myCtrls = new List<T>();
foreach (Control ctrl in parent.Controls)
{
// if ctrl is type of T
if (ctrl.GetType() == typeof(T) ||
ctrl.GetType().IsInstanceOfType(typeof(T)))
{
myCtrls.Add(ctrl as T);
}
else if (ctrl.HasChildren)
{
var childs = GetSubControlsOf<T>(ctrl);
if (childs.Any())
myCtrls.AddRange(childs);
}
}
return myCtrls;
}
and use that this form for e.g:
foreach (var textbox in GetSubControlsOf<TextBox>(this))
{
validData &= !string.IsNullOrWhiteSpace(textbox.Text);
}
I found following links on StackOverflow itself:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
Loop through all the user controls on a page
Give them try. Should work in your case.
Before opening the form I used following code to check if its label then change the font
foreach (Label ctl in frm.Controls)
{
ctl.Font = usefontgrid;
}
But on first line return error because it check other control types such as textbox or button,etc.
How can I check if the object is only label then go to for each?
Try this;
foreach (Control c in this.Controls)
{
if (c is Label)
c.Font = usefontgrid;
}
Or
foreach (var c in this.Controls.OfType<Label>())
{
c.Font = usefontgrid;
}
Its not clear where you place this code (should be after initialize component) but try
foreach (Label ctl in frm.Controls.OfType<Label>())
{
ctl.Font = usefontgrid;
}
There is also the following Linq to do the same thing
foreach (Label ctl in frm.Controls.Where(x => x is Label))
try this.
foreach (Control ctl in frm.Controls)
{
if(ctl.GetType()==typeof(Label)){
ctl.Font = usefontgrid;
}
}
frm.controls will give all controls
You need to check whether the control is a type of Label.
I have a asp.net page which is inherited from a master page .I want to clear all controls in this page .I tried using the bellow method .This is not working if a master page is there. Otherwise its working fine any ideas?
private void ClearControls()
{
foreach(Control c in Page.Controls)
{
foreach (Control ctrl in c.Controls)
{
if (ctrl is TextBox)
{
((TextBox)ctrl).Text = string.Empty;
}
}
}
}
try this:
public void FindAllTextBox(Control ctrl)
{
if (ctrl != null)
{
foreach (Control c in ctrl.Controls)
{
if (c is TextBox)
((TextBox)c).Text = string.empty;
FindAllTextBox(c);
}
}
}
Ex.:
Control ctrl = this.FindControl("content");
FindAllTextBox(ctrl);
You should be able to do this with Page.Form.FindControl("ContentPlaceHolder1").Controls:
foreach (Control item in Page.Form.FindControl("ContentPlaceHolder1").Controls)
{
if (item is TextBox)
{
((TextBox)item).Text = string.Empty;
}
}
This is probably because of your controls are inside of another container when you add a master page. Have you tried adding another foreach before if?
private void ClearControls()
{
foreach(Control container in Page.Controls)
{
foreach (Control c in container.Controls)
{
foreach (Control ctrl in c.Controls)
{
if (ctrl is TextBox)
{
((TextBox)ctrl).Text = string.Empty;
}
}
}
}
}
I wouldn't do it this way though. Sometimes hardcoding is better. This would use a lot of resource when called on a page that contains lots of controls.
Don't hard code:
//Recursively get all the formControls underneath the current one, be it Page, UserControl or whatever.
public static IEnumerable<Control> GetAllControls(this Control parent)
{
foreach (Control control in parent.Controls)
{
yield return control;
foreach (Control descendant in control.GetAllControls())
{
yield return descendant;
}
}
}
Then you can call it in your webform / control:
var formCtls = this.GetAllControls().OfType<TextBox>();
foreach(TextBox txtbx in formCtls)
{
//do what you gotta do ;)
}
First, use operator as instead of is and cast:
TextBox tb = ctrl as TextBox;
if (tb != null)
{
tb.Text = String.Empty;
}
Second, you can use ITextControl instead of TextBox.
And third, try next extension method:
public static IEnumerable<T> GetChildControls(this Control control) where T : Control
{
var children = (control.Controls != null) ? control.Controls.OfType<T>() : Enumerable.Empty<T>();
return children.SelectMany(c => GetChildControls(c)).Concat(children);
}
Usage:
foreach (var c in this.Page.Controls.GetChildControls<TextBox>())
{
c.Text = String.Empty;
}
I had the same problem but I think I was making it too hard. I'm using an AJAX UpdatePanel control and I just referenced that instead of going all the way up to the MasterPage. This worked for me.
foreach (Control c in UpdatePanel1.Controls)
{
foreach (Control c1 in c.Controls)
{
if (c1 is TextBox)
{
TextBox txtBox = (TextBox)c1;
txtBox.Text = "0";
}
}
}
Just keep the controls in Panel, and try the code below
foreach (Control cntrl in pnl.Controls)//pnl is panel id
{
if (cntrl is TextBox)
{
TextBox txtBox = (TextBox)cntrl;
txtBox.Text = " ";
}
}
Make a method on your .cs like this:
//Where "this" is Page.
ClearInput(this);
private void ClearInput(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c.Controls.Count > 0)
ClearInput(c);
else
{
if (c is TextBox)
(c as TextBox).Text = "";
if (c is CheckBox)
(c as CheckBox).Checked = false;
if (c is DropDownList)
(c as DropDownList).SelectedIndex = 1;
}
}
}
private void EnableControls(Control control)
{
var textbox = control as TextBox;
if (textbox != null)
{
textbox.Enabled = true;
}
var dropDownList = control as DropDownList;
if (dropDownList != null)
{
dropDownList.Enabled = true;
}
var radioButton = control as RadioButton;
if (radioButton != null)
{
radioButton.Enabled = true;
}
var checkBox = control as CheckBox;
if (checkBox != null)
{
checkBox.Enabled = true;
}
foreach (Control childControl in control.Controls)
{
EnableControls(childControl);
}
}
public void getAllCtl(ControlCollection ctls)
{
foreach (Control c in ctls)
{
if (c is System.Web.UI.WebControls.TextBox)
{
//TextBox tt = c as TextBox;
////to do something by using textBox tt.
((TextBox)c).Text = string.Empty;
}
if (c is System.Web.UI.WebControls.CheckBox)
{
((CheckBox)c).Checked = false;
}
if (c is System.Web.UI.WebControls.DropDownList)
{
((DropDownList)c).SelectedIndex = -1;
}
if (c.HasControls())
{
getAllCtl(c.Controls);
}
}
}
calling in aspx.cs file as
getAllCtl(this.Form.Controls);
This is OK and tested work for all Master-child page and where ever multiple controls are contains in the page...