c# creating dynamic textbox in a second form - c#

I am trying to write a code in order to create dynamic textboxes.
I have Function class and have a second form in my program named ProductForm.cs
What I wanna do is to read some data with a function named GetSpecs in my Function.cs and than inside GetSpecs I want to call a function in another class and send data to my other function under ProductForm.cs class.
I am getting blank form at the end.
a part of my GetSpecs function:
private String GetSpecs(String webData)
{
......
ProductForm form2 = new ProductForm();
form2.CreateTextBox(n);
}
ProductForm.cs
public void CreateTextBox(int i)
{
ProductForm form2 = new ProductForm();
form2.Visible = true;
form2.Activate();
int x = 10;
int y = 10;
int width = 100;
int height = 20;
for (int n = 0; n < i; n++)
{
for (int row = 0; row < 4; row++)
{
String name = "txtBox_" + row.ToString();
TextBox tb = new TextBox();
tb.Name = name;
tb.Location = new Point(x, y);
tb.Height = height;
tb.Width = width + row * 2;
x += 25 + row * 2;
this.Controls.Add(tb);
}
y += 25;
}
}
I get a blank form of ProductForm. Textboxes are not created or I cannot see them.
If I put textbox inside
private void ProductForm_Load(object sender, EventArgs e)
I can see textboxes.

You're creating showing a brand new ProductForm instance (in the form2 variable), then adding controls to this (which is never shown).

You are adding the controls to the current form: this.Controls.Add(tb);, you need to add them to the other form:
form2.Controls.Add(tb);

Related

Adding value from dynamically created textboxes into array (windows forms)

im making a project for university, for which i use windows forms. i have to create a program, where you can generate an several amount of textboxes and calculate all values. the calcutation is about the sum and average of every value combined. therefore i have two buttons, one to create the textboxes and another one to do the calculation (doTheMath_Click).
heres my code so far:
button for the calculation:
private void doTheMath_Click(object sender, EventArgs e)
{
int radius = int.Parse(numberofnumbers.Text)
int sum = 0;
for (int i = 0; i < zahlen.Length; i++)
{
sum += numbers[i];
}
double average = (double)sum / (double)radius;
total.Text = sum.ToString();
averagee.Text = average.ToString();;
}
int newtextboxn = 8;
int alingment = 200;
public TextBox addnewtextbox()
{
TextBox textbox = new TextBox();
this.Controls.Add(textbox);
if (newtextboxn % 18 == 0)
{
alingment += 200;
newtextboxn = 8;
textbox.Top = newtextboxn * 27;
textbox.Left = alingment;
}
else
{
textbox.Top = newtextboxn * 27;
textbox.Left = alingment;
}
newtextboxn = newtextboxn + 1;
return textbox;
}
button to print the textbox:
public void printTextbox(int radius)
{
for (int i = 0; i < radius; i++)
{
addnewtextbox();
}
}
private void printTheBox_Click(object sender, EventArgs e)
{
int radius = int.Parse(numberofnumbers.Text);
printTextboxandLabels(radius);
}
I had the idea to save the values of the textboxes in an array, but i dont know if it would work, because the array length should also be dynamically and i also dont know, how to initialize the array in the end. My other idea was to save the values in a list, but theres the same problem about the initialization.
i hope, that my problem is understandable and that you can help me.
i already surfed around stackoverflow, but i didnt found an idea to solve my problem.
thx
Just create a List where you store the created set of textboxes. Then you can use the code to loop over this list and retrieve the content of each textbox.
List<TextBox> textboxslist = new List<TextBox>();
and inside addnewtextbox() method fill textboxlist using The Add method.
textboxlist.Add(textbox);
then inside loop code in doTheMath_Click button you can access the values of each textbox by using Text Property.
for (int i = 0; i < textboxlist.Count; i++) {
int textboxvalue = int.Parse(textboxlist[i].Text);
sum += textboxvalue;
}

