GetEnumerator problem in c# - c#

i got this GetEnumerator problem.. here's my situation
Panel eachPanel = new Panel();
eachPanel.Size = new Size(pnlProcessCon.Width - 27, 24);
eachPanel.Location = new Point(5, startPoint);
eachPanel.BackColor = (defaultColor == alterColor[0]) ? alterColor[1] : alterColor[0];
TextBox txtProcess = new TextBox();
txtProcess.Size = new Size(50, 20);
txtProcess.Location = new Point(2,2);
txtProcess.TextAlign = HorizontalAlignment.Center;
txtProcess.Text = "P" + Convert.ToString(startProcess);
TextBox txtBurstTime = new TextBox();
txtBurstTime.Size = new Size(50, 20);
txtBurstTime.Location = new Point(txtProcess.Right + 70, 2);
txtBurstTime.TextAlign = HorizontalAlignment.Center;
TextBox txtPriority = new TextBox();
txtPriority.Size = new Size(50, 20);
txtPriority.Location = new Point(txtBurstTime.Right + 70, 2);
txtPriority.TextAlign = HorizontalAlignment.Center;
eachPanel.Controls.Add(txtProcess);
eachPanel.Controls.Add(txtBurstTime);
eachPanel.Controls.Add(txtPriority);
pnlProcessCon.Controls.Add(eachPanel);
but when i call each of their text and add to dictionary, i got this error..
Error 1 foreach statement cannot operate on variables of type 'System.Windows.Forms.Panel' because 'System.Windows.Forms.Panel' does not contain a public definition for 'GetEnumerator' C:\Users\vrynxzent#yahoo.com\Documents\Visual Studio 2008\Projects\Scheduler\Scheduler\Form1.cs 68 13 Scheduler
and got my error here..
foreach (var each in pnlProcessCon)
{
String[] temp = new String[3];
foreach (var process in each)
{
temp = process.Text;
}
}

There are a few issues there.
First, you should enumerate the Controls collections. Second, you will have to cast each control to TextBox before you can retrieve the text. Third, you declared temp as an array, so you can't directly assign a string to it. Fourth (as Henk Holterman pointed out), you should use actual types and not var in the foreach loops.
I'm going to take a stab at working code here. Feel free to adjust for your own needs.
TextBox txtProcess = new TextBox();
txtProcess.Name = "Process";
//configure other textboxes, add to panels, etc.
foreach (Panel each in pnlProcessCon.Controls)
{
String[] temp = new String[3];
foreach (Control control in each.Controls)
{
if(control.Name == "Process")
{
temp[0] = ((TextBox)control).Text;
}
}
}

This would be the general idea (note: no var)
foreach (Panel p in pnlProcessCon.Controls)
{
foreach (Control process in p.Controls)
{
}
}
But make sure pnlProcessCon only contains Panels.

Related

How to initialize Labels in Label Array using foreach?

I want to create 32 labels in my Form so I used code like this:
//using System.Windows.Forms;
Label[] Lb_clubs;
Lb_clubs = new Label[32];
foreach(Label lb in Lb_clubs)
{
lb = new Label();
lb.Text = "somename";
//and other codes
}
But I am getting an error
CS1656 : Cannot assign lb because it is a foreach iteration variable.
Any Solution?
You can use a for loop as described by the #Phils and #rickvdbosch, but you can keep you foreach loop by using Enumerable.Select:
//using System.Windows.Forms;
Label[] Lb_clubs;
Lb_clubs = new Label[32].Select(lbl => new Label()).ToArray();
foreach (Label lb in Lb_clubs)
{
lb.Text = "somename";
//and other codes
}
You can't assign to the lb variable, because it's a foreach iteration variable, so it's in a read-only context. That's why you're getting Compiler Error CS1656:
This error occurs when an assignment to variable occurs in a read-only context. Read-only contexts include foreach iteration variables, using variables, and fixed variables. To resolve this error, avoid assignments to a statement variable in using blocks, foreach statements, and fixed statements.
Try a for-loop:
Label[] Lb_clubs;
Lb_clubs = new Label[32];
for (int i = 0; i < 32; i++)
{
var lb = new Label();
lb.Text = "somename";
//and other codes
Lb_clubs[i] = lb;
}
You need to use a for loop, not foreach
Label[] Lb_clubs;
Lb_clubs = new Label[32];
for (int i = 0; i < 32; i++)
{
var lb = new Label();
lb.Text = "somename";
//and other codes
Lb_clubs[i] = lb;
}
You can't assign a value in a foreach loop: you should also see the lb = new Label(); marked in the editor, which should tell you that it
Cannot assign to 'lb' because it is a 'foreach iteration variable'
which generates a Compiler Error CS1656.
You can do this (besides what others have already suggested) in one line, using Enumerable.Range:
var Lb_clubs = Enumerable.Range(0, 32).Select(l => new Label() { Text = "SomeText" }).ToArray();
Slightly different, adding a progressive value to the text, using the index of the enumeration and also assign a Name (and/or other values) to the Label, if needed:
var Lb_clubs = Enumerable.Range(0, 32).Select(idx => new Label() {
Text = "SomeText" + idx.ToString(),
Name = "SomeName" + idx.ToString() }).ToArray();

