use more than one labels - c#

In my ASP.NET application I have around 7 to 8 Label controls and currently my code to set their Text value looks like this:
while (MyReader.Read())
{
if(j>=i && j-i<=10 && j<(10+i+a))
{
Label"+[j]+".Text=a;
}
j++;
}
Now my label name statred from 1 to 8, I dont want to repaeat my statements like:
label1.text=a;
label.text=b;
What to do?

Rather than having seven different variables (label1, label2 etc) have one variable of type List<Label> or something similar. Then you can access them by index, iterate over all of them etc.
If you're relying on the designer to declare your variables for you, you could leave them alone but also have a collection variable which you populate in one place. The only problem is that then if you reassign the individual variables, that change won't be reflected in your collection.
As an aside, it looks like you've got your presentation logic and your data access logic in one place - you should consider separating them...

That actually should resolve your issue:
((Label)Page.FindControl("Label" + j)).Text = a;
However as Jon suggested, it would be better to manage your labels in more generic way using list or something.

try this
while (MyReader.Read())
{
if(j>=i && j-i<=10 && j<(10+i+a))
{
Label lbl = new Label();
lbl.Name="Label" + j;
lbl.Text = a;
}
j++;
}

Related

Get element by name

I am trying to loop trough something 3 times and change the .text property of 3 element that have the names "label1", "label2" and "label3". I'm trying to add the 1,2,3 to the label but I can't get it to work.
this is what I'm trying to do:
the y is either 1,2 or 3
("label" + y).Text
I think you want this,so I make a simple code of it.
for(int i = 1; i <= 3; i++)
{
Console.WriteLine("label" + i);
}
if I understand correctly - you can do this using reflection:
var temp = (double)typeof(MyClass).GetProperty("label" + y).GetValue(myClassInstance);
if you change the type of MyClass to the class that holds your variable, myClassInstance to an instance of your class and the cast from double to your field type (which I'm guessing is some sort of WPF / Winforms control) you can get the variable by name.
It's important to note that your program will slow down if this is used often.

c# getting values from using loop like combobox[i], i++

Hello i am working on some personal project,
I have lots of comboboxes in my project, which names are combobox1,combobox2 etc..
What i am trying to do is, getting combobox.text values respectively and do some work according to this.
Here is my code below;
for (i = 1; i <= geneList.Length; i++)
{
baserequest = "/" + comboBox[i].Text + ".docx";
sources.Add(new Source(new WmlDocument(basesource + geneList[i] + baserequest), false));
baserequest="";
DocumentBuilder.BuildDocument(sources, Path.Combine(tempDi.FullName, "Output.docx"));
}
so that actually not work. I searched but i think i missearching something because all i can get is about iterating through items, but what i want to do is exactly this;
comboBox[i].Text
Thank you very much.
If your comboboxes are named comboBox1, comboBox2 .... then you can't refer to comboBox2 using a syntax like comboBox[2]. This syntax means .. give me the third combobox stored in an array of comboboxes (and that should contain at least 3 elements)
So if you really want to use this syntax you need to create that combobox array somewhere in your code. After the call to InitializeComponent for example
public class Form1: Form
{
// declare the array as a global variable
private ComboBox[] combobox;
public Form1()
{
// Create and initialize all the elements of your form
// according to the properties set in the WinForms Designer
InitializeComponent();
// Choose all the individual comboboxes that you want to use
// inside your loops in the remainder of your code
combobox = new ComboBox[] { comboBox1, comboBox2, comboBox3 };
}
// all the code of your Form1 follows.....
}
A final note: You use a different array to create your loops. This array is named geneList and it should be kept in sync with the combobox array. Meaning the two arrays should have the same number of elements otherwise (if the geneList array is bigger than the combobox one you will get an ArgumentOutOfRangeException). Also array indexing start at index 0 not 1 so the usual loop is created with this syntax
for (i = 0; i < geneList.Length; i++)
Otherwise if you start from 1, as you do now, you skip the first element in the array and the last loop searches for an element that doesn't exist.

Out of bounds exception whilst using arrays

I have an array of textboxes in which they change dyanmically depending on what the user types in. Those textboxes contain a number which represents a score of an assignment. Those score are linked to a module object. So if the user has 3 modules; 2 assignments on the first and second module and 3 assignments on the third module; then in total there would be 7 textboxes created for the user to input all their assignment marks.
What I am trying to do is to create a keyup event handler in which it gets the number in typed in by the user, and then dynamically calls a method to display the average of the the module. This is what I have so far. The following method gets called whenever the user types in a character:
public void calculateLevel4Modules(int counter) {
//iterate through modules
//iterate through assignts in that module
//whilst iterating, check tb and set userscore
//after iterating, update overall label with regards to modulecounter
//int assignmentCounter = 0;
//Console.WriteLine("in If statement.. " + counter);
for (int moduleCounter = 0; moduleCounter < requiredLevelList().Count; moduleCounter++)
{
int totalNumberOfAssignmentsInCurrentModule = requiredLevelList().ElementAt(moduleCounter).Assignments.Count;
Console.WriteLine("total number of assignmetns: " + totalNumberOfAssignmentsInCurrentModule);
assignmentCounter = assignmentCounter + totalNumberOfAssignmentsInCurrentModule;
Console.WriteLine("assignment counter: " + totalNumberOfAssignmentsInCurrentModule);
if (counter < assignmentCounter)
{
Console.WriteLine("in If statement.. " + userMarksTBLvl4[moduleCounter].Text);
try
{
int userMark = int.Parse(userMarksTBLvl4[counter].Text);
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
double modAvg = requiredLevelList().ElementAt(moduleCounter).getModuleScoreOverall();
moduleOverallLvl4[moduleCounter].Text = modAvg.ToString();
break;
}
catch (FormatException) { break; }
}
else { }
}
it works fine if the user has one module but if the user has two or more, then I get an error in the following line:
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
I am getting an out of bounds exception. I know why; its because counter is basically the # of the textbox that was typed into but by me using counter, I am accessing something not within the assignments list. This is an example of when the problem occus:
The user has 2 modules. In each module there are 2 assignments thus 4 textboxes are been created with their index ranging from 0 - 3. If the user wants to type in their score of the first assignment on the second module, its basically trying to write to the third index in that element then it crashes since that module only consist of 2 assignments.
There are some strange things in your code that make it hard to answer. First, the code you posted doesn't compile, so we have no way to test it.
Several times you use code like:
requiredLevelList().ElementAt(moduleCounter)
I assume requiredLevelList is a method that returns a list of things. There is no reason to assume requiredLevelList returns the same list, or even lists with the same number of elements, each time you call it. Maybe it does in your particular case, but this is a dangerous thing to rely on. You should use a construct like:
foreach (var module in requiredLevelList())
{
int totalNumberOfAssignmentsInCurrentModule = module.Assignments.Count;
...
module.Assignments.ElementAt(counter).UsersScore = userMark;
...
}
Code like this:
Console.WriteLine("total number of assignmetns: " + totalNumberOfAssignmentsInCurrentModule);
is symptomatic of trying to debug something after it has crashed. That is extremely inefficient. Learn how to use a debugger; you will not become an effective programmer until you know how to do this.
requiredLevelList().ElementAt(moduleCounter).Assignments.ElementAt(counter).UsersScore = userMark;
You're probably getting an out-of-bounds exception here because counter is outside the indexes of Assignments. Since you never initialize or change counter, I have no way to know what it is or should be. A debugger will tell you this, use one.
the # of the textbox that was typed into but by me using counter, I am accessing something not within the assignments list.
OK, if you're typing something “not within the assignments list” then you have to test for that and decide what to do. Perhaps something like:
if (counter >= 0 && counter < module.Assignments.Count)
module.Assignments.ElementAt(counter).UsersScore = userMark;
else
throw new Exception("I really have no idea what you want to do here.");
This also looks wrong:
moduleOverallLvl4[moduleCounter].Text = modAvg.ToString();
You never tell us what moduleOverallLvl4 is, but here you're assuming it has the same size as what is returned by requiredLevelList(). Maybe they are in this particular case, but that is a dangerous assumption. If these values are related, moduleOverallLvl4 should be contained in whatever class implements requiredLevelList, and you should have a method that assigns getModuleScoreOverall() to the correct element of moduleOverallLvl4.

Control array type loop in C#/ASP.NET

I am writing a C#/ASP.Net web application and I have a large number of text boxes that need to be set to variable values in the code behind. Currently I am doing the following:
AspTextBox0.Text = codeBehindVariable[0];
AspTextBox1.Text = codeBehindVariable[1];
AspTextBox2.Text = codeBehindVariable[2];
AspTextBox3.Text = codeBehindVariable[3];
…
Is there an easy way to do this in a simple “for” loop??
This is a very simplified example, the real program has a switch case and some other testing that needs to be performed at the time the variable is assigned. Therefore, a “for” loop would drastically simplify the writing and maintainability of the code. Back in the good-old-days of VB6 and control arrays this was a piece of cake.
The good old days of VB6 are long gone and better don't come back.
Create a control array or better a List<TextBox> yourself:
var textBoxes = new List<TextBox> {
AspTextBox0,
AspTextBox1,
// ...
};
Then Zip it with the codeBehindVariable:
textBoxes.Zip(codeBehindVariable,
(textBox, variable) => textBox.Text = variable);
Or, if you prefer a for loop:
for ( int i = 0; i < codeBehindVariable.Length; i++ )
{
textBoxes[i].Text = codeBehindVariable[i];
}
Keep in mind that in the for loop you will have to make sure that both textBoxes and codeBehindVariable have the same number of items (or make the loop run only over the shortest list's amount of entries). The Zip function will take care of this by itself.
Assuming you are in a class that implements System.Web.UI.Page you can try to look up the control to find the one you want like so:
for (int i = 0; i <= codeBehindVariable.Length; i++)
{
var textBox = FindControl("AspTextBox" + i, false);
if(textBox != null)
{
textBox.Text = codeBehindVariable[i];
}
}
you can do something like this...
int i = 0;
foreach (Control ctrl in this.Controls)
{
if (ctrl is TextBox)
{
TextBox tempTextBox = (TextBox)ctrl;
tempTextBox.Text = codeBehindVariable[i];
i++;
}
}

Name of picturebox

I have many PictureBoxes with the names picturebox_D1, picturebox_D2... D30.
What I'd like to do is to change the images in those PictureBoxes, but in loop. Something like this, but working
for (int i = 0; i < 30; i++)
{
if (ReceivedDataTextBox.Text[i].ToString()=="1")
"pictureBox_D"+i.Image= new Bitmap(#"Pictures\\green.png");
else
"pictureBox_D"+i.Image= new Bitmap(#"Pictures\\red.png");
}
How can I do it?
You can use indexing of the parent container's controls to get a Control by name. For example: If your pictureboxes are just put straight on your form (i.e, not in a Panel, GroupBox or other container):
for(int i = 0; i < 30; i++)
{
((PictureBox)this.Controls["pictureBox_D" + i.ToString()]).Image = new Bitmap(#"Pictures\\green.png");
}
For nested PictureBoxes (i.e, ones within GroupBoxes or Panels), just take the same approach but on the parent container:
for(int i = 0; i < 30; i++)
{
((PictureBox)this.panel1.Controls["pictureBox_D" + i.ToString()]).Image = new Bitmap(#"Pictures\\green.png");
}
On the surface it may seem logical that by just typing in the string you should be able to reference variables, but once you start to delve deeper into C# you'll realize that this isn't really how things work in C#. The code you write into the IDE is compiled, and during that compilation, all the nice things about high level code (variable names, function names..etc) vanish; your "pictureBox_D" string is meaningless once the code is compiled and makes no sense to the compiler.
The best way to do this would be to create a PictureBox array and fill it with your pictureboxes like this:
PictureBox[] pictures = {picturebox_D1, picturebox_D2, ...};
then you can iterate over them
foreach(var p in pictures)
{
p.Image = new Bitmap(#"Pictures\\green.png");
}
Very simple solution:
PictureBox mybox = (PictureBox)this.Controls.Find("pictureBox2", true)[0];
In your constructor create and set a local Dictionary<string, PictureBox>. Remember, Forms are classes just like any other C# class and should be treated as such.
Instead of for, you can now use foreach and access the .Key and .Value to get the file names and PictureBox objects. This only works because you have such a rigid relationship between PictureBox name and desired picture, however. If the pairing changes, or you ever want to use the same image for two pictures boxes you'd want to change this to a List<Tuple<string, PictureBox>>. That may even be the best want to handle the situation, in fact.
public class Form1 : Form
{
private Dictionary<string, PictureBox> pictureBoxes;
public Form1()
{
pictureBoxes = new Dictionary<string, PictureBox>()
{
{"Pictures\\green.png", pictureBox_D},
{"Pictures\\blue.png", pictureBox_B},
// Etcetera
}
}
}
When you want to loop over them you do the following:
foreach(var kvp in pictureBoxes)
{
kvp.Value.Image = new Bitmap(kvp.Key);
}
I had to deal with a similar situation sometime ago where I had variable names var1, var2, ...
The best way I could find to get around having a monster switch case is to use reflection. Given the name of the picture box, you can easily find out the variable itself using reflection.
This should work:
// Assuming this is inside the form where the pictures boxes are hosted
for (int i = 0; i < 30; i++){
FieldInfo field = GetType().GetField("pictureBox_D"+i, flags);
PictureBox pictureBox = (PictureBox)field.GetValue(this);
if (ReceivedDataTextBox.Text[i].ToString()=="1")
pictureBox.Image= new Bitmap(#"Pictures\\green.png");
else
pictureBox.Image= new Bitmap(#"Pictures\\red.png");
}
You can use Controls.OfType<PictureBox>() combined with LINQ to get the items you want. In fact, you can probably transform them all into a collection you can use:
var picBoxes = this.Controls
.OfType<PictureBox>()
.Where(pb => pb.Name.StartsWith("pictureBox_D"))
.ToDictionary(pb => int.Parse(pb.Name.Replace("pictureBox_D", string.Empty)));
for(int i = 0; i < picBoxes.Length; i++)
{
// Do what you need with picBoxes[i]
}
The nice thing is that you can do this once in your constructor (after InitializeComponent is called) and you have this collection to reuse for the rest of the life of the form. This also ensures that should you add any additional PictureBoxes (that follow the same naming convention) you don't need to change anything.

Categories

Resources