C# remove last dynamically created textbox - c#

Almost totally noob here. Im stucked. I know how to delete all dc textboxes but have no idea how to delete only last created one. Thx
piece of my code:
int B = 1;
public void NovIntRazd()
{
TextBox txt = new TextBox();
this.Controls.Add(txt);
txt.Top = B * 30;
txt.Left = 26;
txt.Height = 20;
txt.Width = 65;
txt.Name = "txtIntRazd" + this.B.ToString();
B++;
}

If you only need to ever remove one textbox, you can just keep the reference to the last one:
int B = 1;
TextBox txt;
public void NovIntRazd()
{
txt = new TextBox();
this.Controls.Add(txt);
txt.Top = B * 30;
txt.Left = 26;
txt.Height = 20;
txt.Width = 65;
txt.Name = "txtIntRazd" + this.B.ToString();
B++;
}
public void RemoveLast()
{
if (txt == null) return;
Controls.Remove(txt);
txt = null;
}
Alternatively, a good practice is to put dynamically created controls in their own container, like a panel. It sounds like your case is a perfect use for a FlowLayoutPanel, which will handle control positioning too. When you remove any control, all the others are automatically moved around to the right places.
Then to remove the last added control, you can just do
if (pnl.Controls.Count > 0) pnl.Controls.RemoveAt(pnl.Controls.Count - 1);
If you really want to keep the controls mixed up in the top-level form, you can easily organize the dynamic textboxes by using a Stack:
Stack<TextBox> textboxes = new Stack<TextBox>();
public void NovIntRazd()
{
var txt = new TextBox()
{
Top = (textboxes.Count + 1) * 30,
Left = 26,
Height = 20,
Width = 65,
Name = "txtIntRazd" + (textboxes.Count + 1).ToString()
};
this.Controls.Add(txt);
textboxes.Push(txt);
}
public void RemoveLast()
{
if (textboxes.Count == 0) return;
Controls.Remove(textboxes.Pop());
}

Related

c# how to add Button to array and set text of all buttons