How to assign text to a Label with the Label ID being assigned by a string?

Target:
To write in the label text, but the label ID is assigned by a string.
Problem:
It doesn't work, no errors given. I looked in most places for an answer but nothing helped!
My Code:
string asdfj = treeView2.SelectedNode.Text;
string adqien = System.IO.Path.Combine(dir7, asdfj);
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
h1a.Text = "100";
for (int o = 2; o > 6; o++)
{
//This is the label name e.g "h2a',h3a" etc
string tempc = string.Format("h" + o.ToString() + "a");
foreach (Control ctr in this.Controls)
{
if (ctr is Label)
{
if (ctr.Name == tempc)
{
ctr.Text = tnsop[o];
}
}
}
}
I also consulted this post:
Use string variable content as label ID to update label.Text, I get error - 'string' does not contain a definition for 'Text'
You can do it simply like:
this.Controls.Find(labelname).Text = Value;
or
this.Controls.OfType<Label>().FirstOrDefault(x => x.Name == labelName).Text = Value;
The for loop
First of all, this is wrong for (int o = 2; o > 6; o++).
It starts at o = 2, then checks if o > 6, which is false, because o = 2, and then skips the loop.
I guess you wanted to write: for (int o = 2; o < 6; o++). I am not sure about that, fix it as appropiate.
Addendum: This would have been easily discovored by debugging and stepping. You can start by adding a break point on your code (in Visual Studio you can place your cursor on the desired line and press F9 - by default) and then run in the debugger. When the a line with the break point is reached, the debbuger stops the execution and let you inspect the values of the variables, the call stack, etc. You can then step with F10 or F11 (if you want to inside a method call) and see how the code evolves. You would notice it does not enter the for loop.
Finding the labels
If finding the label still does not work, I would guess the problem is that the labels are not directly on the form or that they do not have the given name.
You can use this.Controls.Find(name, searchAllChildren) to get the labels you need.
That is:
string labelName = string.Format("h" + o.ToString() + "a");
Control[] control = this.Controls.Find(labelName, true);
Note: Yes, I can figure out it is the name of the label by how you use it. Using a comment to tell me saves some time... however, please use better variable names. You won't need a comment to tell me this is the name of the label if the variable name says so.
You still need to check it for the label:
string labelName = string.Format("h" + o.ToString() + "a");
Control[] controls = this.Controls.Find(labelName, true);
foreach (Control control in controls)
{
if (control is Label) // if (control.GetType() == typeof(Label))
{
// ...
}
}
Building a Dictionary
However, I would advice against doing this every time. Instead, I suggest to build a dictionary:
Dictionary<string, Label> labels;
// ...
labels = new Dictionary<string, Label>();
for(int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
Label label = GetLabel(labelName);
labels.Add(labelName, label);
}
// ...
private Label GetLabel(string labelName)
{
Control[] controls = this.Controls.Find(labelName, true);
foreach (Control control in controls)
{
if (control is Label) // if (control.GetType() == typeof(Label))
{
return control as Label;
}
}
return null;
}
Note: I suggest to make the dictionary a field and initialize it only once during the form load.
This separates the responsability of finding the labels from reading the file (which is external to the program). Allowing you to test if it can find the right controls without the need of a file.
It will also make the case where the Label is not found visible (we just added a null to the dictionary).
And then use it:
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
label = labels[labelName];
label.Text = tnsop[o];
}
The code above should throw NullReferenceException if the label was not found while building the dictionary.
Simplify
I guess we can do better. The designer will create fields for your labels, you can just add them to the dictionary:
Dictionary<string, Label> labels;
// ...
labels = new Dictionary<string, Label>();
labels["h2a"] = h2a;
labels["h3a"] = h3a;
labels["h4a"] = h4a;
labels["h5a"] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
string labelName = string.Format("h" + o.ToString() + "a");
label = labels[labelName];
label.Text = tnsop[o];
}
Note: There are plenty of opportunities for more modern syntax, including collection initialization and the var keyword.
Addendum: I am unrolling the loop in the above code, this is ok for maintainability if the number of iterations small, in fact, it is a common optimization. You could, in theory do it for the other loop too.
PS. An array will do
I noticed, after finishing writing, that the code only needs to look up by an int o.
We can rework to use int for dictionary keys:
Dictionary<int, Label> labels;
// ...
labels = new Dictionary<int, Label>();
labels[2] = h2a;
labels[3] = h3a;
labels[4] = h4a;
labels[5] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
label = labels[o];
label.Text = tnsop[o];
}
Now we have less concatenations, and a simpler code.
We could, in fact, be using an array:
Label[] labels;
// ...
labels = new Label[4];
labels[0] = h2a;
labels[1] = h3a;
labels[2] = h4a;
labels[3] = h5a;
// ...
string[] tnsop = System.IO.File.ReadAllLines(#adqien);
for (int o = 2; o < 6; o++)
{
label = labels[o - 2];
label.Text = tnsop[o];
}
Notice I did offset the indexes to be able to use the array from index 0.

Only one item appearing on Listview

I need to make a list of products with their respective icons above but it only appears one item. There are 20 products total. How can I insert the other 19 items?
Code:
ImageList imageList = new ImageList();
prodview.LargeImageList = imageList;
while (i < 20)
{
var json = c.DownloadString(url + (i + 1).ToString());
var image = c.DownloadData(urlicon + (i + 1).ToString());
var dataDict = JsonConvert.DeserializeObject<List<Data>>(json);
ListViewItem item = new ListViewItem();
foreach (var data in dataDict)
item.Text = data.name;
imageList.ImageSize = new Size(100, 100);
imageList.Images.Add(i.ToString(), new Bitmap(new MemoryStream(image)));
item.ImageIndex = i;
prodview.Items.Add(item);
i++;
}
This version of the code already works. Answer below.
Your logic has issues
for i = 0 to 19 ..
download data/string create new list item create new image list
foreach item in datadict set item.text
add 1 image to imagelist
for all items currently in image list (aka 1) add it to prodview
rpt.
so you only end up with 1 item, as you remade item list each time, and each variable each time.
you almost certainly want something like:
ImageList imageList = new ImageList();
to be before the while loop. The below doesnt need to be in a loop either - otherwise its repeating.
prodview.LargeImageList = imageList;
item.ImageIndex = i;
prodview.Items.Add(item);
There maybe other issues - such as im not convinced about the images but.. start there
Adjusting my code some..
Your code probably should end up like
ImageList imageList = new ImageList();
prodview.LargeImageList = imageList;
while(i <20)
{
var json = c.DownloadString(url + (i + 1).ToString());
var image = c.DownloadData(urlicon + (i + 1).ToString());
var dataDict = JsonConvert.DeserializeObject<List<Data>>(json);
ListViewItem item = new ListViewItem();
// not sure what you were trying to do here as it would always end up with the last name..
// foreach (var data in dataDict)
// item.Text = data.name;
item.Text = "item "+i; // giving it a name
imageList.ImageSize = new Size(100, 100);
imageList.Images.Add(i.ToString(), new Bitmap(new MemoryStream(image)));
item.ImageIndex = i;
prodview.Items.Add(item);
i++;
}

accessing dynamically created controls C#

I have been reading for a bit and found some things close, but not anything works in my case. The user has a settings file that they use and I read it into the Windows form. One tab has 2 standard columns but then there can be any number more after those two which have different labels and listbox names that are based on the label (i.e. if the label is "portland" the corresponding listbox is "lstportland" but these names WILL vary). There are created in the is part of the settings file import method, on the fly:
for (int i = 3; i < (lastColumn); i++)
{
//creates new list box and names it the column name with a "lst" infront of it
var cellVal = squidSheet.Cells[1, i].Value;
string convertString = cellVal.ToString();
string listBoxName = "lst" + convertString;
int lbLocation = new int();
/*where to place the next label/listbox on the sheet based on a placement point if its the first one
*it is placed in a specific spot, then each subsequent one is placed equidistant from the last.*/
if (i==3)
{ lbLocation = 382; }
else
{ lbLocation = 382 + (115*(i-3)); }
//create the properties for the new listbox and label in its proper place on the "Run Tab"
ListBox listBox1 = new ListBox();
Label label1 = new Label();
listBox1.Name = listBoxName;
listBox1.Height = 316;
listBox1.Width = 94;
listBox1.Location = new Point(lbLocation, 30);
label1.Location = new Point(lbLocation, 14);
label1.Text = convertString;
label1.Name = "lbl" + convertString;
label1.Font = new Font("Microsoft Sans Serif", 8, FontStyle.Regular);
//add the new listbox and label to the Form
tabPage4.Controls.Add(listBox1);
tabPage4.Controls.Add(label1);
//fill the new list box
string colIdString = TestCase((i-1).ToString());
fillListBox(listBox1, lastRowRunList, squidSheet, colIdString);
}
In a Later method, I need to read the items of each listbox created on the fly, into its own array or somehow access the items in the listbox itself. I have sketched the following but it doesn't work. Any ideas?
for (int l = 2; l < (listBoxNames.Count); l++)
{
string variableNameString = labelText[l].ToString();
string variableNames = "#" + variableNameString + "#";
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
string variableValues = listboxTest.Items[(l-1)].ToString();
readText = readText.Replace(variableNames, variableValues);
}
The control isn't being found because you are searching the Form's Controls() collection, instead of its actual container, tabPage4.
Change:
ListBox listboxTest = Controls[("lst" + variableNameString)] as ListBox;
To:
ListBox listboxTest = tabPage4.Controls[("lst" + variableNameString)] as ListBox;
Or search for the control as in the link provided by drzounds in the comments.

Create control in runtime

I can't manage to get the values from textboxes that are created at run-time.
I want an user to choose something from a checkedlistbox, and to enter any values he wants in textboxes that are created at every button click.
How can I get the name of those texboxes? They really exist? I am a beginner and I really don't understand how they are created.
This is my code where I create textboxes.
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int x = 466;
int y = 84;
foreach (var itemChecked in checkedListBox1.CheckedItems)
{
int i = 0;
TextBox tb = new TextBox();
tb.Location = new Point(x, y);
tb.Name = "txtBox" + i++.ToString();
Controls.Add(tb);
y += 30;
}
just place the i outside the foreach and done.
int i = 0;
foreach (var itemChecked in checkedListBox1.CheckedItems)
{
i++;
string textBoxName = "textBox" + i.ToString();
TextBox tb = new TextBox();
tb.Location = new Point(x, y);
//tb.Name = "txtBox" + i++.ToString(); <--Your Version
tb.Name = textBoxName;
//...
//Other stuff or your codes
}
Rather than searching for exact name what you can do is have a string(fixed) which is searched for the control.
so if you find that string ( in your case which is 'textbox' ), what you can do is search for that fixed string in the name of control. if it exists then it's dynamically generated control.
foreach(Control c in parentControlIdOrName.Controls)
{
if(c.GetType()==typeof(TextBox))
{
if(((TextBox)c).Name.indexOf("textbox")!=-1)
{
// do your coding here...what ever you want....
}
}
}
Haven't tested but,Hope for the best. It might work.

Categories

Resources