(C#) Create user control components with for loop and put those components in a list

Of course it's easy to use designer. But, in case for plenty of controls, it hurts to use designer. I'm trying to create a Sudoku table 9 x 9, and need 81 text box with exactly same size. I think, it will be easier to use for loop.
My code so far is like this:
class SudokuTable
{
private List<List<TextBox>> table;
public SudokuTable()
{
initializeComponent();
}
private void initializeComponent()
{
List<List<TextBox>> newTable = new List<List<TextBox>>();
int sz = 30;
int gap = 3;
int x = gap, y = gap;
for (int row = 0; row < 9; row++)
{
x = gap;
List<TextBox> TextBoxes = new List<TextBox>();
for (int col = 0; col < 9; col++)
{
System.Drawing.Size size = new System.Drawing.Size(sz, sz);
System.Drawing.Point location = new System.Drawing.Point(x, y);
System.Drawing.Font font = new System.Drawing.Font("Tahoma", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
TextBox box = new TextBox();
box.Location = location;
box.Size = size;
box.TextAlign = HorizontalAlignment.Center;
box.Font = font;
box.MaxLength = 1;
TextBoxes.Add(box);
x += ((col + 1) % 3 == 0 && (col + 1) < 9) ? sz + gap : sz;
}
newTable.Add(TextBoxes);
y += ((row + 1) % 3 == 0 && (row + 1) < 9) ? sz + gap : sz;
}
table = newTable;
}
public void addSudoku(System.Windows.Forms.Form form)
{
form.SuspendLayout();
foreach (List<TextBox> row in table)
{
foreach (TextBox col in row)
{
form.Controls.Add(col);
}
}
form.PerformLayout();
}
}
And add that table in Main Form with this code:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
SudokuTable st = new SudokuTable();
this.ClientSize = st.getSize();
st.addSudoku(this);
}
}
So far, it works fine. Here's the result:
My problem is, my SudokuTable class can't behave like normal user control. What I mean by normal user control is like when I create a user control via Project --> Add Class --> User Control. My class can't appear in the toolbox.
Is there anyway to create user control components with for loop and make it to behave like normal user control. So I can treat my created control like another control (like add it to Main Form with designer)?
it seems to me you should create new UserControl and incapsulate all this logic in it. Then build solution and UserControl should apear in your toolbox.

Dynamically added labels only show one

Ok so I decided to add controls to a panel on form_load based on labels in an array. Below is my code, but no matter how many files I upload through the button listener and reload this form, it only displays one label and nothing more. Why is it only displaying one? I have added a breakpoint and verified that the count does go up to 2, 3, etc.
Code:
public partial class Attachments : Form
{
ArrayList attachmentFiles;
ArrayList attachmentNames;
public Attachments(ArrayList attachments, ArrayList attachmentFileNames)
{
InitializeComponent();
attachmentFiles = attachments;
attachmentNames = attachmentFileNames;
}
private void Attachments_Load(object sender, EventArgs e)
{
ScrollBar vScrollBar1 = new VScrollBar();
vScrollBar1.Dock = DockStyle.Right;
vScrollBar1.Scroll += (sender2, e2) => { pnl_Attachments.VerticalScroll.Value = vScrollBar1.Value; };
pnl_Attachments.Controls.Add(vScrollBar1);
Label fileName;
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
}
private void btn_AddAttachment_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string fileName = openFileDialog1.FileName;
attachmentFiles.Add(fileName);
attachmentNames.Add(Path.GetFileName(fileName));
this.Close();
}
}
}
This is because the labels are all stacking on top of each other. You will need to specify a top for each one or use an auto-flow panel.
Adding the following line after creating the new label will ensure all labels are visible (you may have to adjust the multiplier depending on your font):
fileName.Top = (i + 1) * 22;
As competent_tech stated the labels are stacking on top of each other, but another approach is to modify the location value of the label.The benefit to this is you can control the absolute location of the label.
fileName.Location = new Point(x, y);
y += marginAmount;
x is the vertical position on the form and y is the horizontal location on the form. Then all that has to be modified is the amount of space you want in between each label in the marginAmount variable.
So in this for loop
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
You could modify it to this:
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
fileName.Location = new Point(x, y);
y += marginAmount;
pnl_Attachments.Controls.Add(fileName);
}
Then all you have to do is define x, y, and the marginAmount.

Get real time input from programmatically generated elements in C# form

