This question already has answers here:
Loop through Textboxes
(12 answers)
Closed 8 years ago.
I have a form with a tabbed control (5 tabs) and on one tab I have 10 picture boxes, named pic1, pic, pic3 and so on. In VBA it is possible to loop through the controls using something like this:
For i = 1 To 10
Me.Controls("Img" & i).Picture = Me.cboProperty.Column(i)
Next
At the moment I have
this.pic1.DataBindings.Add("ImageLocation", this.mainTableBindingSource, "localPic1");
this.pic2.DataBindings.Add("ImageLocation", this.mainTableBindingSource, "localPic2");
this.pic3.DataBindings.Add("ImageLocation", this.mainTableBindingSource, "localPic3");
until 10, but surely there is a better way?
Like that, no. Normally, you would acceess a group of controls like this:
foreach (var pictureBox in PictureTab.Controls.OfType(Of PictureBox)())
{
pictureBox.Picture = //...
}
Of course, the trick here is that there is no index, to know which column to look at. But that's easy enough to get around:
int i = 0;
foreach (var pictureBox in PictureTab.Controls.OfType<PictureBox>())
{
pictureBox.Picture = cboProperty.Column[i];
i++;
}
Based on your edit, you may want this:
int i = 0;
foreach(var pictureBox in PictureTab.Controls.OfType<PictureBox>())
{
picutreBox.DataBindings.Add("ImageLocation", mainTableBindingSource, string.Format("loalPic{0}", i));
i++;
}
Perhaps something like this:
var pictureBoxes = this.Controls.OfType<PictureBox>().ToList();
for (int i = 0; i < pictureBoxes.Count; i++) {
pictureBoxes[i].DataBindings.Add("ImageLocation",
this.mainTableBindingSource,
"localPic" + (i + 1).ToString());
}
You can Search for the name of the pictureBox in form controls and loop increasing the value of each like Pic1, Pic2, etc.
for (int a = 1; a <= 10; a++)
{
string name = "pic" + a;
PictureBox pic = (PictureBox)(this.Controls.Find(name, true))[0];
pic.DataBindings.Add("ImageLocation", this.mainTableBindingSource, "localPic3");
}
iterate through all form controls
List<Control> lstOfControls = new List<Contol>();
public void AllPictureControls(Control control, bool enabled)
{
foreach(Control child in control.Controls)
{
if(child.Name.StartsWith("pic"))
{
lstOfControls.Add(control);
}
}
}
Put references of all your picture controls into a data structure, e.g. an array, and iterate over them.
Something similar to:
PictureBox[] picBoxArray = new PictureBox[50];
// 50 iterations for 50 object instantiations.
for (int i=0; i<picBoxArray.Length; i++) {
// create an pictureBox instance.
picBoxArray[i] = new PictureBox();
}
PictureBox pb = null;
// 50 iterations for calling methods on each of the 50 objects.
for (int i=0; i<picBoxArray.Length; i++) {
pb = picBoxArray[i];
// do something with the picturebox e.g. pb.SetPicture(...)
}
Related
So, we have a way to dynamically create an array of x by y of texboxes to input values into it to later on do some matrix calculation, like determine the rank of the matrix.
To generate the array we use this:
protected void Form2_Load(object sender, EventArgs e)
{
for (int row = 0; row < LinhaText; row++)
{
List<TextBox> newLin = new List<TextBox>();
textboxes.Add(newLin);
for (int col = 0; col < ColunText; col++)
{
TextBox newbox = new TextBox();
newbox.Width = textboxWidth;
newbox.Height = textboxHeight;
newbox.Top = (row * (textboxHeight + spacing)) + spacing + vOffset;
newbox.Left = (col * (textboxWidth + spacing)) + spacing + hOffset;
newLin.Add(newbox);
this.Controls.Add(newbox);
}
}
}
This stands on the second form, as in the first one we input the dimensions of the array. When we input the values on the textboxes they should get sent to the third form to get used by the other calculations.
We are wondering how we grab the values and send them to the other form to later on display the results.
Any further information you need, just ask!
I'm assuming that these are not modal windows and that the user can switch between them at any point? If that is the case then I would suggest using a design pattern like MVC or MVVM, separating your data, view, and control logic. By keeping the data layer distinct from the view, you can have all of your windows (views) share the same underlying data. Of course, you'll want to use events to notify the various windows of when the data is changed (see the INotifyPropertyChanged Interface).
I would not pass around textboxes, instead store the numbers in a 2-dimensional array (matrix). Also I would use binding to automatically bind the matrix values to the textboxes. To make binding work, you need a helper class containing your values, because binding needs to bind to a property.
private class Data // Can be a nested private class in Form2.
{
public double Value { get; set; }
public override string ToString() => Value.ToString(); // Not strictly necessary, but
// makes debugging easier.
}
We create a _matrix field as well as a property converting this Data[,] matrix to a double[,] matrix and returning it (in Form2):
private Data[,] _matrix;
public double[,] Matrix
{
get {
var m = new double[LinhaText, ColunText];
for (int row = 0; row < LinhaText; row++) {
for (int col = 0; col < ColunText; col++) {
m[row, col] = _matrix[row, col].Value;
}
}
return m;
}
}
Now create the textboxes and bind them to a Data object (In Form2_Load or in the form constructor after InitializeComponent):
_matrix = new Data[LinhaText, ColunText];
for (int row = 0; row < LinhaText; row++) {
for (int col = 0; col < ColunText; col++) {
var newbox = new TextBox {
Width = textboxWidth,
Height = textboxHeight,
Top = (row * (textboxHeight + spacing)) + spacing + vOffset,
Left = (col * (textboxWidth + spacing)) + spacing + hOffset
};
// Create Data object, add it to the matrix and bind it to the TextBox.
var data = new Data();
_matrix[row, col] = data;
newbox.DataBindings.Add(new Binding("Text", data, "Value", true));
Controls.Add(newbox);
}
}
Note that binding works two way. If you initialize the matrix with numbers, they will be displayed in the textboxes when opening the form. Numbers entered in textboxes will be stored in the matrix.
Now, on the other form, you need a reference to this form. Then you can get the matrix with
double[,] matrix = frmMartixInput.Matrix;
If you have difficulties passing around form references, then use a static property in a static class for the matrix, that can be referenced by all the forms.
public static class Globals
{
public static double[,] Matrix { get; set; }
}
You can also pass data to a form through constructor parameters (either a reference to another form or the matrix itself).
I'm not sure if the title is correct because I wasn't sure how to explain it. I've encountered many scenarios where being able to dynamically modify part of a variable name such a suffixing integer could save me a great deal of time and keep my code much cleaner but I'm not sure how to do it. Here's an example of my most recent encounter.
I have 9 PictureBox's in a 3 x 3 grid. Each PictureBox has a name of cell followed by it's number so cell1, cell2, cell3 etc. I want to get the background colour of each of these cells and assign them to a variable whilst converting them to strings... something like this:
for (int i = 1; i < 10; i++)
{
string ci = celli.BackColor.ToString();
}
Is there a way I can have the i variable insert only it's numeric value to the placeholder rather than appending an i to the variable name? Can I wrap it in some sort of bracket? I've tried Googleing this but I'm finding it difficult to search for using just keywords.
Thanks in advance.
You are probably using a visual form editor, the best way to do this whould probably be to generate the grid by code (and not visually).
Another solution is to make it a matrix:
PictureBox[,] cell = new PictureBox[,] {
{ cell1, cell2, cell3 },
{ cell4, cell5, cell6 },
{ cell7, cell8, cell9 }
};
string[,] c = new string[3, 3];
for(int y=0; y<3; y++)
for(int x=0; x<3; x++)
c[x, y] = cell[x, y].BackColor.ToString();
Good luck with your code.
You would like to generate a list or collection of all your pictureboxes so that you can access them by specifying their index. One way is to generate the PictureBoxes on runtime:
Like this:
List<PictureBox> myPics = new List<PictureBox>();
int picWidth = 100;
int picHeight = 100;
for (x = 0; x <= this.Width; x += picWidth) {
for (y = 0; y <= this.Height; y += picHeight) {
PictureBox pic = new PictureBox();
pic.Image = pic.Image;
// Your image
pic.Location = new Point(x, y);
this.Controls.Add(pic);
myPics.Add(pic);
}
}
// Do something with myPics...
The other method is that when you do have all the pictureboxes on your form already, you can iterate through all the controls, check which ones are pictureboxes and then check their Name property to identify their index. Then do something with them accordingly.
foreach (void ctrl_loopVariable in this.Controls) {
ctrl = ctrl_loopVariable;
if (ctrl.GetType() == typeof(PictureBox)) {
if (ctrl.Name == "your picture box name to test") {
// Do something here with ctrl
}
}
}
(The above code is converted from VB to C#, excuse conversion issues)
Your intend here is to dynamically reference those controls.
In order to achieve this, there is two options:
You create those controls dynamically
You create dynamic references for the controls created by your form-designer
The first point is explained ny Shreyas Kapur's answer.
The second could be cone like this,
readonly Dictionary<Point,PictureBox> _dynamicMappedBoxes =
new Dictionary<Point,PictureBox>();
// Call this once in the beginning ofr your program
void createDynamicMapping()
{
foreach(PictureBox box in Controls.OfType<PictureBox>())
{
Point coords = getCoordinatesFromName(box);
_dynamicMappedBoxes.Add(coords, box);
}
}
Point getCoordinatesFromName(PictrueBox box)
{
int x = int.Parse(box.Name.SubString(IdontKnow);
int y = int.Parse(box.Name.SubString(IdontKnow);
retrun new Point(x,y);
}
//usage
string colorName = dynamicMappedBoxes[new Point(x,y)].BackColor.ToString();
I was wondering is there a way to run an input form a user as a command without using switch or if statements?
For example if I had a form that contained a 10 by 10 picture frame, and wanted to change its size to 100 by 100. Better yet, is there a way to use a string that is defined in code:
string newString = "";
then change the name of said string: newString = "newButton" + count;
This code would be used like so:
for (int count = 0; count < records) // Records being the count of records to be presented.
{
newString = "newButton" + count;
Button newString.ToString() = new Button();
} //Uses the newString to give ID name to the new buttons.
Some thing similar to this would be using java code to create a table for a servlet using the <tag> and the out_print command.
It seems like maybe you're looking for a Dictionary<T,T>. You could implement your loop idea like this:
var buttons = new Dictionary<string,Button>();
for (int count = 0; count < records)
{
newString = "newButton" + count;
var newButton = new Button();
buttons.Add(newString, newButton);
}
How do I get the info from a certain cell in a data grid? I want an event to happen when a person clicks the button in the 7th column, but the event depends on the value in the first column. here's what i have, but nothing is happening.
if (InventoryDataGridView.CurrentCell.ColumnIndex == 7)
{
if(InventoryDataGridView[0,0].Equals("Books"))
{
Books open = new Books();
open.Show();
}
}
Nothing happens though
InventoryDataGridView[0,0]
only refers to the DataGridViewCell. That class has a Value property which contains the value of the cell.
so that line should look like this:
if(InventoryDataGridView[0,0].Value.Equals("Books"))
{
//
}
If you using WPF then you must try this:
for (int j = 0; j < dataGrid1.Columns.Count; j++)
{
for (int i = 0; i < dataGrid1.Items.Count - 1; i++)
{
string s=(dataGrid1.Items[i] as DataRowView).Row.ItemArray[j].ToString();
}
}
i,j are the co-ordinates. So you can play around it.
reference: http://subrat308.blogspot.in/2012/02/wpf-get-cell-value-from-datagrid-cellij.html
I am new to C#.I have been thinking of adding a ButtonControlArray where i can store each button control.Here is part of my code.I am creating a 6*6 array of button Control.
ButtonControl buttonControl;
ButtonControl[,] arrayButtons = new ButtonControl[6,6];
public void createGrid()
{
l = 0;
for (int i = 0; i < numberOfButtons; i++)
{
for (int k = 0; k < numberOfButtons; k++)
{
buttonControl = new ButtonControl();
buttonControl.Location = new Point(l,j);
j += 55;
arrayButtons[i, k] = buttonControl;
//After the above statement if i print Console.WriteLine(""+arrayButtons[i,k]); i am getting only my projectname.buttoncontrol
myGridControl.Controls.Add(buttonControl);
}
l += 55; j = 10;
}
}
I want to access each variable in arrayButtons[][]..like in a 3*3 matrix..if i want 2nd row 1 column element..then i get something like arrayname[2][1]..same way if i want 2nd button in 2nd row how can i get..i tried doing one way but i couldnt figure it out...Can you help me out with this..
What are you having difficulty with?
If you're running into bounds checking problems, you should know that C# arrays start at zero, not one. So the button in the second row, first column is a[1,0] not a[2,1]
If you Google Control Arrays in C# you will get several good matches, including this one.