C# Problem removing textbox from tableLayoutPanel - c#

Hello I'm currently working on a windows from where I need to be able to add and remove a number of textboxes (and a lable) with a button click.
I have to have it set out within a tableLayoutPanel and Once "Add" is clicked a Label and 5 Text boxes must appear on the same row, and then when I click "Remove" they must dissapear, Hiding won't work as Data needs to be taken from them at a later stage but thats not an issue atm.
The problem is with the removal (I can add them fine as you'll see below) I know whats happening and can guess as to why but I need to find an alternate solution >.<
public partial class Form2 : Form
{
int Count = 1;
int rowIndex = 2, colIndex = 1;
Label Label;
TextBox Value;
TextBox Weight;
TextBox Width;
TextBox Height;
TextBox Length;
private void button1_Click(object sender, EventArgs e)
{
if (Count <= 9)
{
Count += 1;
rowIndex += 1;
tableLayoutPanel10.RowCount = +1;
AddLot(Count);
if (Count > 9)
button1.Enabled = false;
}
button2.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
if (Count == 2)
{
tableLayoutPanel10.Controls.Remove(Label);
tableLayoutPanel10.Controls.Remove(Value);
tableLayoutPanel10.Controls.Remove(Weight);
tableLayoutPanel10.Controls.Remove(Width);
tableLayoutPanel10.Controls.Remove(Height);
tableLayoutPanel10.Controls.Remove(Length);
Count -= 1;
rowIndex -= 1;
button2.Enabled = false;
}
else
{
tableLayoutPanel10.Controls.Remove(Label);
tableLayoutPanel10.Controls.Remove(Value);
tableLayoutPanel10.Controls.Remove(Weight);
tableLayoutPanel10.Controls.Remove(Width);
tableLayoutPanel10.Controls.Remove(Height);
tableLayoutPanel10.Controls.Remove(Length);
Count -= 1;
rowIndex -= 1;
button1.Enabled = true;
}
}
private void AddLot(int Count)
{
Label = new Label();
Label.Dock = DockStyle.Fill;
Label.Text = Count.ToString();
Label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
Value = new TextBox();
Value.Dock = DockStyle.Fill;
Weight = new TextBox();
Weight.Dock = DockStyle.Fill;
Width = new TextBox();
Width.Dock = DockStyle.Fill;
Height = new TextBox();
Height.Dock = DockStyle.Fill;
Length = new TextBox();
Length.Dock = DockStyle.Fill;
tableLayoutPanel10.Controls.Add(Label, colIndex - 1, rowIndex);
tableLayoutPanel10.Controls.Add(Value, colIndex, rowIndex);
tableLayoutPanel10.Controls.Add(Weight, colIndex + 1, rowIndex);
tableLayoutPanel10.Controls.Add(Width, colIndex + 2, rowIndex);
tableLayoutPanel10.Controls.Add(Height, colIndex + 3, rowIndex);
tableLayoutPanel10.Controls.Add(Length, colIndex + 4, rowIndex);
}
}
All That Happens when I try to remove is the Last added Row of label/textboxes is removed, and then only the rowindex/count decrease on any clocks afterwards.
Any Ideas how to get this to work, I'll accept having to change it almost completely but as I said It must be done in the TableLayoutPanel >.<
Cheers,
Jmaru7

This works 100% for me i spent an hour working on it :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
tableLayoutPanel1.RowCount = 1;
tableLayoutPanel1.ColumnCount = 6;
removeButton.Enabled = false;
}
private void addButton_Click(object sender, EventArgs e)
{
int index = tableLayoutPanel1.RowCount - 1;
Label label = new Label();
TextBox Value = new TextBox();
TextBox Weight = new TextBox();
TextBox Width = new TextBox();
TextBox Height = new TextBox();
TextBox Length = new TextBox();
label.Dock = DockStyle.Fill;
label.Text = (index + 1).ToString();
label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
Value.Dock = DockStyle.Fill;
Weight.Dock = DockStyle.Fill;
Width.Dock = DockStyle.Fill;
Height.Dock = DockStyle.Fill;
Length.Dock = DockStyle.Fill;
int i = 0;
tableLayoutPanel1.Controls.Add(label, i++, index);
tableLayoutPanel1.Controls.Add(Value, i++, index);
tableLayoutPanel1.Controls.Add(Weight, i++, index);
tableLayoutPanel1.Controls.Add(Width, i++, index);
tableLayoutPanel1.Controls.Add(Height, i++, index);
tableLayoutPanel1.Controls.Add(Length, i++, index);
tableLayoutPanel1.RowCount += 1;
if (tableLayoutPanel1.RowCount > 9)
{
addButton.Enabled = false;
}
if (tableLayoutPanel1.RowCount > 0)
{
removeButton.Enabled = true;
}
}
private void removeButton_Click(object sender, EventArgs e)
{
if (tableLayoutPanel1.RowCount > 0)
{
int startIndex = ((tableLayoutPanel1.RowCount - 1) * 6) - 1;
for (int i = 0; i < 6; i++)
{
tableLayoutPanel1.Controls.RemoveAt(startIndex--);
}
tableLayoutPanel1.RowCount -= 1;
if (tableLayoutPanel1.RowCount == 0)
{
removeButton.Enabled = false;
}
if (tableLayoutPanel1.RowCount <= 9)
{
addButton.Enabled = true;
}
}
}
}