How to get value of checkboxes (and the textbox upon change in text) in real time with form particulars that are all generated via code?
This following code produces a form upon button press, the form has checkboxes and a richtextbox. Ideally I want any interaction to have an effect, so if I paste in a grid of ones and zeros the checkboxes update, and once a checkbox gets click, the corresponding one or zero in the textarea will update (So that I can then copy the grid (matrix) out and into another program.
I know how to get the events using the visual studio GUI maker, but not from a programmatically created form like this.
private void begin_button_Click(object sender, EventArgs e)
{
// Build the child form
Form check_box = new Form();
check_box.FormBorderStyle = FormBorderStyle.FixedSingle;
// Get the values from the textboxes
int height = Convert.ToInt16(this.height_input.Text);
int width = Convert.ToInt16(this.width_input.Text);
// Set the dimensions of the form
check_box.Width = width * 15 + 40;
check_box.Height = ( height * 15 + 40 ) * 3;
// Build checkboxes for the checkbox form
CheckBox[] chk;
chk = new CheckBox[height * width];
int count = 0;
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
chk[count] = new CheckBox();
chk[count].Name = count.ToString();
chk[count].Width = 15; // because the default is 100px for text
chk[count].Height = 15;
chk[count].Location = new Point(j * 15, i * 15);
chk[count].CheckedChanged += new EventHandler(this.CheckedChanged);
check_box.Controls.Add(chk[count]);
count += 1;
//Console.WriteLine(" i: " + i + " j: " + j + " Count: " + count);
}
}
RichTextBox output_area;
output_area = new RichTextBox();
output_area.Location = new Point(chk[0].Location.X, chk[count-1].Location.Y + 30);
check_box.Controls.Add(output_area);
output_area.Text = "hello world\n1,1,1,1,1,1,1,1,1\n0,0,0,0,0,1,0,1\nthese ones and zeros are meant to update in real time!";
output_area.Width = check_box.Width - 40;
output_area.Height = check_box.Height / 2;
// Run the form
check_box.ShowDialog();
}
EDIT:
I have added the event handler and it's working, however I can't access the checkbox form, only the main form.
private void CheckedChanged(object sender, EventArgs e)
{
//throw new NotImplementedException();
CheckBox x = (CheckBox)sender;
Console.WriteLine(x);
Console.WriteLine(x.Name.ToString());
}
Have a look at the .Designer file that the form designer generates for you!
Anyway, in your loop, try something like this:
chk[count].CheckedChanged += MyFancyHandler;
And the handler itself will look just like a normal handler:
private void MyFancyHandler( object sender, EventArgs e )
{
// ...
}
Also notice that the sender argument there will contain a reference to whichever checkbox/control the event refers to.
Below code updates matrix text in the rich text box when check box check state changed.
RichTextBox output_area;
CheckBox[] chk;
Size MatrixSize;
private void begin_button_Click()
{
// Build the child form
Form check_box = new Form();
check_box.FormBorderStyle = FormBorderStyle.FixedSingle;
check_box.StartPosition = FormStartPosition.CenterScreen;
// Get the values from the textboxes
int height = Convert.ToInt16("10");
int width = Convert.ToInt16("7");
MatrixSize = new Size(width, height);
// Set the dimensions of the form
check_box.Width = width * 15 + 40;
check_box.Height = (height * 15 + 40) * 3;
// Build checkboxes for the checkbox form
chk = new CheckBox[height * width];
int count = 0;
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
chk[count] = new CheckBox();
chk[count].Name = count.ToString();
chk[count].Width = 15; // because the default is 100px for text
chk[count].Height = 15;
chk[count].Location = new Point(j * 15, i * 15);
check_box.Controls.Add(chk[count]);
chk[count].CheckedChanged += new EventHandler(CheckBox1_CheckedChanged);
count += 1;
//Console.WriteLine(" i: " + i + " j: " + j + " Count: " + count);
}
}
output_area = new RichTextBox();
output_area.Location = new Point(chk[0].Location.X, chk[count - 1].Location.Y + 30);
check_box.Controls.Add(output_area);
output_area.Text = "hello world\n1,1,1,1,1,1,1,1,1\n0,0,0,0,0,1,0,1\nthese ones and zeros are meant to update in real time!";
output_area.Width = check_box.Width - 40;
output_area.Height = check_box.Height / 2;
// Run the form
check_box.ShowDialog();
}
private void CheckBox1_CheckedChanged(Object sender, EventArgs e)
{
CheckBox c = (CheckBox)sender;
Debug.WriteLine(c.Name);
StringBuilder sb = new StringBuilder();
int count = 0;
for (int i = 1; i <= MatrixSize.Height; i++)
{
for (int j = 1; j <= MatrixSize.Width; j++)
{
if (chk[count].Checked)
{
sb.Append("1,");
}
else
{
sb.Append("0,");
}
count += 1;
}
sb.Append("\r\n");
}
output_area.Text = sb.ToString();
}

How to create many labels and textboxes dynamically depending on the value of an integer variable?

