I want to set up a for loop to change the content of pictureboxes with using like picturebox[i] but I can't figure out how to do that.
My idea was doing something like this, the whole code snippet has a lot of if statements but is similar to this.
for (int i = 0; i < length; i++)
{
pictureBox[i].image = Image.FromFile("../Pics/Salmon.jpg");
}
I don't know how to do it and I cant' find anyone with the same problem. Is there any way how to do this? Or do I have to manually do it.
You can prepare collection first and then iterate it:
var pictureBox = new[] { pictureBox1, pictureBox2, ... };
for (int i = 0; i < pictureBox.Length; i++)
pictureBox[i].Image = Image.FromFile("../Pics/Salmon.jpg");
You can use same approach to have different pictures, I'll let it for you as a kind of exercise ;)
You can't access the PictureBox controls in an array. They are part of the overall control collection on a form. You can loop through all the controls on a form and only act on the picture boxes.
Example:
foreach (Control ctrl in this.Controls)
{
if (ctrl is PictureBox picBox) //determine if the control is a picture box
{
picBox.Image = Image.FromFile("../Pics/Salmon.jpg");
}
}
Or using Linq:
this.Controls.OfType<PictureBox>().ToList()
.ForEach(p => p.Image = Image.FromFile("../Pics/Salmon.jpg"));
Or if you have to act on based on posistion array:
var pics = this.Controls.OfType<PictureBox>().ToArray();
for (int i = 0; i < pics.Length; i++)
{
pics[i].Image = Image.FromFile("../Pics/Salmon.jpg");
}
Related
I'm trying to reverse the order of Controls in a FlowLayoutPanel.
I tried converting the ControlCollection to an array and then reversed that and cleared the ControlCollection and then readded the Controls. But this doesn't seem to have the planned effect.
Here's the code I use:
private static void ReverseLayout(Control control, bool suspend = true) {
if (suspend) control.SuspendLayout();
Control[] newCC = new Control[control.Controls.Count];
control.Controls.CopyTo(newCC, 0);
Array.Reverse(newCC);
control.Controls.Clear();
//control.Controls.AddRange(newCC);
for (int i = 0; i < newCC.Length; i++) {
newCC[i].Location = new System.Drawing.Point(); // maybe? no :\
newCC[i].TabIndex = i; // maybe? no :\
control.Controls.Add(newCC[i]);
}
if (suspend) control.ResumeLayout(false);
}
Your code seems more complicated than it needs to be. Try putting the controls in a List<Control> and then call reverse on it, put the collection back:
int firstTabIndex = flp.Controls[0].TabIndex;
List<Control> controls = flp.Controls.Cast<Control>().ToList();
flp.Controls.Clear();
controls.Reverse();
flp.Controls.AddRange(controls.ToArray());
For the TabIndex property, you would have to reapply the value:
for (int i = 0; i < flp.Controls.Count; ++i) {
flp.Controls[i].TabIndex = firstTabIndex + i;
}
Is it possible to set a components visible attribute based on its name?
I have 12 "master" components (comboboxes) if you want to call them that and based on the selection in these I want to display anywhere from 1 to 16 textboxes. These are named in numeric order such as combobox1_textbox_0, combobox1_textbox_1 and so on. What I would like to do ideally is take the index of the combobox and pass it as a parameter to a method that sets the textboxes visible attribute to visible/hidden depending on the index passed into the method.
Is this possible? in pseudocode or what you call it I would like it to work something like this:
private void methodToSetVisibleAttribute(int indexFromMainComboBox)
{
for(int i = 0; i < 15; i++)
{
if(i < index)
{
combobox1_textbox_+i.Visible = true;
}
else
{
combobox1_textbox_+i.Visible = false;
}
}
}
I could do panels or something for the choices but seeing as all the selections from the combobox will use the same textboxes but in different amounts it seems like alot of work to make a panel for every possible selection not to mention difficult to expand the program later on.
Assuming you are using Windows Forms and not WPF, you can use ControlCollection.Find() to find controls by name:
var textBox = this.Controls.Find(string.Format("combobox1_textbox_{0}", i), true).OfType<ComboBox>().FirstOrDefault();
if (textBox != null)
textBox.Visible = (i < index);
else
Debug.Assert(false, "textbox not found"); // Or throw an exception if you prefer.
I'll suggest an alternative to your approach, maybe not quite what you're looking for:
Place your combo boxes in a List<ComboBox> and you can access them by an index number.
List<ComboBox> myCombos = new List<ComboBox>();
for (int i = 0; i < 16; i++)
{
ComboBox cb = new ComboBox();
//do what ever you need to do here. Set its location, add items, etc.
Form1.Controls.Add(cb); //Alternatively add it to another container.
myCombos.Add(cb); //Now it's in a list.
}
Modify them like this:
for(int i = 0; i < 15; i++)
{
if(i < index)
{
myCombos[i].Visible = true;
}
else
{
myCombos[i].Visible = false;
}
}
Or even more succintly:
for(int i = 0; i < 15; i++)
{
myCombos[i].Visible = i < index;
}
im looping on 24 picturebox on groupbox for displaying something, but it doesn't loop in the right order, it may start at the 18th picture box and here is the code im using
foreach (var pb in groupBox1.Controls)
{
if (pb is PictureBox && previewIndexer < Previewer.Count)
{
try
{
((PictureBox)pb).Image = ...
previewIndexer++;
...
}
catch
{
...
}
}
}
i would want to loop in ascending order of which it loops on picturebox1 first till picturebox24, thanks and have wonderful day
Your problem is ordering controls by name. You need alphanumeric sorting in order to picturebox10 go after picturebox5. This can be done if you will sort pictureboxes by numbers in their names:
foreach (var pb in groupBox1.Controls.OfType<PictureBox>()
.OrderBy(x => Int32.Parse(x.Name.Substring("picturebox".Length))))
{
pb.Image = ...;
}
I would even created some method like (it removes all non-numeric characters from control name and tries to parse rest to integer value):
private int GetControlId(Control control)
{
int id;
string idToParse = Regex.Replace(control.Name, #"\D+", "");
return Int32.TryParse(idToParse, out id) ? id : 0;
}
And used this method in query
var pictureBoxes = groupBox1.Controls.OfType<PictureBox>();
foreach (var pb in pictureBoxes.OrderBy(GetControlId))
{
pb.Image = ...;
}
You can take benefit of LINQ here, suppose you named your pictureboxes as picture1, picture2, ...
foreach (var pb in groupBox1.Controls.OfType<PictureBox>().OrderBy(p=>int.Parse(Regex.Replace(k,"\\D*",""))))
{
if(previewIndexer < Previewer.Count) {
try
{
((PictureBox)pb).Image = ...
previewIndexer++;
...
}
catch
{
...
}
}
}
You can index the Controls property with a string which refers to the name of the control.
This might be the simpliest solution:
for (int i = 1; i <= 24; i++)
{
PictureBox pb = groupBox1.Controls["picturebox" + i.ToString()] as PictureBox;
}
I have ten labels on a page. I want to make these invisible in a for loop on page load.
I have tried this (doesn't work):
for (int i = 0; i < 10; i++)
{
my_lbl+i.Visible = false;
}
Therefore, it should do:
my_lbl1.Visible = false;
my_lbl2.Visible = false;
my_lbl3.Visible = false;
my_lbl4.Visible = false;
etc...
Is there a way to do this?
Put all of the labels into a collection:
private List<Label> labels = new List<Label>{my_lbl1, my_lbl2, my_lbl3, my_lbl4};
Then you can iterate the whole collection:
foreach(var label in labels)
label.Visible = false;
Make a List of them;
List<Label> yourlabels = new List<Label>{my_lbl1, my_lbl2, my_lbl3...};
and use foreach loop making them visible.
foreach(var label in yourlabels)
{
label.Visible = false;
}
I don't know if there is a better way but this way seems logical to me.
Putting the labels in a collection (as the previous answers have suggested) is a great solution. You can also retrieve the controls by their name using FindControl method of the Page.
for (int i = 0; i < 10; i++)
{
this.FindControl("my_lbl" + i.ToString()).Visible = false;
}
I guess you can utillize Page's FindControl method:
for (int i = 0; i < 10; i++)
{
FindControl(string.Format("my_lbl{0}", i)).Visible = false;
}
But check the case if control is not found of course.
Or, you can put them into dictionary:
Dictionary<string, Label> nameOfDict = new Dictionary<string, Label>();
nameOfDict.Add("label1", label1);
nameOfDict.Add("label2", label2);
For...
nameOfDict ["label" + incrementator].visible = false;
Or, create them dynamically into an array of labels.
If you're sure that, let's say, you want to uncheck all checkboxes in a groupbox, you can do this, too:
foreach (var item in groupBox1.Controls)
{
if (item.GetType() == typeof(CheckBox))
{
((CheckBox)item).Checked = true;
}
}
with LINQ:
foreach (var item in groupBox1.Controls.Cast<object>().Where(item => item.GetType() == typeof(CheckBox)))
{
((CheckBox)item).Checked = true;
}
I have many pictureboxes in my project and would like to know if there is code that makes it easy to switch between them in C#, for example:
// I dont' want to have to do this all the time
pictureBox38.Image = slagalica.Properties.Resources.grn_tick;
pictureBox39.Image = slagalica.Properties.Resources.grn_tick;
// I want something like this
int n = 38
pictureBox(n).Image = slagalica.Properties.Resources.grn_tick;
pictureBox(n+1).Image = slagalica.Properties.Resources.grn_tick;
Is it possible? Any code is welcome.
You can loop through all controls and apply settings to those, which are pictureboxes:
foreach(Control control in Controls)
{
if (control is PictureBox)
((PictureBox)control).Image = slagalica.Properties.Resources.grn_tick;
}
Or you can create your custom picturebox and use it instead of default pictureboxes:
public class SlagalicaPictureBox : PictureBox
{
public SlagalicaPictureBox()
{
Image = slagalica.Properties.Resources.grn_tick;
}
}
You might want to create list of Picture boxes. Then you will be able to write something like pictureBoxes[0].Image=img;
Definitely consider what Lazyberezovsky posts. However, if you want to iterate through controls rapidly, you can also construct a control array.
You can easily do this:
List<PictureBox> list = new List<PictureBox>();
list.Add(pictureBox38);
list.Add(pictureBox39);
Then you can iterate through them as follows:
foreach (PictureBox pb in list) {
pictureBox.Image = slagalica.Properties.Resources.grn_tick;
}
If you want to be more clever, you can even create an array with a specified size and do the same.
PictureBox[] pb_array = new PictureBox[50];
pb_array[38] = pictureBox38;
Add them to a list and use the indexer, for example a List<PictureBox> or PictureBox[]:
var dir = new System.IO.DirectoryInfo(imagePath);
List<FileInfo> images = dir.GetFiles("*.jpg", System.IO.SearchOption.AllDirectories).ToList();
List<PictureBox> pictures = new List<PictureBox>();
foreach (FileInfo img in images) {
PictureBox picture = new PictureBox();
picture.Image = Image.FromFile(img.FullName);
pictures.Add(picture);
}
Now you ca access the pictures by index, for example:
var rnd = new Random();
int imgIndex = rnd.Next(0, 38);
PictureBox img = pictures[imgIndex];
Or in a loop
for(int i=0; i<38; i++)
{
PictureBox img = pictures[i];
}
Edit: If you just want to find all PictureBoxes on your form, you can use Enumerable.OfType which filters and casts the controls accordingly:
IEnumerable<PictureBox> allPictures = this.Controls.OfType<PictureBox>();
foreach(var pic in allPictures)
{
//....
}
while(n <= (number of pics)){
n++
pictureBox(n).Image = slagalica.Properties.Resources.grn_tick;
}
Yes i know this is Objective-C, but you get the main idea