Im using Visual Studio Community with the Windows Forms template, and was wondering if there is a way to reference a newly created pcb when created during runtime like shown in code:
for (int i = 0; i <= mapSize - 1 && !foundPos; i++)
{
for (int j = 0; j <= mapSize - 1 && !foundPos; j++)
{
var pcb = new PictureBox();
pcb.Name = "pcb" + i + "" + j;
pcb.Margin = new Padding(0);
pcb.Size = new Size(slotSize, slotSize);
pcb.Location = new Point(0 + i * slotSize, 0 + j * slotSize);
if (currMap[i, j] == 5)
pcb.BackColor = Color.Yellow;
if (currMap[i, j] == 0)
pcb.BackColor = Color.White;
if (currMap[i, j] == 1)
pcb.BackColor = Color.Gray;
this.Controls.Add(pcb);
}
}
this.pcb00.BackColor = Color.Yellow; // A way to reference the pictureboxes just made?
i gave the picturebox a name when i created it and tried using the name of the picturebox like normal.
Im using Visual Studio Community with the Windows Forms template, and was wondering if there is a way to reference a newly created pcb when created during runtime like shown in code:
for (int i = 0; i <= mapSize - 1 && !foundPos; i++)
{
for (int j = 0; j <= mapSize - 1 && !foundPos; j++)
{
var pcb = new PictureBox();
pcb.Name = "pcb" + i + "" + j;
pcb.Margin = new Padding(0);
pcb.Size = new Size(slotSize, slotSize);
pcb.Location = new Point(0 + i * slotSize, 0 + j * slotSize);
if (currMap[i, j] == 5)
pcb.BackColor = Color.Yellow;
if (currMap[i, j] == 0)
pcb.BackColor = Color.White;
if (currMap[i, j] == 1)
pcb.BackColor = Color.Gray;
this.Controls.Add(pcb);
}
}
this.pcb00.BackColor = Color.Yellow; // A way to reference the pictureboxes just made?
i gave the picturebox a name when i created it and tried using the name of the picturebox like normal.
Share Improve this question asked Feb 7 at 12:56 Spell CinSpell Cin 151 silver badge3 bronze badges 2 |2 Answers
Reset to default 2You'll need to either keep a reference to the variable created or perform operations on the Controls container it's in to find it later. In my own application I have a custom control, and I keep a dictionary<string, MyCustomControl> that I add the generated controls to for easier access.
See the answers here for information on using either this.Controls.Find() or this.Controls[name] to find the control if needed.
You're doing the right thing by naming the PictureBox controls before adding them to this.Controls
. You don't need to do anything else, thanks to the string indexer of the Controls
collection, just refer to a control (for example) as Controls["pcb01"]
as shown in the working minimal example below.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// Set some values so example can compile
const int mapSize = 3, slotSize = 100;
bool foundPos = false;
int[,] currMap = new int[mapSize, mapSize];
// ========================================
for (int i = 0; i < mapSize && !foundPos; i++)
{
for (int j = 0; j < mapSize && !foundPos; j++)
{
var pcb = new PictureBox
{
Name = $"pcb{i}{j}",
Size = new Size(slotSize, slotSize),
Location = new Point(0 + i * slotSize, 0 + j * slotSize),
BackColor = Color.LightBlue,
};
pcb.Left += 50;
pcb.Top += 50;
// Skip the colors so this example can set them below
this.Controls.Add(pcb);
pcb.BorderStyle = BorderStyle.FixedSingle;
Debug.WriteLine(pcb.Name);
}
}
Controls["pcb00"].BackColor = Color.White;
Controls["pcb01"].BackColor = Color.Gray;
Controls["pcb12"].BackColor = Color.Yellow;
}
}
That said, I agree with Jimi's comment that you might greatly benefit from a TableLayoutPanel
.
TableLayoutPanel Minimal Example
public partial class MainForm : Form
{
TableLayoutPanel currMap;
public MainForm()
{
InitializeComponent();
const int DIM = 3;
Padding = new Padding(25);
currMap = new TableLayoutPanel
{
Dock = DockStyle.Fill,
RowCount = DIM,
ColumnCount = DIM,
BackColor = Color.LightBlue,
Padding = new Padding(2),
};
Controls.Add(currMap);
int autoIncrement = 0;
for (int col = 0; col < DIM; col++)
{
currMap.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1));
currMap.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
for (int row = 0; row < DIM; row++)
{
var pcb = new SmartSquare
{
Name = $"pcb{col}{row}",
ValueForDemo = autoIncrement++,
};
currMap.Controls.Add(pcb, col, row);
}
}
}
}
In this case, there are at least two answers to the question:
Is there a way to reference a picturebox just created and added during runtime?
currMap.Controls["pcb20"].BackColor = Color.Red;
currMap.GetControlFromPosition(2,1).BackColor = Color.Green;
I would take it a step further and recommend that you inherit PictureBox
to make something like SmartSquare
, a custom PictureBox
that might (for example) know what color it's supposed to be based on the ValueForDemo
property.
SmartSquare
Minimal Example
class SmartSquare : PictureBox
{
public SmartSquare()
{
Margin = new Padding(2);
Dock = DockStyle.Fill;
BorderStyle = BorderStyle.FixedSingle;
}
public int ValueForDemo
{
get => _valueForDemo;
set
{
if (!Equals(_valueForDemo, value))
{
_valueForDemo = value;
switch (_valueForDemo)
{
case 0:
BackColor = Color.White;
break;
case 1:
BackColor = Color.Gray;
break;
case 5:
BackColor = Color.Yellow;
break;
default:
BackColor = Color.Transparent;
break;
}
}
}
}
int _valueForDemo = int.MinValue;
}
SmartSquare
Demo
Using your examples of {5, 0, 1}
:
PictureBox
in this case) as instance of any other class around. The winform designer creates a property for you. Since you need indexing, consider creating property of type which supports indexes, likecurrMap
, e.g. arrayPictureBox[,]
– Sinatr Commented Feb 7 at 13:28GetPositionFromControl()
) etc. You also allow the parent Form to scale as required, without messing up the layout of your Controls – Jimi Commented Feb 7 at 13:36