I have a list of variable in ASP.NET (C#) that I'm trying to loop through without writing dozens of If statements. What I was hoping to do is just reference each of them with a variable and append it to the variable name. So something like the following:
string _id1 = Id1CheckBox.Checke.ToString();
string _id2 = Id2CheckBox.Checke.ToString();
string _id3 = Id3CheckBox.Checke.ToString();
int x = 1;
while (x < 20)
{
if ("_id&" + x == "True")
{
_id + x = x.ToString();
}
else
{
_id + x = 0;
}
x++;
}
The logic behind what I'm trying to do is I have several checkboxes on a form, Id1CheckBox, Id2CheckBox, Id3CheckBox, etc. I need get these values as strings so I can pass them as parameters in a SQL query. So basically If Id1CheckBox = true then _id1 = 1. If Id2CheckBox = true then _id2 = 2. If any are false then I would want something like If Id3CheckBox = false then _id3 = 0. Is this possible or will I just need to write several If statements instead of using a loop?
You can put the checkboxes into an array like this:
private bool[] _checked;
public Form1() // Constructor
{
InitializeComponent();
_checked = Controls
.OfType<CheckBox>()
.Where(cb => cb.Name.StartsWith("Id"))
.OrderBy(cb => cb.Name)
.Select(cb => cb.Checked)
.ToArray();
}
Then loop the array like this:
for (int i = 0; i < _checked.Length; i++) {
if (_checked[i]) {
...
} else {
...
}
}
Note: An array is a list of numbered variables (so to say). We say that the array is indexed. The index range goes from 0 to the length of the array - 1.
If you have 20 checkboxes add leading zeroes to the names up to number 9. E.g. "Id05CheckBox". Otherwise the checkboxes won't be sorted right.
Note also that the form's Controls collection contains only the controls that are directly on the form. If the ckeckboxes are on a panel or tab-page or the like, then loop through the Controls collection of this container control: panel1.Controls or page1.Controls - you get it.
you could use the loop and do something like this inside of your loop
CheckBox checkbox = (CheckBox )this.FindControl("_id" + x.toString());
if(checkbox.isChecked)
//do something here
Then you can just read the value from there.
Answer came from here
I ended up going with a Dictionary and adding parameters in a foreach loop instead of attempting to combine variables. Heres the code:
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("ID1", _id1);
dictionary.Add("ID2", _id2);
dictionary.Add("ID3", _id3);
dictionary.Add("ID4", _id4);
int i = 1;
foreach (var pair in dictionary)
{
if (pair.Value == "True")
{
cmd.Parameters.AddWithValue(pair.Key, i.ToString());
}
else
{
cmd.Parameters.AddWithValue(pair.Key, "0");
}
i++;
}
Related
I´d like to be able to acces a Checkbox (or Textbox or similar) by just adding the last digit or letter like this:
int number = 1;
CheckBox tempCheckbox = "myform.checkBoxTool" + number;
tempCheckbox.Checked = true;
I guess this is already covered but I cant seem to find the right search words.
You have several opportunities. The most obvious is to use the ControlsCollection of your Form:
var checkBox = myForm.Controls["myform.checkBoxTool" + number];
Alternativly go with ControlCollection.Find:
var checkBox = myForm.Controls.Find("myform.checkBoxTool" + number, true).FirstOrDefault();
However if you have multiple checkboxes that all differ only by a single index, it´s a better idea to store them as a list or array of CheckBox in the first place:
List<CheckBox> myCheckBoxes = new List<CheckBox>();
Now you can easily access them by index:
var checkBox = myChekBoxes[number];
Be aware that indices - as any number in .NET - are zero-based. So the very first element in the list has index zero.
Technically, if tempCheckbox is on the same form where the querying code is, you can try Linq;
using System.Linq;
...
public partial class MyForm : Form {
...
int number = 1;
CheckBox tempCheckbox = this
.Controls
.Find($"checkBoxTool{number}", true) // we don't want "myform." here
.OfType<CheckBox>()
.FirstOrDefault();
// If check box found, check it
if (tempCheckbox != null)
tempCheckbox.Checked = true;
A better approach is to organize these controls into a collection, e.g. Dictionary:
public partial class MyForm : Form {
private Dictionary<int, CheckBox> m_CheckBoxTools = new Dictionary<int, CheckBox>();
public MyForm() {
InitializeComponent();
m_CheckBoxTools.Add(1, checkBoxTool1);
m_CheckBoxTools.Add(3, checkBoxTool3);
m_CheckBoxTools.Add(25, checkBoxTool25);
}
Then you can query the dictionary
if (m_CheckBoxTools.TryGetValue(number, out CheckBox tempCheckbox)) {
tempCheckbox.Checked = true;
}
you can use something like below
CheckBox chkList1 =new CheckBox();
chkList1.Text = strCheckboxText;
chkList1.ID="Chk"+intControlIndex;
chkList1.Font.Name = "Verdana";
chkList1.Font.Size = 9;
chkList1.Checked = true;
this.Form.Controls.Add(chkList1);
then you can check existing check box and find your ID. Assuming checkbox is in Panel control.
string str1="";
foreach (Control c in panel1.Controls)
{
if((c is CheckBox) && ((CheckBox) c).Checked)
str1 += c.ID+ ", ";
}
str1=str1.Trim();
Assume we have an array list of type Employe , does expanding it's length by 1 make a new object in the list ?
is the code in else statement correct? and is it recommended?
public void ModifierEmp(int c)
{
for(int i = 0; i < Ann.Count; i++)
{
if(Ann[i].Code == c)
{
Ann[i].saisie();
} else
{
i = Ann.Count + 1; //expanding arraylist ann
Ann[i].saisie(); //saisie a method for the user to input Employe infos
}
}
}
https://imgur.com/VfFHDKu "code snippet"
i = Ann.Count + 1;
The code above is not expanding the list: it is only setting your index variable (i) to have a new value.
If you wanted to make the list bigger, you would have to tell it which object to put into that new space you create. For example:
Ann.Add(anotherItem);
Of course, this gives you the ability to decide whether to add an existing item, create a new item (e.g. Ann.Add(new Something() { Code = c })), or even add a null value to the list (which is not usually a good idea).
I've been trying to add multiple items to a list using a temporary variable and a loop of some kind. I'll create the temp variable and list outside of the loop, and then inside the loop the temp variable will change value, and then will be added to the list as a new element before the loop repeats. The problem is, whenever the temp variable is changed, all elements in the list will change to be the same.
As an example, if I was making a list of fruits, and entered te list 'banana', 'apple' and 'pear', the list when written to the console would read 'pear', 'pear' and 'pear', which is also how the list appears in debugging mode.
The specific code I've been typing is below:
string inputText = "";
List<TextNumbers> inputTextChars = new List<TextNumbers>();
TextNumbers temp = new TextNumbers();
bool charFound = false;
inputText = Console.ReadLine();
foreach (char letter in inputText)
{
for (int i = 0; i < inputTextChars.Count; i++)
{
if (letter == inputTextChars.ElementAt(i).character)
{
charFound = true;
}
}
if (charFound == false)
{
temp.character = letter;
temp.number = 0;
}
temp.number++;
inputTextChars.Add(temp);
charFound = false;
}
inputTextChars.Sort();
foreach (TextNumbers text in inputTextChars)
{
Console.WriteLine(text.character + ": " + text.number);
}
The class 'TextNumbers' is:
public class TextNumbers
{
public char character;
public int number;
}
So as you can see from the accepted answer on this question :
Yes, a list of reference types is actually just a list of references
This means you are adding a reference to temp to the list every time.
To avoid this, move the declaration of the temp variable to within your loop so that you are adding a reference to a completely new object every time, like so:
foreach (char letter in inputText)
{
TextNumbers temp = new TextNumbers();
//..... rest of code
I have 16 text boxes in my Form whose names are suffixed sequentially from 1 to 16 respectively.
i.e. The 16 test boxes are names TextBox1, 'TextBox2, .... all the way until the 16th one, which is namedTextBox16`.
I would like to read the contents of these 16 text boxes in a loop and modify the ith TextBox's contents or properties based on a certain condition.
How do I do this?
If you use WinForms, easiest way is to store text boxes references in array, in constructor of window:
TextBox[] data = new TextBox[16]{textBox1,textBox2, [...],textBox16};
then you can use for loop to access them.
You can try something like this:
Dictionary<string, string> yourValues = new Dictionary<string, string>();
foreach (Control x in this.Controls)
{
if (x is TextBox)
{
yourValues.Add(((TextBox)x).Name, ((TextBox)x).Text);
}
}
NOTE: On your future question please provide more information and make your question more clear.
i would try to find and modify using Linq:
using System.Linq;
//...
int x = 5; //number of textbox to search
var textbox = this.Controls.OfType<TextBox>().Single(tb => tb.Name.EndsWith(x.ToString()));
textbox.Text = "abc";
In case you have to loop thru all the texboxes in form, you can do something like this:
List<TextBox> textboxes = this.Controls.OfType<TextBox>().ToList();
foreach (TextBox box in textboxes)
{
box.Text = "something";
}
Easiest way according to what you specified is to use Linq.
Let's assume you have 3 TextBoxes :
// 1st -> which is named meTextBox1
// 2nd -> which is named meTextBox2
// 3rd -> which is named meTextBox3
As you can see from above every line differs only by the number ( index .. call it whatever you want ).
Now you can make your base "query" which would look like :
const string TB_NAME = "meTextBox{0}";
And as you can presume right now this will be used inside of string.Format method. Now to retrieve desired TextBox all you have to do is to make Linq statement :
string boxName = string.Format(TB_NAME, 7); // retrieve 7th text box
TextBox tBox = Controls.OfType<TextBox>().FirstOrDefault(tb => tb.Name == boxName);
This example does not consider nested Controls but you can make do this recursively which will retrieve nested Controls:
TextBox ByIndex(int idx, Control parent)
{
TextBox result = null;
string searchFor = string.Format(TB_NAME, idx);
foreach(Control ctrl in parent.Controls)
{
if(!(ctrl is TextBox) && ctrl.HasChildren)
{
result = ByIndex(idx, ctrl);
if( result != null)
break;
}
else if(ctrl is TextBox)
{
if(ctrl.Name = searchFor)
{
result = ctrl as TextBox;
break;
}
}
}
return result;
}
To use above method you can just call it like such :
public class MeForm : Form
{
//.. your code here ..
void meImaginaryMethodToRetrieveTextBox()
{
int meRandomIndex = 7;
TextBox tb = ByIndex(meRandomIndex, this);
// rest of the code...
}
}
I am trying to make a 1d array of lists. I make it like this:
public static List<string>[] words = new List<string>[30];
public static List<string>[] hints = new List<string>[30];
And I call it like this:
foreach (string item in vars.directory)
{
reader2 = new StreamReader(item);
while (reader2.Peek() > 0)
{
string line = reader2.ReadLine();
if (line.StartsWith("#"))
{
vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
}
else if (line.StartsWith("-"))
{
vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
}
else if (line == "#end")
{
counter++;
}
}
}
I just wanted to add that vars is where I keep my public variables and that counter is indeed at 0 when the loop starts.
EDIT
In my haste I forgot to add the question... oops...
Here it is: When I call the add function (or any another function for that matter) it returns a null reference exception. How can I fix this?
I assume you're crashing when attempting to call .Add on your array element. You need to initialize your arrays with valid objects.
for( Int32 i = 0; i < vars.words.Length; ++i )
vars.words[i] = new List<string>();
for( Int32 i = 0; i < vars.hints.Length; ++i )
vars.hints[i] = new List<string>();
Why not just make a List<List<string>>, but yes you can make an array of lists
Using a list of lists, as already recommended, would make you escape your problems,
and it´s much more flexible and handy than your construction.
-> f.i. if the size of your data changes, you don´t have to change the list size, but the array
Here's a one-liner to initialize an array of lists of size 30:
static List<string>[] lists = (from i in Enumerable.Range(0, 30)
select new List<string>()).ToArray();
The problem is that array values are initialized to the default value, and the default value for reference types is null.
default(List<string>) returns null.
So, you'll need to re-initialize the objects in the array before you can access them, otherwise you will get a NullReferenceException.
One way to initialize all the objects in your array up front is to use this Linq statement:
const int sizeOfLists = 5;
List<string>[] lists = Enumerable.Range(0, sizeOfLists)
.Select(i => new List<string>())
.ToArray();
Another option is to initialize and add the sub-lists only when you need them, by using an outer List:
var lists = new List<List<string>>();
// ...
var aSubList = new List<string>();
lists.Add(aSubList);
This is particularly useful if you don't know the size of the outer set of lists up-front, and is still accessible by index.
(This was a comment before, but I made it an answer since many other answers got caught up in the solution and don't describe the problem)
You could initialize the lists right before you use them:
foreach (string item in vars.directory)
{
reader2 = new StreamReader(item);
while (reader2.Peek() > 0)
{
string line = reader2.ReadLine();
// new code
if (vars.words[counter] == null) vars.words[counter] = new List<string>();
if (vars.hints[counter] == null) vars.hints[counter] = new List<string>();
if (line.StartsWith("#"))
{
vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
}
else if (line.StartsWith("-"))
{
vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
}
else if (line == "#end")
{
counter++;
}
}
}