C# Array of Controls - c#

Basically I have 3 arrays of different types:
control = new Control[2] { txtRecordDelimeter, txtFieldDelimeter };
name = new string[2] { "Record Delimiter", "Field Delimiter" };
exists = new bool[2] { false, false };
...essentially I would like to create a loop that checks whether the string existed in an object passed into a constructor, if did, set the bool of the respective index to true and then ammend the respective control with a new value.
Originally I had a bunch of if statements and repeating code so I wanna cut that out with a for loop.
However, for example, when I attempt to reference control[0].whatever I get the same list from IntelliSense regardless of whether or not the control is a text box or a combo box etc.
I'm guessing I'm missing something simple here like not referencing an instance of the control per se, but I'd be greatful if someone could explain what I'm doing wrong or suggest a better way to achieve this!
Thanks :]

Your Control[] array contains Control objects, not TextBox'es etc. You have to cast each particular object in order to use other properties. You can try this:
if(Control[i] is TextBox) (Control[i] as TextBox).Text = "Yeah, it's text box!";
if(Control[i] is CheckBox) (Control[i] as CheckBox).Checked = true;

I think you mean something like this:
for(int i = 0; i < control.Length; i++)
{
TextBox textBox = control[i] as TextBox;
if(textBox != null)
{
if(textBox.Text == name[i])
{
exists[i] = true;
continue;
}
}
}

you are getting same list from intellisense because all the elements in array are of Control type. You will need to Explicitely cast the Control to (TextBox) or (ComboBox).
lie this:
foreach(Control ctrl in control)
{
TextoBox tbx = ctrl as TextBox;
if(tbx != null)
{
//do processing
continue;
}
ComboBox cbx = ctrl as ComboBox;
if(cbx != null)
{
//do processing
continue;
}
//and so on
}

Related

How to use int i for selecting text box NR

I have 10 text boxes. Like textBox1.Text , textBox2.Text and so on. I need to use textBox2.Text if i=2, textBox2.Text if i =3 and so on.
I did:
string t = "textBox"+i+".Text";
But outcome coming as "textBox1.Text".
How to insert 'i' Value into textBox name instead of 1. And get the outcome as textBox1.Text
So I can use it as name and pass value from textbox to my program.
Based on what I think you are asking, you could store a reference to each TextBox in an array and then use your int to reference it.
TextBox[] boxes = new TextBox[10];
boxes[0] = textBox1;
// ... follow the pattern
boxes[9] = textBox10;
string value = boxes[i-1].Text; // Gets the value of the textBoxi.Text
You can do it like so:
private TextBox GetTB(int i) {
string name = "textBox" + i.ToString();
foreach (var ctrl in Controls) {
var tbox = ctrl as TextBox;
if (tbox?.Name == name) return tbox;
}
return null
}
The easiest way, if you need to access them in C# code this way, would be to maintain an array or List of these textboxes, indexed in order of their numeric value. Then you could simply reference textBoxes[i-1] and get the textbox numbered "i". How you get that array depends on exactly what you're developing. For WinForms, you can use a little Linq on the Form.Controls property:
public static IEnumerable<Control> Flatten(this IEnumerable<Control> controls)
{
var results = new List<Control>();
foreach (var control in controls)
{
results.Add(control);
control.Controls.OfType<Control>().Flatten(results);
}
return results;
}
private static void Flatten(this IEnumerable<Control> controls, List<Control> results)
{
foreach (var control in controls)
{
results.Add(control);
control.Controls.OfType<Control>().Flatten(results);
}
}
...
var textboxes = Form.Controls.Flatten()
.OfType<TextBox>()
.Where(t=>t.Name.StartsWith("textBox"))
.OrderBy(t=>t.Name)
.ToArray();

Check fields for null entry and change field background to lightyellow?

