How switch between pictureboxes? - c#

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

Related

dynamically created labels overlap each other

I want to create labels that will follow one another. I have a grid name WordTemplateLayout to which I want to add the labels. I add them dynamically on the wpf window constructor after InitializeComponent() is called. Here is the method creating the labels:
private void CreateWordTemplate()
{
IList<char> template = CurrentGame.Template;
double widthPerBox = WordTemplateLayout.Width / template.Count;
//template.Count being a number, irrelevant to the question
for (int i = 0; i < template.Count; i++)
{
var templateVisual = new Label();
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
WordTemplateLayout.Children.Add(templateVisual);
}
}
the problem being, that what actually appends is that instead of the labels lining up one after the other, they overlap each other:
The aqua box is all the labels overlap each other
so what I am asking, is how can I make the labels line up (horizontally) instead of to overlap?
As others have pointed out, you're better off using a StackPanel, or learning how to use viewmodels and data binding. Having said that, to answer your direct question, here's how you'd do it programmatically.
**NOTE: Ignore the 5 that I'm passing in to the methods, and instead use your template.Count. This is was just for me to get it to work on my end.
public MainWindow()
{
InitializeComponent();
CreateGridLayout(5);
CreateWordTemplate(5);
}
// Define the Grid layout
// If you want the labels to follow one another horizontally, define columns.
// If you want them stacked vertically, instead define rows.
private void CreateGridLayout(int count)
{
for (int i = 0; i < count; i++)
{
WordTemplateLayout.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private void CreateWordTemplate(int count)
{
double widthPerBox = WordTemplateLayout.Width / 5;
for (int i = 0; i < 5; i++)
{
var templateVisual = new Label();
templateVisual.SetValue(Grid.ColumnProperty, i); // SET YOUR COLUMN HERE!
templateVisual.Name = "c" + i;
templateVisual.Width = widthPerBox;
templateVisual.Height = WordTemplateLayout.Height;
templateVisual.Background = new SolidColorBrush(Colors.Aqua);
templateVisual.Content = templateVisual.Name;
WordTemplateLayout.Children.Add(templateVisual);
}
}
you need to use another layout so the new elements will get in normal order. try stackPanel.
you can use grid and give each new label Row=index.
you can give each new label margin, like newLabel.margin-top = index*50

Changing picturebox #N

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");
}

looping on parent controls in order

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;
}

How can I use variables on variable name?