You are keeping only last added set of controls, you should keep all of them. Now when you delete last added controls, next delete uses reference to already deleted so it wont have any effect.
Best would be to make some storage class for set of the controls and keep them in some kind of collection.

Related

Labels don't move using Mouse events

I created 5 labels using a for. Inside the for I declared the properties of the labels, such as location, size, color, etc. and the possibility to move the labels using the mouse events:
private void Form1_Load(object sender, EventArgs e)
{
int alto = 100;
int ancho = 65;
for (byte fila = 0; fila < 5; fila++)
{
Label letras = new Label();
letras.Height = alto;
letras.Width = ancho;
letras.BackColor = Color.Blue;
letras.ForeColor = Color.AntiqueWhite;
letras.Font = new Font("Arial", 60);
letras.TextAlign = ContentAlignment.MiddleCenter;
letras.BorderStyle = BorderStyle.FixedSingle;
letras.Left = 200 + (ancho + 20) * fila;
letras.Top = 60;
letras.Text = null;
letras.MouseDown += new MouseEventHandler(this.letras_MouseDown);
letras.MouseMove += new MouseEventHandler(this.letras_MouseMove);
letras.MouseUp += new MouseEventHandler(this.letras_MouseUp);
this.Controls.Add(letras);
}
}
Later in the code, I create the events which will make the labels move.
private void letras_MouseDown(object sender, MouseEventArgs e)
{
mousedown = true;
}
private void letras_MouseMove(object sender, MouseEventArgs e)
{
if (mousedown)
{
letras.Location = new Point(letras.Location.X + e.Location.X, letras.Location.Y + e.Location.Y);
}
}
private void letras_MouseUp(object sender, MouseEventArgs e)
{
mousedown = false;
}
but it isn't working. Any ideas? I think that could be an Indentation problem, but I'm not sure.
The sender argument received by the letras_MouseMove method is the Label so the first thing to do is perform a cast to a usable Label object. Then simply test the static Control.MouseButtons property to determine if the Left button is currently active. You calculated the offset correctly. I believe that all you really needed was to have the correct Label object. (Of course I tested it)
Some of the code you posted is not necessary and should be removed. This shows a minimal working example.
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// This code stays the same
int alto = 100;
int ancho = 65;
for (byte fila = 0; fila < 5; fila++)
{
Label letras = new Label();
letras.Height = alto;
letras.Width = ancho;
letras.BackColor = Color.Blue;
letras.ForeColor = Color.AntiqueWhite;
letras.Font = new Font("Arial", 60);
letras.TextAlign = ContentAlignment.MiddleCenter;
letras.BorderStyle = BorderStyle.FixedSingle;
letras.Left = 200 + (ancho + 20) * fila;
letras.Top = 60;
letras.Text = null;
letras.MouseMove += new MouseEventHandler(this.letras_MouseMove);
this.Controls.Add(letras);
}
}
// This code is different
private void letras_MouseMove(object sender, MouseEventArgs e)
{
Label letra = (Label)sender;
if(MouseButtons == MouseButtons.Left)
{
// Here, your original calculation works OK once you have the correct Label object
letra.Location = new Point(letra.Location.X + e.Location.X, letra.Location.Y + e.Location.Y);
}
}
}
Haven't tested but replace:
private void Form1_Load(object sender, EventArgs e)
{
int alto = 100;
int ancho = 65;
for (byte fila = 0; fila < 5; fila++)
{
letras = new Label();
With:
Label[] labels = Array.Empty<Label>();
private void Form1_Load(object sender, EventArgs e)
{
int alto = 100;
int ancho = 65;
for (byte fila = 0; fila < 5; fila++)
{
labels[fila] = new Label();
And replace every letras in the file with labels[(number)].

Form slide transition C#

Im creating a transition for my form in Visual Studio,
i'm coding a slide effect for the width but it ends up to slow
is there anyway to make it more faster?
btw here is the code :
`int check = 0;
private void button1_Click(object sender, EventArgs e)
{
this.button1.Text = "Hide";
if (check == 0)
{
for (int i = 350; i <= 824; ++i)
{
this.Size = new Size(i, 507);
Thread.Sleep(10);
this.CenterToScreen();
}
check = 1;
}
else if (check == 1)
{
this.button1.Text = "Key";
for (int i = 824; i >= 351; i--)
{
this.Size = new Size(i, 507);
Thread.Sleep(5);
this.CenterToScreen();
}
check = 0;
}
}
By using your existing code, you can tune it for the sake of speed like;
private int check = 0;
private void button1_Click(object sender, EventArgs e)
{
this.button1.Text = "Hide";
if (check == 0)
{
for (int i = 350; i <= 824; i += 2)
{
this.Size = new Size(i, 507);
Thread.Sleep(1);
this.CenterToScreen();
}
check = 1;
}
else if (check == 1)
{
this.button1.Text = "Key";
for (int i = 824; i >= 351; i -= 2)
{
this.Size = new Size(i, 507);
Thread.Sleep(1);
this.CenterToScreen();
}
check = 0;
}
}
You can change Thread.Sleep lines as above and increase or decrease the loop variables for faster an animation.

Retrieving values from dynamically created controls Label in asp .net

I have created Label controls dynamically on button click:
protected void createDynamicLabels_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
When I tried to read back fro another button I see Label Control returned null
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
not sure what went wrong here
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
this is the issue of every time page load event. ASP.net fire every time page load event when any button is click.
suppose in this example..
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
when Button trigger Page doesn't have any label because it is made on runtime. and Page doesn't find particular label. if you tried above code it is run properly.
protected void Page_Load(object sender, EventArgs e)
{
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
in this Example code find label every time because every time it can make labels for this page.
Dynamically created labels exists only until the next postback occurs. When you click on another button to retrieve their values a postback occurs and values become null.
For saving labels state after postback you have to use some hidden field.
If the text / value of the labes does not change it is enough to generate them on every postback (as mck already mentioned). If you need to retrieve changes made on the client side, you should create the controls in the OnInit event instead of the PageLoad and use inputs / texboxes instead of labels.
Another option (which I would recommend) would be to use a asp:Repeater to generate the Labels.

Dynamic button creation & placing them in a predefined order using c#

NET 4.5 C# to create a windows form. I want to dynamically create & add buttons & also assign them click events but want them to be dynamically placed in a particular fashion just like the image.
My question is how do I place the buttons dynamically in the above fashion i.e. 4x4 format (4 buttons in a row, 4 columns but unlimited rows). Is it possible to do so in win forms?
Presently I'm trying the below mentioned code but have no clear idea as to how I can place the buttons as shown above.
public Form1()
{
InitializeComponent();
for (int i = 0; i < 5; i++)
{
Button button = new Button();
button.Location = new Point(160, 30 * i + 10);
button.Click += new EventHandler(ButtonClickCommonEvent);
button.Tag = i;
this.Controls.Add(button);
}
}
void ButtonClickCommonEvent(object sender, EventArgs e)
{
Button button = sender as Button;
if (button != null)
{
switch ((int)button.Tag)
{
case 0:
// First Button Clicked
break;
case 1:
// Second Button Clicked
break;
// ...
}
}
}
Please advise solution with codes.
You can use a TableLayoutPanel and create your buttons dynamically and add them to the panel.
For example:
private void Form1_Load(object sender, EventArgs e)
{
var rowCount = 3;
var columnCount = 4;
this.tableLayoutPanel1.ColumnCount = columnCount;
this.tableLayoutPanel1.RowCount = rowCount;
this.tableLayoutPanel1.ColumnStyles.Clear();
this.tableLayoutPanel1.RowStyles.Clear();
for (int i = 0; i < columnCount; i++)
{
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / columnCount));
}
for (int i = 0; i < rowCount; i++)
{
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / rowCount));
}
for (int i = 0; i < rowCount* columnCount; i++)
{
var b = new Button();
b.Text = (i+1).ToString();
b.Name = string.Format("b_{0}", i + 1);
b.Click += b_Click;
b.Dock = DockStyle.Fill;
this.tableLayoutPanel1.Controls.Add(b);
}
}
void b_Click(object sender, EventArgs e)
{
var b = sender as Button;
if (b != null)
MessageBox.Show(string.Format("{0} Clicked", b.Text));
}
Note:
Using TableLayoutPanel.Controls.Add(control) we can add controls sequentially to the panel.
Using TableLayoutPanel.Controls.Add(control, columnIndex, rowIndex) we can add controls at specific cells.

Button Click Frequency Array

I need to make a ListBox that displays how often a Button is clicked.
The user chooses how many buttons are available to click. Here is what I've tried:
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
for (int i = 0; i < freq_array[clicked]; i++)
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
freq_array uses the 'clicked' variable to add to the frequency that button has been clicked. Or, it's supposed to.
When I debug it, 'clicked' always comes out to 0. I want 'clicked' to equal the text value of the button that's clicked. When I try to run the program, I get an error saying "Input string was not in correct format."
Edit:
I was able to fix my program with help from you guys. I realized I didn't show enough of my code to be clear enough, and I apologize for that. I had to add some things and move things around and got it soon enough. Thank you all.
Here is the code just for those who may need help in the future:
public partial class Form1 : Form
{
int[] freq_array = new int[11];
int[] numList = new int[11];
int oBase = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
invisiblity();
}
private void invisiblity()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
ctrl.Visible = false;
}
}
private void btnSetBase_Click(object sender, EventArgs e)
{
Form2 frmDialog = new Form2();
frmDialog.ShowDialog(this);
if (frmDialog.DialogResult == DialogResult.OK)
{
oBase = frmDialog.Base;
//lblOutDigits.Text = oBase.ToString();
for (int i = 0; i < oBase; i++)
{
numList[i] = i;
}
}
ShowBaseButtons(oBase);
}
private void ShowBaseButtons(int last_digit)
{
invisiblity();
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
if (int.Parse(ctrl.Text) <= last_digit - 1)
ctrl.Visible = true;
}
}
private void btnN_Click(object sender, EventArgs e)
{
lblOutDigits.Text += ((Button)(sender)).Text;
int clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
}
private void btnShowFreq_Click(object sender, EventArgs e)
{
lstFrequencies.Items.Clear();
for (int i = 0; i < oBase; i++)
lstFrequencies.Items.Add(numList[i] + " \t\t\t" + freq_array[i]);
}
Your code should work as long as your Button Text is actually just a number. Since what you are trying to do is create an index, what I usually do is use the Tag Property of the control, set it to the Index I want in the designer and then cast that to an Int.
i.e.
if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
freq_array[clicked]++;
I believe what is happening is that you are not initializing your ListBox, This example Code does work using your initial method. Just create a new Form and paste it in and test.
public partial class Form1 : Form
{
ListBox lstFrequencies = new ListBox();
int[] freq_array = new int[10];
public Form1()
{
InitializeComponent();
Size = new Size(400, 400);
lstFrequencies.Location = new Point(150, 0);
lstFrequencies.Size = new Size(150, 200);
Controls.Add(lstFrequencies);
int top = 0;
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Size = new Size(70, 30);
btn.Location = new Point(5, top);
Controls.Add(btn);
top += 35;
btn.Tag = i;
btn.Text = i.ToString();
btn.Click += new EventHandler(btn_Click);
lstFrequencies.Items.Add(i.ToString());
}
}
void btn_Click(object sender, EventArgs e)
{
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked]; //Cleaned up you do not need to iterate your list
// Using my example code
//if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
//{
// freq_array[clicked]++;
// lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
//}
}
}
Your code always comes out to 0 because you never assign last clicked value to button text. Try this code:
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
clicked = Convert.ToInt32(((Button)sender).Text);
lstFrequencies.Items.Add(((Button)sender).Name + " " + ++clicked);
button1.Text = clicked.ToString(); // you lose this line
}
EDIT: Counter from variable member
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
// if you want to display button name, change .Text to .Name
lstFrequencies.Items.Add(((Button)sender).Text + " " + ++clicked);
}

Categories