Great website - very helpful in my C# Class.
I am trying to write a method in C# that will Check fields for null entry and change field background to LightYellow?
The form is a display form that views records in a SQL database.
Here is what I tried - but the variable for the field names isn't translating to the field name.
Advice?
// YellowBack Method fills background of key fields that are missing data or are NULL
private void YellowBack()
{
//Bool fieldContents = true;
string fieldVariable;
string[] fieldName = { "activity_TitleTextBox", "act_Title2TextBox", "kid_NotesTextBox", "review_AdultTextBox",
"phoneTextBox", "addressTextBox", "cityTextBox", "websiteTextBox", "weblink_TextTextBox",
"hoursTextBox", "admissionTextBox" };
int count = 0;
//Check each field name
for (int index = 0; index < fieldName.Length; index++)
{
fieldVariable == fieldName.Text;
if (fieldVariable.Trim = "")
{
fieldVariable.BackColor = LightYellow;
}
else
{
fieldVariable.BackColor = Window;
}
}
}
You are not using the index . . . . you should be using something like:
fieldVariable = fieldName[i].Text;
I also think that you won't be able to set the property BackColor on fieldVariable as it is a string. You should probably be using the object grid or text control that your database binds to and setting the color properties of that . . . but I'm not sure there's enough information here to go on.
I think the problem is that you're looping through a list of strings and trying to make the string into a TextBox control. Instead, you should probably loop through all the controls on the form, and for each one that is a TextBox, see if it's name matches a name in your list. Then you can set the back color of the control based on the Text property.
There are other problems with your code also, like in your if statement you are doing an assignment (=) instead of a comparison (==).
Here's what I would do:
private void HighlightEmptyFields()
{
// Create a list of all the text box names that we want to examine
var textBoxNames = new List<string>
{
"activity_TitleTextBox", "act_Title2TextBox", "kid_NotesTextBox",
"review_AdultTextBox", "phoneTextBox", "addressTextBox", "cityTextBox",
"websiteTextBox", "weblink_TextTextBox", "hoursTextBox", "admissionTextBox"
};
// Loop through every control on the form
foreach (Control formControl in this.Controls)
{
// Find the groupbox control by name
if (formControl.Name != "groupBox1") continue;
// We found the group box, so loop through every control in it
foreach (Control groupBoxControl in formControl.Controls)
{
// Try to cast the control to a TextBox.
var textBoxControl = groupBoxControl as TextBox;
// If the cast fails, move on to the next one...
if (textBoxControl == null) continue;
// Now we have one a textbox control, so see if the
// textBoxNames array contains the name of this text box.
if (textBoxNames.Contains(textBoxControl.Name,
StringComparer.OrdinalIgnoreCase))
{
// We found a match, so set the backcolor based on Text property
if (textBoxControl.Text.Trim() == "")
{
textBoxControl.BackColor = Color.LightYellow;
}
else
{
textBoxControl.BackColor = Color.White;
}
}
}
// Since we found the control we were looking for, we can stop looking
break;
}
}

C# multiple checkboxes

I have 10 checkboxes on my form. They are named checkBox1, checkBox2, ..., checkBox10.
At the moment my code looks like this:
if(checkBox1.Checked)
Call MyFunction(1);
if(checkBox2.Checked)
Call MyFunction(2);
etc
Because the argument I pass to my function is the same as the checkbox number, I would like to use a for loop, so that for each checkbox_i, I should call MyFunction(i)
Thanks,
Nick
Not very safe, but simple way:
int index = 1;
foreach (var checkBox in this.Controls.OfType<CheckBox>())
{
if (checkBox.Checked)
{
MyFunction(index);
}
index++;
}
Next idea is safer, but not very elegant:
foreach (var checkBox in this.Controls.OfType<CheckBox>())
{
if (checkBox.Checked)
{
int index = int.Parse(checkBox.Name.Substring(8));
MyFunction(index);
}
}
Ultimately, best is to populate .Tag property of all checkboxes with appropriate indices. In this solution you could even skip some checkboxes like this:
foreach (var checkBox in this.Controls.OfType<CheckBox>().Where(c => c.Checked))
{
int? index = checkBox.Tag as int;
if (index.HasValue)
{
MyFunction(index.Value);
}
}
And even more readable way would be to have a list of checkboxes you are interested in this process in your form's constructor for example:
relevantCheckBoxes = new List<CheckBox>();
relevantCheckBoxes.Add(this.checkBox1);
relevantCheckBoxes.Add(this.checkBox3);
// etc.
And then:
for (int index = 0;index < relevantCheckboxes.Count;++index)
{
if (relevantCheckboxes[index].Checked)
{
MyFunction(index);
}
}
ok there are property in any control name Name check this pesodo code
Checkbox t=CheckBox(object);
var number=t.name.substring("checkbox".length,name.length-"checkbox".length) // to get only number or you can split name by regular expression
myfunction(int.parse(number));
// try this code and and ask here agine if any problem due to I can't test it now