Is there any way to dynamically create and display 'n' Labels with 'n' corresponding Textboxs when we know value of 'n' after for example, clicking "Display" button.
Let me know if anything make you don't understand my question. Thank you!
I am working with VS C# Express 2010 Windows Form.
I would create a user control which holds a Label and a Text Box in it and simply create instances of that user control 'n' times. If you want to know a better way to do it and use properties to get access to the values of Label and Text Box from the user control, please let me know.
Simple way to do it would be:
int n = 4; // Or whatever value - n has to be global so that the event handler can access it
private void btnDisplay_Click(object sender, EventArgs e)
{
TextBox[] textBoxes = new TextBox[n];
Label[] labels = new Label[n];
for (int i = 0; i < n; i++)
{
textBoxes[i] = new TextBox();
// Here you can modify the value of the textbox which is at textBoxes[i]
labels[i] = new Label();
// Here you can modify the value of the label which is at labels[i]
}
// This adds the controls to the form (you will need to specify thier co-ordinates etc. first)
for (int i = 0; i < n; i++)
{
this.Controls.Add(textBoxes[i]);
this.Controls.Add(labels[i]);
}
}
The code above assumes that you have a button btnDisplay and it has a onClick event assigned to btnDisplay_Click event handler. You also need to know the value of n and need a way of figuring out where to place all controls. Controls should have a width and height specified as well.
To do it using a User Control simply do this.
Okay, first of all go and create a new user control and put a text box and label in it.
Lets say they are called txtSomeTextBox and lblSomeLabel. In the code behind add this code:
public string GetTextBoxValue()
{
return this.txtSomeTextBox.Text;
}
public string GetLabelValue()
{
return this.lblSomeLabel.Text;
}
public void SetTextBoxValue(string newText)
{
this.txtSomeTextBox.Text = newText;
}
public void SetLabelValue(string newText)
{
this.lblSomeLabel.Text = newText;
}
Now the code to generate the user control will look like this (MyUserControl is the name you have give to your user control):
private void btnDisplay_Click(object sender, EventArgs e)
{
MyUserControl[] controls = new MyUserControl[n];
for (int i = 0; i < n; i++)
{
controls[i] = new MyUserControl();
controls[i].setTextBoxValue("some value to display in text");
controls[i].setLabelValue("some value to display in label");
// Now if you write controls[i].getTextBoxValue() it will return "some value to display in text" and controls[i].getLabelValue() will return "some value to display in label". These value will also be displayed in the user control.
}
// This adds the controls to the form (you will need to specify thier co-ordinates etc. first)
for (int i = 0; i < n; i++)
{
this.Controls.Add(controls[i]);
}
}
Of course you can create more methods in the usercontrol to access properties and set them. Or simply if you have to access a lot, just put in these two variables and you can access the textbox and label directly:
public TextBox myTextBox;
public Label myLabel;
In the constructor of the user control do this:
myTextBox = this.txtSomeTextBox;
myLabel = this.lblSomeLabel;
Then in your program if you want to modify the text value of either just do this.
control[i].myTextBox.Text = "some random text"; // Same applies to myLabel
Hope it helped :)
Here is a simple example that should let you keep going add somethink that would act as a placeholder to your winform can be TableLayoutPanel
and then just add controls to it
for ( int i = 0; i < COUNT; i++ ) {
Label lblTitle = new Label();
lblTitle.Text = i+"Your Text";
youlayOut.Controls.Add( lblTitle, 0, i );
TextBox txtValue = new TextBox();
youlayOut.Controls.Add( txtValue, 2, i );
}
Suppose you have a button that when pressed sets n to 5, you could then generate labels and textboxes on your form like so.
var n = 5;
for (int i = 0; i < n; i++)
{
//Create label
Label label = new Label();
label.Text = String.Format("Label {0}", i);
//Position label on screen
label.Left = 10;
label.Top = (i + 1) * 20;
//Create textbox
TextBox textBox = new TextBox();
//Position textbox on screen
textBox.Left = 120;
textBox.Top = (i + 1) * 20;
//Add controls to form
this.Controls.Add(label);
this.Controls.Add(textBox);
}
This will not only add them to the form but position them decently as well.
You can try this:
int cleft = 1;
intaleft = 1;
private void button2_Click(object sender, EventArgs e)
{
TextBox txt = new TextBox();
this.Controls.Add(txt);
txt.Top = cleft * 40;
txt.Size = new Size(200, 16);
txt.Left = 150;
cleft = cleft + 1;
Label lbl = new Label();
this.Controls.Add(lbl);
lbl.Top = aleft * 40;
lbl.Size = new Size(100, 16);
lbl.ForeColor = Color.Blue;
lbl.Text = "BoxNo/CardNo";
lbl.Left = 70;
aleft = aleft + 1;
return;
}
private void btd_Click(object sender, EventArgs e)
{
//Here you Delete Text Box One By One(int ix for Text Box)
for (int ix = this.Controls.Count - 2; ix >= 0; ix--)
//Here you Delete Lable One By One(int ix for Lable)
for (int x = this.Controls.Count - 2; x >= 0; x--)
{
if (this.Controls[ix] is TextBox)
this.Controls[ix].Dispose();
if (this.Controls[x] is Label)
this.Controls[x].Dispose();
return;
}
}

Categories