This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to find which textbox i have entered the information into on a form and make the rest of the textboxes within the form blanked out and locked so no information can be entered into them.
The problem is when i run the code and debug. I do not seem to be finding all the textboxes that are on the form when looping through them.
I have tried to change some of the information in the foreach by trying to find if groupbox name.equals and if items within groupbox equal text. I assume i have made mistake with the foreach statements.
Below is my code.
foreach (Control C in this.Controls)
{
if (C is GroupBox)
foreach (Control T in this.Controls)
{
if (T is TextBox)
{
{
if (T.Text != string.Empty && T.Name.Equals("txtlotno"))
{
txtheads.Enabled = false;
txtheads.BackColor = Color.LightGray;
GroupBoxHeads.BackColor = Color.LightSlateGray;
txtrisersgood.Enabled = false;
txtrisersgood.BackColor = Color.LightGray;
GroupBoxRisers.BackColor = Color.LightSlateGray;
}
else if (T.Text != string.Empty && T.Name.Equals("txtvingot"))
{
txtheads.Enabled = false;
txtheads.BackColor = Color.LightGray;
GroupBoxHeads.BackColor = Color.LightSlateGray;
txtrisersgood.Enabled = false;
txtrisersgood.BackColor = Color.LightGray;
GroupBoxRisers.BackColor = Color.LightSlateGray;
}
else if (T.Text != string.Empty && T.Name.Equals("txtheads"))
{
txtvingot.Enabled = false;
txtvingot.BackColor = Color.LightGray;
txtlotno.Enabled = false;
txtlotno.BackColor = Color.LightGray;
GroupBoxIngot.BackColor = Color.LightSlateGray;
txtrisersgood.Enabled = false;
txtrisersgood.BackColor = Color.LightGray;
GroupBoxRisers.BackColor = Color.LightSlateGray;
}
else if (T.Text != string.Empty && T.Name.Equals("txtrisersgood"))
{
txtvingot.Enabled = false;
txtvingot.BackColor = Color.LightGray;
txtlotno.Enabled = false;
txtlotno.BackColor = Color.LightGray;
GroupBoxHeads.BackColor = Color.LightSlateGray;
txtheads.Enabled = false;
txtheads.BackColor = Color.LightGray;
GroupBoxIngot.BackColor = Color.LightSlateGray;
}
}
}
}
}
There is a simple error in your loop initialization
foreach (Control C in this.Controls)
{
if (C is GroupBox)
{
foreach (Control T in C.Controls)
{
......
The second foreach should work on the controls of the groupbox not again on this.Controls.
Of course, these loops works only for TextBoxes contained in a GroupBox. If you have a TextBox outside of any GroupBox this code will not find them-
However, why do you need a loop?
You change a finite number of textboxes, so you could just access the textboxes directly
if (txtlotno.Text != string.Empty)
{
txtheads.Enabled = false;
txtheads.BackColor = Color.LightGray;
GroupBoxHeads.BackColor = Color.LightSlateGray;
txtrisersgood.Enabled = false;
txtrisersgood.BackColor = Color.LightGray;
GroupBoxRisers.BackColor = Color.LightSlateGray;
}
.... and so on the the other three
Your issue seems to be that you are iterating through this.Controls and not the controls in your groupbox
However, the loop seems redundant, since you directly access each Textbox by name. I would maybe try something like this:
List<TextBox> _disable = new List<TextBox>();
List<TextBox _enable = new List<TextBox>();
// Gather Textboxes to be disabled and enabled
foreach(Control c in this.Controls)
{
GroupBox group = c as GroupBox;
if(group == null ) // Not a group box so continue on
continue;
foreach(Control c in group.Controls)
{
TextBox tb = c as TextBox;
if(tb == null )
continue; // Not a textbox so continue on
if(!String.IsNullOrWhitespace(tb.Text)) // We have information so add to _enable
_enable.Add(tb);
else
_disable.Add(tb); // empty textbox so ... disable
}
}
// Enable or Disable Textboxes
foreach(TextBox tb in _enable)
{
tb.Enabled = true;
tb.BackColor = Colors.White
}
foreach(TextBox tb in _disable)
{
tb.Enabled = false;
tb.BackColor = Colors.LightGrey
}
This approach lets you Loop through all your group boxes, loop through all their textboxes and organize each textbox and enable/disable them together, or not disable any if the _enable list is empty. Alternatively, instead of adding them to a list, you could just disable them/enable them right there.
Hope this helps
It appears that you want to iterate through the Controls of the GroupBox:
foreach (Control C in this.Controls)
{
if (C is GroupBox)
foreach (Control T in C.Controls) // loop GroupBox controls
...
In WPF I am using the following procedure in order to get all TextBox Controls in main Grid and its nested containers. The same approach should work in your case as well.
private List<TextBox> GetTB(Grid Grd)
{
List<TextBox> _lstT = new List<TextBox>();
try
{
// get ALL TextBox in main Grid and sub Grid/UniformGrid
UIElementCollection _mainGrd = Grd.Children;
foreach (UIElement el in _mainGrd)
{
if (el is TextBox) { _lstT.Add((TextBox)el); }
else if (el is Grid)
{
foreach (UIElement el1 in ((Grid)el).Children)
{ if (el1 is TextBox) { _lstT.Add((TextBox)el1); } }
}
else if (el is UniformGrid)
{
foreach (UIElement el1 in ((UniformGrid)el).Children)
{ if (el1 is TextBox) { _lstT.Add((TextBox)el1); } }
}
}
return _lstT;
}
catch { throw; }
}
Related
I'm just wondering really.
I have series of if statements that check
if textboxes are empty (or have results strings) after i pass SQL
results to then
.
if (IncidentData.Tables[0].Rows[0]["Property Category"].ToString()
== "RoadVehicle")
{
lbl_alarmOperated.Visible = false; tb_alarmOperated.Visible = false;
}
else
{
lbl_alarmOperated.Visible = true;
tb_alarmOperated.Visible = true;
}
I have been looking into controls and seeing if i can do a check on all textboxes and hide them if they are empty (instead of writing loads of if statements)
i have this at the moment:
public void ChecknHide()
{
HideTextBoxes(this);
}
protected void HideTextBoxes(Control ctrl)
{
foreach (var c in ctrl.Controls)
{
if (c is TextBox) ((TextBox)c).Text = String.Empty;
{
((TextBox)c).Visible = false;
}
}
}
Its mostly put together from reading posts on here. But I've ran into an issue. When i compile and go to view the page i get this:
Unable to cast object of type 'ASP.masterpage_master' to type
'System.Web.UI.WebControls.TextBox'.
Any ideas whats going wrong?
The statement after the if isn't part of the condition. This causes all controls to be casted to a TextBox. You should be able to fix it like so:
protected void HideTextBoxes(Control ctrl)
{
foreach (var c in ctrl.Controls)
{
if (c is TextBox && ((TextBox)c).Text == String.Empty)
{
((TextBox)c).Visible = false;
}
}
}
Weird code line:
if (c is TextBox) ((TextBox)c).Text = String.Empty;
Try something like:
protected void HideTextBoxes(Control ctrl)
{
//Iterate over controlls
foreach (var c in ctrl.Controls)
{
//Check for Textbox controls with the .Text property equal to Null or Empty.
if (c is TextBox && string.IsNullOrEmpty(((TextBox)c).Text))
{
//Set visibility of Textbox control to invisible.
((TextBox)c).Visible = false;
}
}
}
You're checking if c is a TextBox, but then trying to cast c as a TextBox and set it to String.Empty in the same line, regardless of whether it actually is a TextBox.
if (c is TextBox) ((TextBox)c).Text = String.Empty;
Hello all I am slowly learning c#, and I have this problem:
I want to make a function that sets all panels not visible and then set one as visible given to me from a string variable.
public void setMeVisible(string PanelName)
{
PageMainScreen.Visible = false;
PageNewRegistration.Visible = false;
PageSelectedPatient.Visible = false;
["PanelName"].Visible = true; // in this line I want to set the value of
// PanelName.Visible=true.
// what is the format that I must put PanelName?
}
For Windows, The simplest way is loop through all the controls and check if its a panel and set it to false. In the same loop you can check panel.Name for the pass in "PanelName" and set it to true. Something like this
foreach(Control control in form.Controls)
{
if( control is Panel )
{
control.Visible = false;
if(control.Name == "PanelName")
control.Visible = true;
}
}
Use Page.FindControl for ASP.Net:
var control = FindControl(PanelName);
if (control != null)
control.Visible = true;
If your control is nested, you can create a FindControlRecursive function, suggested by this answer:
private Control FindControlRecursive(Control root, string id)
{
return root.ID == id
? root
: (root.Controls.Cast<Control>()
.Select(c => FindControlRecursive(c, id)))
.FirstOrDefault(t => t != null);
}
Then call it by doing:
var control = FindControlRecursive(form1, PanelName); // Or another top-level control other than form1
if (control != null)
control.Visible = true;
Use Controls.Find for a windows form application:
var control = Controls.Find(PanelName, true).FirstOrDefault();
if (control != null)
control.Visible = true;
Looping and finding controls is not really necessary. You should add all your panels to a same container, use the Controls collection and pass in the name to get the control:
public void setMeVisible(string PanelName) {
PageMainScreen.Visible = false;
PageNewRegistration.Visible = false;
PageSelectedPatient.Visible = false;
Control c = sameContainer.Controls[PanelName];
if(c != null) c.Visible = true;
}
If each time there is only 1 panel visible, you should use some variable to track the current shown panel and hide only this (instead of all controls as you did) like this:
Control currentShown;
public void setMeVisible(string PanelName) {
Control c = sameContainer.Controls[PanelName];
if(c != null) {
c.Visible = true;
if(currentShown != null) currentShown.Visible = false;
currentShown = c;
}
}
And the last, if you don't want to use the same container for all your panels. You should declare some List<Panel> to contain all your panels, then you can navigate through them easily:
List<Panel> panels = new List<Panel>();
panels.AddRange(new[]{PageMainScreen, PageNewRegistration, PageSelectedPatient});
public void setMeVisible(string PanelName) {
var c = panels.FirstOrDefault(panel=>panel.Name == PanelName);
if(c != null) {
c.Visible = true;
if(currentShown != null) currentShown.Visible = false;
currentShown = c;
}
}
NOTE: Don't try complicating your UI unnecessarily. I want to mean that you should place all your panels on the same container (such as your form). That's the way we do, that way you can use the first approach, no need to loop, easy to maintain. You should also consider the Dock and the methods like BringToFront() and SendToBack() to show/hide the view.
I'm working in VS 2012 using C# and WinForms for my application, and I'm curious what sort of routine I should use to clear all methods of entering data I have, which includes textboxes, comboboxes, and date time pickers. I've Googled and found a few 'answers', but none seem to work or actually prove helpful.
[EDIT]:
I kept researching and actually found a helpful method that I just had to add some ifs to to get what I wanted:
private void ResetFields()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is TextBox)
{
TextBox tb = (TextBox)ctrl;
if (tb != null)
{
tb.Text = string.Empty;
}
}
else if (ctrl is ComboBox)
{
ComboBox dd = (ComboBox)ctrl;
if (dd != null)
{
dd.Text = string.Empty;
dd.SelectedIndex = -1;
}
}
else if (ctrl is DateTimePicker)
{
DateTimePicker dtp = (DateTimePicker)ctrl;
if (dtp != null)
{
dtp.Text = DateTime.Today.ToShortDateString();
}
}
}
}
Something like this:
void ClearThem(Control ctrl)
{
ctrl.Text = "";
foreach (Control childCtrl in ctrl.Controls) ClearThem(childCtrl);
}
And then:
ClearThem(this);
Another option:
Create a class deriving from Panel, with all of what you need on it, and Dock it in the Form. When you need to "refresh" - simply replace that Panel with a new instance of that Panel.
You could just loop in all the controls of the form and clear depending on the control type
We can clear all Textboxes, Comboboxes but not the DateTimePicker
If you want to clear the DateTimePicker you must set the properties:
Format = Custom, CustomFormat = " " and in time that you want to select a date in DateTimePicker
private void dateTimePicker1_CloseUp(object sender, EventArgs e)
{
dateTimePicker1.Format = DateTimePickerFormat.Short;
}
And this could be the solution:
public static void ClearAll(Control control)
{
foreach (Control c in control.Controls)
{
var texbox = c as TextBox;
var comboBox = c as ComboBox;
var dateTimePicker = c as DateTimePicker;
if (texbox != null)
texbox.Clear();
if (comboBox != null)
comboBox.SelectedIndex = -1;
if (dateTimePicker != null)
{
dateTimePicker.Format = DateTimePickerFormat.Short;
dateTimePicker.CustomFormat = " ";
}
if (c.HasChildren)
ClearAll(c);
}
}
Loop through your form controls, match them to your types and set it to "" or null;
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...
I have a method that finds all the controls, iterates through them, determines if they are a textbox,drop down list, etc.. retrieves their ID name, and depending on the ID name it will set a boolean statement (thus I would know if that section of the form is complete, and will email to a certain group of people) unfortunetly this is done with too many if statements and was wondering if I could get some help making this more manageable
protected void getEmailGroup()
{
Control[] allControls = FlattenHierachy(Page);
foreach (Control control in allControls)
{
if (control.ID != null)
{
if (control is TextBox)
{
TextBox txt = control as TextBox;
if (txt.Text != "")
{
if (control.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (control.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
}
if (control is DropDownList)
{
DropDownList lb = control as DropDownList;
if (lb.SelectedIndex != -1)
{
if (control.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (control.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
}
}
}
}
Why not just use the Control.FindControl(string) method?
private void Button1_Click(object sender, EventArgs MyEventArgs)
{
// Find control on page.
Control myControl1 = FindControl("TextBox2");
if(myControl1!=null)
{
// Get control's parent.
Control myControl2 = myControl1.Parent;
Response.Write("Parent of the text box is : " + myControl2.ID);
}
else
{
Response.Write("Control not found");
}
}
from: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.control.findcontrol
It is hard to understand the logic behind your code, but I'm sure it can be written easier. For example you can do something like this:
DropDownBox box = FlattenHierachy(Page)
.Where(c => c is DropDownList)
.Cast<DropDownList>()
.Where(d => d.SelectedIndex != -1)
.FirstOrDefault();
if (box != null)
{
if (box.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
}
if (box.ID.StartsWith("EmpInfo_"))
{
EmpInfo = true;
}
}
Obviously you can make this generic if you extract the lambda expression from the seconde Where call. So you could reuse it for different types. That's the solution which is as close to your code as possible, but I guess it would be a better idea to use a recursive method traversing the page and giving that method your predicates as lambda expressions.
Cleaned up you code a little to only include each check once.
protected void getEmailGroup()
{
Control[] allControls = FlattenHierachy(Page);
foreach (Control control in allControls)
{
if (control.ID != null &&
((control is TextBox && ((TextBox)control).Text = "" )
|| (control is DropDownList && ((DropDownList)control).SelectedIndex != -1 ))
{
if (control.ID.StartsWith("GenInfo_"))
GenInfo = true;
if (control.ID.StartsWith("EmpInfo_"))
EmpInfo = true;
}
}
}
}
Instead of using the Lambda expression I have created a method that handles the control for me, and depending on the name of the control, it sets that section to be true
public bool setGroup(Control ctrl)
{
isAControl = false;
//set a section to true, so it will pull the html
if (ctrl.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
lstControls.Add(ctrl.ID.Replace("GenInfo_", ""));
isAControl = true;
return isAControl;
}
here is a small snippet of my code I only want to check for certain controls(to speed things up) and I go through each control as each control has a different way to get the value (textbox would use .text where dropdownlist would use .selectedValue)
if(control is TextBox || control is DropDownList || control is RadioButton || control is RadioButtonList
|| control is CheckBox || control is CheckBoxList)
{
if (control is TextBox)
{
TextBox txt = control as TextBox;
if (txt.Text != "" && txt.Text != "YYYY/MM/DD")
{
setGroup(control);
if (isAControl)
{
string controlNoGroup = lstControls.Last();
strHtml = strHtml.Replace("#" + (controlNoGroup.ToString()) + "#", txt.Text);
}
}
}