Retaining Textbox Value

I'm trying to update a person's details in the database. Since I'm using textboxes, how would I keep the original value if the textbox is empty?
I'm trying to write it in a short way rather than having a tonne of IF statements.
The code I've written will work but not the way I want, any suggestions on what I could do?
Code (C#):
foreach (Control c in pnlUpdate.Controls)
{
if (c is TextBox)
{
TextBox questionTextBox = c as TextBox;
if (questionTextBox.Text == "")
{
questionTextBox.Text = pat[0].Forename;
questionTextBox.Text = pat[0].Surname;
questionTextBox.Text = pat[0].Street;
questionTextBox.Text = pat[0].Town;
questionTextBox.Text = pat[0].City;
questionTextBox.Text = pat[0].DOB.ToString();
questionTextBox.Text = pat[0].House_number;
questionTextBox.Text = pat[0].Mobile;
}
}
}
Pat = database object
I'm trying to update a person's details in the database. Since I'm using textboxes, how would I keep the original value if the textbox is empty?
Use Server Validation. To make sure that user has entered values for all controls you need to use RequiredFieldValidator. Go through below link:
http://msdn.microsoft.com/en-us/library/5hbw267h(v=vs.80).aspx
Something like below will provide you the help
pat[0].Name = TextBox.Text == "" ? pat[0].Name : TextBox.Text

Loop through Textboxes

I have a winforms app that has 37 textboxes on the screen. Each one is sequentially numbered:
DateTextBox0
DateTextBox1 ...
DateTextBox37
I am trying to iterate through the text boxes and assign a value to each one:
int month = MonthYearPicker.Value.Month;
int year = MonthYearPicker.Value.Year;
int numberOfDays = DateTime.DaysInMonth(year, month);
m_MonthStartDate = new DateTime(year, month, 1);
m_MonthEndDate = new DateTime(year, month, numberOfDays);
DayOfWeek monthStartDayOfWeek = m_MonthStartDate.DayOfWeek;
int daysOffset = Math.Abs(DayOfWeek.Sunday - monthStartDayOfWeek);
for (int i = 0; i <= (numberOfDays - 1); i++)
{
//Here is where I want to loop through the textboxes and assign values based on the 'i' value
DateTextBox(daysOffset + i) = m_MonthStartDate.AddDays(i).Day.ToString();
}
Let me clarify that these textboxes appear on separate panels (37 of them). So in order for me to loop through using a foreach, I have to loop through the primary controls (the panels), then loop through the controls on the panels. It starts getting complicated.
Any suggestions on how I can assign this value to the textbox?
To get all controls and sub-controls recursively of specified type, use this extension method:
public static IEnumerable<TControl> GetChildControls<TControl>(this Control control) where TControl : Control
{
var children = (control.Controls != null) ? control.Controls.OfType<TControl>() : Enumerable.Empty<TControl>();
return children.SelectMany(c => GetChildControls<TControl>(c)).Concat(children);
}
usage:
var allTextBoxes = this.GetChildControls<TextBox>();
foreach (TextBox tb in allTextBoxes)
{
tb.Text = ...;
}
You Could loop all the controls in the form asking one by one if it is a "Textbox" y ther return the complete List of them.
public List GetTextBoxes(){
var textBoxes = new List();
foreach (Control c in Controls){
if(c is TextBox){
textBoxes.add(c);
}
}
return textBoxes;
}
You can loop through the textboxes in your form in a fairly simple manner:
Func<ControlCollection, List<TextBox>> SearchTextBoxes = null;
SearchTextBoxes = coll => {
List<TextBox> textBoxes = new List<TextBox>();
foreach (Control c in coll) {
TextBox box = c as TextBox;
if (box != null)
textBoxes.Add(box);
if (c.Controls.Count > 0)
textBoxes.AddRange(SearchTextBoxes(c.Controls));
}
return textBoxes;
};
var tbs = SearchTextBoxes(this.Controls).OrderBy(tb => tb.Name);
Edit: Changed according to new requirements. Not nearly as elegant as the LINQ-solution, of course :)
Since this post seems to resurrect itself from time to time and since the solutions above do not find controls inside of controls, such as in a groupbox, this will find them. Just add your control type:
public static IList<T> GetAllControls<T>(Control control) where T : Control
{
var lst = new List<T>();
foreach (Control item in control.Controls)
{
var ctr = item as T;
if (ctr != null)
lst.Add(ctr);
else
lst.AddRange(GetAllControls<T>(item));
}
return lst;
}
And it's use:
var listBoxes = GetAllControls<ListBox>(this);
foreach (ListBox lst in listBoxes)
{
//Do Something
}
Iterate through controls within form and check name of the control if matched then set Text property as you require.
int i = 0;
foreach (Control contrl in this.Controls) {
if (contrl.Name == ("DateTextBox" + i.ToString())) {
contrl.Text = "requiredtexttobeset";
}
i = i + 1;
}
If you want to do without 'foreach' (If you have specific boxes to adjust/address)
int numControls = Page.Form.Controls.Count;
for (int i = 0; i < numControls; i++)
{
if (Page.Form.Controls[i] is TextBox)
{
TextBox currBox = Page.Form.Controls[i] as TextBox;
currbox.Text = currbox.TabIndex.ToString();
}
}
//THE EASY WAY! Always post easy solutions. It's the best way.
//This code is used to loop through all textboxes on a form for data validation.
//If an empty textbox is found, Set the error provider for the appropriate textbox.
foreach (var control in Controls)
{
if (control is TextBox)
{
//Box the control into a textbox. Not really needed, but do it anyway
var textbox = (TextBox)control;
if (String.IsNullOrWhiteSpace(textbox.Text))
{
//Set the errorProvider for data validation
errorProvider1.SetError(textbox, "Data Required!");
textbox.Text = String.Empty; //Clear out the whitespace if necessary
//blnError = true;
}
}
}
You can simply do this mate...
foreach (TextBox txt in this.Panel.Controls.OfType<TextBox>())
{
txt.Text="some value you assign";
}
If your text boxes are on the form directly and not on a Panel then you can replace this.Panel.Controls with this.Controls. That should be short and clear enough for you.
After the InitialiseComponents() call, add the textboxes to a collection member variable on the form. You can then iterate through them in order later on.
You can create a Dictionary of TextBox, int like the following
Dictionary<TextBox, int> textBoxes = new Dictionary<TextBox, int>();
foreach (TextBox control in Controls.OfType<TextBox>())
textBoxes[control] = Convert.ToInt32(control.Name.Substring(11));
Now.. to loop through them..
foreach (var item in textBoxes.Select(p => new { textBox = p.Key, no = p.Value}))
item.textBox.Text = item.no.ToString(); // whatever you want...
Good luck!
Since you already know the name of control, therefore you can search the control by its name.
See Get a Windows Forms control by name in C#
Other answers just not cutting it for you?
I found this as an answer to a similar question on SO, but I can't find the thread now. It recursively loops through ALL controls of a given type which are located within a control. So includes children of children of children of... etc. My example changes the ForeColor of each TextBox to Hot Pink!
public IEnumerable<Control> GetAllControlsOfType(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAllControlsOfType(ctrl, type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
Implementation:
IEnumerable<Control> allTxtBxs = GetAllControlsOfType(this, typeof(TextBox));
foreach (TextBox txtBx in allTxtBxs)
{
txtBx.ForeColor = Color.HotPink;
}
Quite similar to abatishchev's answer(which, for me, only returned first-level child controls), but different enough to merit it's own answer I think.

Categories

Resources