for (int f = 1; f <= 6; f++)
{
textBox{f+11} = (loto[f].ToString());
}
Hi again,
I'm trying to learn c# on my own. Sorry for this noobish questions :)
To be more spesific, that's what I want :
A shortcut to write codes like that :
textBox12.Text = loto[1].ToString();
textBox11.Text = loto[2].ToString();
textBox10.Text = loto[3].ToString();
textBox9.Text = loto[4].ToString();
textBox8.Text = loto[5].ToString();
textBox7.Text = loto[6].ToString();
This code is working but i want to write it in a for loop
You can use a dictionary.
Dictionary<int, TextBox> dictionary = new Dictionary<int, TextBox>();
dictionary.Add(1, textbox1);
... // add the other textboxes
// access the dictionary via index
dictionary[f+11] = ...
You could use a List<TextBox> and initialise it in the constructor, after the call to InitialiseComponent() that you will see in the constructor.
Here's how:
Firstly add to your form class a List<TextBox> as follows:
private List<TextBox> textboxes = new List<TextBox>();
Then initialise the list in your constructor something like this (change Form1 to the name of your form's constructor):
public Form1()
{
// ...
InitializeComponent();
// ...
textboxes.Add(textBox1);
textboxes.Add(textBox2);
textboxes.Add(textBox3);
// ...etc up to however many text boxes you have.
}
Then when you want to access the textboxes, you can do so like this:
for (int f = 1; f <= 6; ++f)
{
textboxes[f+11].Text = loto[f].ToString(); // From your example.
}
I'm not sure if your TextBox controls are already on your form. If not and you wanted to create your TextBox controls dynamically, you could do something like this:
for (int f = 1; f <= 6; f++)
{
Dictionary<int, TextBox> dict = new Dictionary<int, TextBox>();
dict.Add(f, new TextBox());
dict[f].Location = new Point(0, f * 20);
dict[f].Text = loto[f].ToString();
this.Controls.Add(dict[f]);
}
You can't. You have to store them in a list of dictionary and access them this way. So
add controls to list/dictionary
in your for loop, access them by index

How to write a list of array in a for loop?

Hi I neeed to do this one in a loop, but I don't have any idea how to do. I can't do this by just simply incrementing it.
CheckBox[] checkboxarray;
checkboxarray = new CheckBox[] {
txtChckBx0, txtChckBx1, txtChckBx2, txtChckBx3, txtChckBx4, txtChckBx5,
txtChckBx6, txtChckBx7, txtChckBx8, txtChckBx9, txtChckBx10, txtChckBx11,
txtChckBx12, txtChckBx13, txtChckBx14, txtChckBx15, txtChckBx16, txtChckBx17,
txtChckBx18, txtChckBx19, txtChckBx20, txtChckBx21, txtChckBx22, txtChckBx23,
txtChckBx24, txtChckBx25, txtChckBx26, txtChckBx27, txtChckBx28, txtChckBx29,
txtChckBx30, txtChckBx31, txtChckBx32, txtChckBx33, txtChckBx34, txtChckBx35,
txtChckBx36, txtChckBx37, txtChckBx38, txtChckBx39, txtChckBx40, txtChckBx41,
txtChckBx42, txtChckBx43, txtChckBx44, txtChckBx45, txtChckBx46, txtChckBx47,
txtChckBx48, txtChckBx49, txtChckBx50, txtChckBx51, txtChckBx52, txtChckBx53,
txtChckBx54, txtChckBx55, txtChckBx56, txtChckBx57, txtChckBx58, txtChckBx59,
txtChckBx60, txtChckBx61, txtChckBx62, txtChckBx63, txtChckBx64, txtChckBx65,
txtChckBx66, txtChckBx67, txtChckBx68, txtChckBx69, txtChckBx70, txtChckBx71,
txtChckBx72, txtChckBx73, txtChckBx74, txtChckBx75, txtChckBx76, txtChckBx77,
txtChckBx78, txtChckBx79, txtChckBx80
};
If you know that the checkboxes are all on a form:
var list = new List<CheckBox>();
foreach(var control in this.Controls)
{
var checkBox = control as CheckBox;
if(checkBox != null)
{
list.Add(checkBox);
}
}
var checkBoxArray = list.ToArray();
If you don't know where the controls are then you will have to search for them.
BTW: The code above uses WinForms. If you are using WPF, Silverlight, Metro,... the container will be named differently.
You can't do new and then
checkboxarray = new CheckBox[] { txtChckBx0, ....}
it's two different ways to define an array.
you need to do:
CheckBox[] checkboxarray = { txtChckBx0, ....};
If you want it to work.
Good luck.
In WinForm
List<CheckBox> checkBox = new List<CheckBox>();
// Adding checkboxes for testing...
for (int i = 0; i <= 80; i++)
{
var cbox = new CheckBox();
cbox.Name = "txtChckBx"+ i.ToString();
checkBox.Add(cbox);
Controls.Add(cbox);
}
List<CheckBox> checkBoxfound = new List<CheckBox>();
// loop though all the controls
foreach (var item in Controls)
{
// filter for checkboxes and name should start with "txtChckBx"
if (item is CheckBox && ((CheckBox)item).Name.StartsWith("txtChckBx", StringComparison.OrdinalIgnoreCase))
{
checkBoxfound.Add((CheckBox)item);
}
}

Categories

Resources