Hi my problem is i want to add buttons to array size: 65
and there is a problem here's my code:
Button[] buttonsa = new Button[65];
for (int d = 0; d <= buttonsa.Length; d++)
{
try
{
buttonsa[d].Text = "Runned!";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
My all code for creating button to scene:
private void CreateButton(int xh, int yh, int width, int height)
{
Button newButton = new Button();
if (width < 100)
{
newButton.Width = 100;
}
else
{
newButton.Width = width;
}
if (height < 30)
{
newButton.Height = 30;
}
else
{
newButton.Height = height;
}
newButton.Text = "button" + btnIndex;
newButton.ForeColor = Color.FromArgb(35,35,35,0);
newButton.Name = "btn" + btnIndex.ToString();
newButton.AccessibleName = btnIndex.ToString() + "|FlatStyle=" + FlatStyle.System.ToString() + "|Pussy=sussy";
newButton.ContextMenuStrip = btnContext;
newButton.Tag = "button" + btnIndex;
newButton.FlatStyle = FlatStyle.Flat;
newButton.BackColor = Color.White;
newButton.Location = new Point(xh, yh);
newButton.Click += newButton_Click2;
buttonsa[btnIndex] = newButton;
btnIndex++;
int x = rand.Next(10, pic.ClientSize.Width - newButton.Width);
int y = rand.Next(10, pic.ClientSize.Height - newButton.Height);
newButton.Location = new Point(xh, yh);
pic.Controls.Add(newButton);
buttonsInScene.Add(newButton);
this.CenterToScreen();
g.Clear(Color.FromArgb(35, 35, 35, 0));
pic.Refresh();
}
Im working on big project if anyone can help me Thanks alot! <3
I tried a few times to fix it i needed to get all my buttons in form and set text to "Runned!"
You can use the recursive method for getting all buttons on the form. You don't need to add all buttons to the array type, anytime you can use your function and gets all buttons on the form and on the child controls.
But, if you want, you can write easy code inside the function, for adding buttons to an array or to the List.
Example:
private void ButtonList (Control cont)
{
foreach (Control c in cont.Controls)
{
if (c is Button)
{
(c as Button).Text = "Hello";
(c as Button).Visible = true;
// and etc...
/*************** example adding button object to list *************
declare listButton property of type List<Button> on your code
listButton.Add((c as Button));
*******************************************************************/
}
if (c.Controls.Count > 0)
{
ButtonList(c);
}
}
}
And you can use this function calling that
ButtonList (MainForm);

How to access and change the property of a label that I created dynamically

I wanna change the Text properties of Label using Buttons just like in hangman; but after I created the Label, I became confused when I try to access the specific Label
// creating label
for (int i = 0; i < numericUpDown1.Value; i++)
{
Label l = new Label();
l.Text = "_";
l.Width = 20;
l.Height = 25;
l.Left = i * 20 + 510;
l.Top = 20;
l.BackColor = Color.Transparent;
groupBox2.Controls.Add(l);
}
// function to change the label text
// if I clicked the button
// the first label text will be changed to the text in the button i clicked
private void B_Click(object sender, EventArgs e)
{
var thsBtn = (Button)sender;
bool benar = false;
if (benar == false)
{
thsBtn.Text = " ";
thsBtn.Enabled = false;
}
else
{
thsBtn.Enabled = false;
}
}
You can organize created Labels into a collection, say, List<Label>:
private List<Label> m_CreatedLabels = new List<Label>();
...
// Remove all previous labels
foreach (Label lbl in m_CreatedLabels)
lbl.Dispose();
m_CreatedLabels.Clear();
// Create new ones
for (int i = 0; i < numericUpDown1.Value; i++) {
m_CreatedLabels.Add(new Label() {
Text = "_",
Width = 20,
Height = 25,
Left = i * 20 + 510,
Top = 20,
BackColor = Color.Transparent,
Parent = groupBox2
});
}
Now you have m_CreatedLabels collection to work with created Labels, e.g.
private void B_Click(object sender, EventArgs e) {
var thsBtn = sender as Button;
// you may want to add a condition into FirstOrDefault(), e.g.
// .FirstOrDefault(lbl => lbl.Text == "_")
// - first label with "_" Text
Label lblToProcess = m_CreatedLabels
.FirstOrDefault();
if (null != lblToProcess)
lblToProcess.Text = thsBtn.Text;
thsBtn.Enabled = false;
}
One option here is to give your dynamically created Label instances a Name. From there, you should be able to use ControlCollection.Find to find your Label instances by name.
private void CreateLabels()
{
for (int i = 0; i < numericUpDown1.Value; i++)
{
Label l = new Label();
l.Name = $"DynamicLabel{i}";
l.Text = "_";
l.Width = 20;
l.Height = 25;
l.Left = i * 20 + 510;
l.Top = 20;
l.BackColor = Color.Transparent;
groupBox2.Controls.Add(l);
}
}
private void DoSomethingWithADynamicLabel(int dynamicLabelIndex)
{
Label l = groupBox2.Controls.Find($"DynamicLabel{i}", true).FirstOrDefault() as Label;
if (l is null)
{
// Couldn't find the label...
return;
}
// Do something with l
}
When creating the Label instances inside CreateLabels, I'm simply appending the for loop's counter to the string "DynamicLabel". This gives you a bunch of Labels with names like "DynamicLabel0", "DynamicLable1", "DynamicLabel2", etc...
Then in DoSomethingWithADynamicLabel, assuming you have the index of the Label you want to deal with, you can use groupBox2.Controls.Find to actually find the Label you're interested in. ControlCollection.Find returns Control[], so calling FirstOrDefault will take the first item from the array or null if no Control with the given name exists.

How to create event from control's that not yet create?

My program is the create datagridview program that user can create dynamic columns like row,column,panel(panel is quantity of the panel) so user can mark it too,
as I know I can mark the cell with CurrentCell.Style.BackColor
when I generate datagridview I have assign name of it But !!!! it cant use the new datagridvieweventhandler command so I cant do any thing with each datagridview
so this is my Datagridview Generate Code
string[] Panelname = { "One","Two","Three","Four","Five"};
for(i=0;i<Panelname.length;i++){
Generate(Panelname[i],a,b)}
DataGridView generate(string name,int columns,int rows)
{
int i;
Control Gen;
Control LB;
LB = new Label();
LB.Text = "Panel : "+name;
LB.Location = new Point(50 + 120 / (c - 1) + 900 / c , 315);
LB.BackColor = Color.Silver;
Gen = new DataGridView();
Gen.Name = name.ToString();
Gen.Size = new Size(900/c,300 );
Gen.Location = new Point(120 / (c ) + 900 / c, 0);
DataGridView CH = (DataGridView)Gen;
CH.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
CH.CellClick += new DataGridViewCellEventHandler(CH_CellClick);
CH.Location = new Point(0+locate, 0);
for (i = 1; i <= columns; i++)
{
CH.Columns.Add("", "");
}
for (i = 1; i < rows; i++)
{
CH.Rows.Add("", "");
}
dataGridView1.Controls.Add(LB);
dataGridView1.Controls.Add(CH);
return null;
}
How can I create the event handler for each datagridview that I'm create it dynamicly ?
thankyou for your kind
Create your datagridview.
for (int i = 0; i < 10; i++)
{
DataGridView d = new DataGridView();
d.MouseClick += dataGridView_MouseClick;
}
Use the add handler method.
private void dataGridView_MouseClick(object sender, MouseEventArgs e)
{
// Use sender to determine which datagridview fired the event
}
The problem that I found is when I'm create datagridview in the datagridview it hard to define it what's datagridview that you're clicking so I have stuck in this problem for a while
And now I found out the way's to through out my problem now, here it is
for(i=0;i
DataGridView generate2(string name, int columns, int rows,int form)
{
Control Gen;
Control LB;
int x = 1;
int runcolumn = columns;
int runrow = rows;
int count=0;
LB = new Label();
LB.Text = "Panel : " + name;
LB.Location = new Point(50 + 120 / (c - 1) + 900 / c, 320);
LB.BackColor = Color.Silver;
Gen = new DataGridView();
Gen.Name = name.ToString();
Gen.Location = new Point(120 / (c) + 900 / c, 0);
DataGridView CH = (DataGridView)Gen;
CH.RowTemplate.Height = 290 / rows;
CH.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
CH.Size = new Size(900 / c, 300);
CH.RowHeadersWidth = 10;
CH.ColumnHeadersHeight = 10;
CH.Location = new Point(0 + locate, 0);
And********* CH.Click += new EventHandler(control_click);********* this is my hero's
private void control_click(object sender, EventArgs e)
{
if (sender is DataGridView)
{
DataGridView A = (DataGridView)sender;
textBox2.Text = A.CurrentCell.RowIndex.ToString();
textBox1.Text = A.CurrentCell.ColumnIndex.ToString();
textBox3.Text = A.Name.ToString();
}
}
in the send control click function you can find what's kind of your control and cast it , so whatever control that you click it you can set it's function now!

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

C# WinForms, Adding a usercontrol Dynamically during runtime and controls are invisible?

I'm working on a contact manager, and I want to add controls for contact details such as Phone Number, Email to a usercontrol. i created a user control called TextPrompt that includes a label and textbox. the code should sort through the contacts Info and add a control for each entree, the program produces no errors(logical, and syntax as far as i can tell). I ran checks to make sure the controls were being added to the panel after the loop ran and it shows the controls are there, but they arent visible during runtime.
List<ContactType> details = contact.ReturnAllContactDetails();
int y = 0;
if (contact != null)
{
lbl_Name.Text = "";
if (contact.GetContactValueByType("FirstName") != null) { lbl_Name.Text = contact.GetContactValueByType("FirstName") + " "; }
if (contact.GetContactValueByType("LastName") != null) { lbl_Name.Text = lbl_Name.Text + contact.GetContactValueByType("LastName"); }
if (contact.GetContactValueByType("Company") != null) { lbl_Name.Text = lbl_Name.Text + "\n" + contact.GetContactValueByType("Company"); }
pnl_ContactDetails.BringToFront();
pnl_ContactDetails.Controls.Clear();
pnl_ContactDetails.SuspendLayout();
for(int i = 3; i < details.Count; i++) {
TextPrompt txtbox = new TextPrompt(details[i]); //Textbox to be added
MessageBox.Show(details[i].value);
this.pnl_ContactDetails.Controls.Add(txtbox);
txtbox.Name = details[i].name; //Sets properties
txtbox.Location = new Point(25, y);
txtbox.Size = new System.Drawing.Size(345, 45);
txtbox.TextValueChanged += new EventHandler(txtbox_TextChanged);
txtbox.Show();
txtbox = (TextPrompt)this.pnl_ContactDetails.Controls[i - 3]; //Checks to make sure controls are on form.
MessageBox.Show(txtbox.ContactDetails.name);
y = y + 45;
}
}
It seems that you have called SuspendLayout() without telling the panel to ResumeLayout()
pnl_ContactDetails.SuspendLayout();
for(int i = 3; i < details.Count; i++)
{
TextPrompt txtbox = new TextPrompt(details[i]); //Textbox to be added
MessageBox.Show(details[i].value);
txtbox.Name = details[i].name; //Sets properties
txtbox.Location = new Point(25, y);
txtbox.Size = new System.Drawing.Size(345, 45);
txtbox.TextValueChanged += new EventHandler(txtbox_TextChanged);
/* txtbox.Show(); */ // Leave this call out in favor of:
txtbox.Visible = true;
this.pnl_ContactDetails.Controls.Add(txtbox);
txtbox = (TextPrompt)this.pnl_ContactDetails.Controls[i - 3]; //Checks to make sure controls are on form.
MessageBox.Show(txtbox.ContactDetails.name);
y = y + 45;
}
pnl_ContactDetails.ResumeLayout();
I made a few modifications to your code. Caveat Emptor :-)

Categories