Removing from the list with button click - c#

I'm printing out items from the list each to the label, and a button nearby for removing them from the list. The removal button doesn't seem to work.
private void cart_Click(object sender, EventArgs e)
{
krepselioPanel.Visible = !krepselioPanel.Visible;
krepselioPav.Visible = !krepselioPav.Visible;
int i = 0;
double s = 0;
foreach (Patiekalas preke in prekes)
{
Label prekiulist = new Label();
prekiulist.Location = new Point(0, 26 * i);
prekiulist.Text = preke.GetPatiekalas() + " | " + preke.GetKaina() + "€";
prekiulist.Size = new Size(200, 20);
krepselioPanel.Controls.Add(prekiulist);
s += Convert.ToDouble(preke.GetKaina());
Button removeButton = new Button();
removeButton.Text = "x";
removeButton.Location = new Point(200, 26 * i);
removeButton.Font = new Font(FontFamily.GenericSansSerif, 9);
removeButton.Size = new Size(20, 22);
removeButton.Click += removeButton_Click;
removeButton.Tag = preke;
krepselioPanel.Controls.Add(removeButton);
i++;
}
Label suma = new Label();
suma.Location = new Point(krepselioPanel.Right - 140, 0);
suma.Font = new Font(FontFamily.GenericSansSerif, 13);
suma.Text = "Total: " + s + "€";
suma.Size = new Size(130, 25);
krepselioPanel.Controls.Add(suma);
}
private void removeButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
Patiekalas preke = (Patiekalas)b.Tag;
prekes.Remove(preke);
cart_Click(sender, e);
cart_Click(sender, e);
}
}
Just for the interest sake I changed the functions removeButton_Click line
prekes.Remove(preke);
to
prekes.Add(preke);
and this creates a new entry to the list but removal doesn't work however.

The code doesn't seem to remove the previous controls from the panel so each time the controls are added new ones are created. If you have only one item in the cart then the next time nothing seems to happen, nothing added nor removed, but if there's multiple items they will start to multiply.
So remove the controls from the panel and then add new ones and the item will disappear.

Related

We have a number of buttons being created on runtime as anonymous objects.Can we add an onlick event on those buttons?

As the title says i have buttons being created as anonymous objects after an event occurs(the click of another button).What i am trying to do is to make this buttons show a Messagebox when they are being clicked.I can't add this functionality to the buttons and i haven't found anything that solves my problem.Maybe it just can't happen this way.
Controls.Add(new Button { Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = i.ToString(),
BackColor = c,
//eventforshowingmessage()
});`
You could assign button to variable first, and then register event:
public AddButton()
{
var newButton = new Button { Text = "Button 1" };
newButton.Click += MyEventListener;
this.Controls.Add(newButton);
}
private void MyEventListener(object sender, EventArgs e)
{
var button = (Button)sender;
MessageBox.Show($"{button.Text} says: Hello, world");
}
I suggest a different syntax: Parent instead of Controls.Add:
for (int i ....) { // whatever loop
...
new Button {
Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = $"{i}", // May appear more readable than i.ToString()
BackColor = c,
Parent = this, // <- instead of this.Controls.Add
}.Click += eventforshowingmessage;
...
}
Demo: For instance, let's create 5 buttons and show up which button has been clicked:
for (int i = 0; i < 5; ++i) {
new Button {
Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = $"{i}",
BackColor = SystemColors.Control,
Parent = this,
}.Click += (ss, ee) => {
// Lambda: what shall we do on click
MessageBox.Show($"{(ss as Control).Text} clicked!");
};
}

Delete 2 Dynamic Buttons from one Dynamic Button

So I have an Image Map and on it I want to appear 3 buttons each time I clicked on a location. Those 3 button would be : hotspot, delete hotspot, save hotspot. These Buttons are Dynamically generated. The question is, how can I the hotspot from delete hotspot Button and also close the other 2 Buttons.
Some code for a little bit of understanding of what am I doing:
private void PictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
//Locatia
PictureBox C = new PictureBox();
int i = 0;
C.Location = new Point(e.X-13, e.Y-30);
C.Name = "Problema_" + (i + 1).ToString();
C.ImageLocation = #"C:\Users\Starrux\Pictures\PNGs\Planner\icons8_GPS_500px.png";
C.Size = new Size(26, 30);
C.SizeMode = PictureBoxSizeMode.StretchImage;
C.BackColor = Color.Transparent;
C.Cursor = Cursors.Hand;
// C.Click += new EventHandler(this.StartRecordingToolStripMenuItem_Click_1);;
PictureBox1.Controls.Add(C);
//salveaza Locatia
PictureBox S = new PictureBox();
S.Name = "Salveaza_" + (i + 1).ToString();
S.Location = new Point(e.X - 45, e.Y+10);
S.ImageLocation = #"C:\Users\Starrux\Pictures\PNGs\Planner\icons8_Checked_Checkbox_500px.png";
S.Size = new Size(35, 35);
S.SizeMode = PictureBoxSizeMode.StretchImage;
S.BackColor = Color.Transparent;
S.Cursor = Cursors.Hand;
PictureBox1.Controls.Add(S);
//sterge Locatia
PictureBox St = new PictureBox();
St.Name = "Sterge_" + (i + 1).ToString();
St.Location = new Point(e.X +10, e.Y+10);
St.Cursor = Cursors.Hand;
St.ImageLocation = #"C:\Users\Starrux\Pictures\PNGs\Planner\icons8_Close_Window_500px.png";
St.Size = new Size(35, 35);
St.SizeMode = PictureBoxSizeMode.StretchImage;
St.BackColor = Color.Transparent;
PictureBox1.Controls.Add(St);
S.Click += new EventHandler(this.stergeAprob);
C.Click += new EventHandler(this.clickHotspot);
}
The solution could be that when creating dynamically you also delete it dynamically using anonymous functions
S.Click += (o, e) => {
//....actions
PictureBox1.Controls.remove(C)
//... other actions
}
we can have access to dynamically created variables since the compiler creates inline functions

C# winforms dynamically created button controls

I have an add user button which dynamically adds a remove button and a username textbox when the user clicks it. The user can click the button as many times as they like and the controls will continue to add.
I am having trouble with the remove button that is created dynamically. It should removed the itself and the username textbox next to it. Instead it will always remove the top row that was added. Also when you click add a new user after you have clicked remove it doesn't automatically fill the blank space - it moves the new textbox and button to the bottom line.
Here is my code:
private void AddUserbtn_Click_1(object sender, EventArgs e)
{
TextBox[] Username = new TextBox[n];
Button[] Remove = new Button[n];
int UsernameX, UsernameY, RemoveX, RemoveY;
UsernameX = 346;
UsernameY = 45;
RemoveX = 946;
RemoveY = 45;
for (int i = 0; i < n; i++)
{
Username[i] = new TextBox();
Username[i].Size = new Size(233, 26);
Username[i].Location = new Point(UsernameX, UsernameY + space);
Username[i].Font = new Font("Arial", 10);
Username[i].Name = "Username" ;
Remove[i] = new Button();
Remove[i].Location = new Point(RemoveX, RemoveY + space);
Remove[i].Text = "Remove";
Remove[i].Font = new Font("Arial", 10);
Remove[i].Size = new Size(95, 23);
Remove[i].UseVisualStyleBackColor = true;
Remove[i].Click += new EventHandler(Remove_Click);
Remove[i].Name = "Remove";
space += 35;
}
for (int i = 0; i < n; i++)
{
CaeUsersPanel.Controls.Add(Username[i]);
CaeUsersPanel.Controls.Add(Remove[i]);
}
}
private void Remove_Click(object sender, EventArgs e)
{
CaeUsersPanel.Controls.Remove(CaeUsersPanel.Controls[("Username")]);
CaeUsersPanel.Controls.Remove(CaeUsersPanel.Controls[("Remove")]);
}
Put a class variant to store Button - TextBox pair, and delete respectively. Quick tested code below - not fine tuned for memory leak / logic etc, just a sample code that fulfills your requirement.
Dictionary<Button, TextBox> pair = new Dictionary<Button, TextBox>(); // A dictionary to store the Button - TextBox pair
private void button1_Click(object sender, EventArgs e) {
int n = 3; // Added for testing
int space = 0; // Added for testing
int UsernameX, UsernameY, RemoveX, RemoveY;
UsernameX = 100; // Modified for testing
UsernameY = 45;
RemoveX = 400; // Modified for testing
RemoveY = 45;
for (int i = 0; i < n; i++) {
var Username = new TextBox();
Username.Size = new Size(233, 26);
Username.Location = new Point(UsernameX, UsernameY + space);
Username.Font = new Font("Arial", 10);
Username.Name = "Username";
var Remove = new Button();
Remove.Location = new Point(RemoveX, RemoveY + space);
Remove.Text = "Remove";
Remove.Font = new Font("Arial", 10);
Remove.Size = new Size(95, 23);
Remove.UseVisualStyleBackColor = true;
Remove.Click += new EventHandler(Remove_Click);
Remove.Name = "Remove";
Controls.Add(Username);
Controls.Add(Remove);
pair.Add(Remove, Username);
space += 35;
}
}
private void Remove_Click(object sender, EventArgs e) {
Controls.Remove((Button)sender); // Removes the delete button
Controls.Remove(pair[(Button)sender]); // Removes the textbox
pair.Remove((Button)sender); // Removes the entry in dictionary
}
Update: Another version for better memory and logic matters. Also shifts up the rest of controls up if it's the OP's desire.
int n = 3; // Added for testing, probably you already have it somewhere
int space = 0; // Added for testing, probably you already have it somewhere
// Moved for logic
// Value modified for testing
int UsernameX = 100;
int UsernameY = 45;
int RemoveX = 400;
int RemoveY = 45;
int SpaceDelta = 35; // Added for logic
List<Button> RemoveButtons = new List<Button>();
List<TextBox> UsernameTextBoxes = new List<TextBox>();
private void button1_Click(object sender, EventArgs e) {
Random rnd = new Random((int)DateTime.Now.Ticks); // Added for testing
for (int i = 0; i < n; i++) {
var Username = new TextBox();
Username.Size = new Size(233, 26);
Username.Location = new Point(UsernameX, UsernameY + space);
Username.Font = new Font("Arial", 10);
Username.Name = "Username";
Username.Text = $"{(int)(rnd.NextDouble() * 100000)}"; // Added for testing
var Remove = new Button();
Remove.Location = new Point(RemoveX, RemoveY + space);
Remove.Text = $"{(int)(rnd.NextDouble() * 100000)}"; // Modified for testing
Remove.Font = new Font("Arial", 10);
Remove.Size = new Size(95, 23);
Remove.UseVisualStyleBackColor = true;
Remove.Click += new EventHandler(Remove_Click);
Remove.Name = "Remove";
Controls.Add(Username);
Controls.Add(Remove);
RemoveButtons.Add(Remove);
UsernameTextBoxes.Add(Username);
space += SpaceDelta;
}
}
private void Remove_Click(object sender, EventArgs e) {
int idx = RemoveButtons.IndexOf((Button)sender);
// Remove button
RemoveButtons[idx].Dispose();
RemoveButtons.RemoveAt(idx);
// Remove textbox
UsernameTextBoxes[idx].Dispose();
UsernameTextBoxes.RemoveAt(idx);
// Shift controls up
for (int i = idx; i < RemoveButtons.Count; i ++) {
RemoveButtons[i].Top -= SpaceDelta;
UsernameTextBoxes[i].Top -= SpaceDelta;
}
space -= SpaceDelta;
}
Remove the two last created :
private void Remove_Click(object sender, EventArgs e)
{
this.Controls.Remove(this.Controls[this.Controls.Count - 1]);
this.Controls.Remove(this.Controls[this.Controls.Count - 1]);
}

How to fetch data from a dynamically created textbox?

This is a follow up question for my previous question.
However in this question, I created such a Control so whenever I click on the button, two TextBoxes will appear (Indefinite count/click) in a row. Whenever I input again a value, they will do the addition and put the result in the third TextBox of their row.
private void buttonNewRow_Click(object sender, EventArgs e)
{
int count = 1;
DateTimePicker date = new DateTimePicker();
count = panel1.Controls.OfType<DateTimePicker>().ToList().Count;
date.Location = new Point(0, 15 * count);
date.Size = new Size(91, 20);
panel1.Controls.Add(date);
//Textbox 1
TextBox textboxTranspo = new TextBox();
textboxTranspo.Location = new Point(576, 45 * count);
textboxTranspo.Size = new Size(81, 20);
panel1.Controls.Add(textboxTranspo);
//Textbox 2
TextBox textboxDaily = new TextBox();
textboxDaily.Location = new Point(663, 45 * count);
textboxDaily.Size = new Size(81, 20);
panel1.Controls.Add(textboxDaily);
//Textbox 1 + Textbox 2 result
TextBox textboxTotal = new TextBox();
textboxTotal.Location = new Point(772, 45 * count);
textboxTotal.Size = new Size(100, 20);
panel1.Controls.Add(textboxTotal);
}
How can I accomplish this?
You can add event handlers like this:
private void buttonNewRow_Click(object sender, EventArgs e)
{
DateTimePicker date = new DateTimePicker();
int count = panel1.Controls.OfType<DateTimePicker>().ToList().Count;
date.Location = new Point(0, 15 * count);
date.Size = new Size(91, 20);
panel1.Controls.Add(date);
//Textbox 1
TextBox textboxTranspo = new TextBox();
textboxTranspo.Location = new Point(576, 45 * count);
textboxTranspo.Size = new Size(81, 20);
panel1.Controls.Add(textboxTranspo);
//Textbox 2
TextBox textboxDaily = new TextBox();
textboxDaily.Location = new Point(663, 45 * count);
textboxDaily.Size = new Size(81, 20);
panel1.Controls.Add(textboxDaily);
//Textbox 1 + Textbox 2 result
TextBox textboxTotal = new TextBox();
textboxTotal.Location = new Point(772, 45 * count);
textboxTotal.Size = new Size(100, 20);
panel1.Controls.Add(textboxTotal);
EventHandler textChanged = (o, e) => {
int intTranspo, intDaily;
if (int.TryParse(textboxTranspo.Text, out intTranspo)
&& int.TryParse(textboxDaily.Text, out intDaily))
textboxTotal.Text = (intTranspo + intDaily).ToString();
};
textboxTranspo.TextChanged += textChanged;
textboxDaily.TextChanged += textChanged;
}
I will address my comment above as an answer.
First you have to define a UserControl and named it whatever you like but let us name it Uc1.
In the designer drag the datetimepicker and the 3 textboxes to the Uc1. Supposed we name the control dt1 for datetimepicker and txtTranspo for textbox1 and txtDaily for textbox2 and txtTotal for the last one. And since we need to compute the value of txtTranspo and txtDaily i want to add 1 button named btnCompute for computation logic for simplicity sake.
then inside the Uc1
class Uc1
{
public Uc1()
{
InitializeComponent();
this.wireEvents();
}
// This will handle all controls events for well organized form sakes.
private void wireEvents()
{
this.btnCompute.Click += OnBtnComputeEvent;
}
private void OnBtnComputeEvent(object sender, EventArgs e)
{
// i used int since i do not know exactly how to do this.
int transpo = Int32.Parse(this.txtTranspo.Text);
int daily = Int32.Parse(this.txtDaily.Text);
double total = ((transpo + daily) / 100 * 100) // <--- this is just a random computation.
this.txtTotal.Text = string.Format("{0:c}", total); // this will format the total to a currency.
}
}
Then build the solution. or click the combination of Ctrl + Shift + B. After this the Uc1 will appear to your toolbox as a new control.
Then you can simply do this to your own logic.
private void buttonNewRow_Click(object sender, EventArgs e)
{
Uc1 c = new Uc1();
c.Dock = DockStyle.Top;
c.BringToFront();
this.panel.Controls.Add(c);
}
You are good to go.

Multiple CheckedChanged event on programmatically added checkboxes

I want to be able to assign each checkbox to it's own richtextbox
I'm making the richtextboxes, then I'm making the checkboxes but how can I "link" them together?
for example :
// richtextbox 1 - > checkbox 1 = false
// richtextbox 2 - > checkbox 2 = true
// richtextbox 3 - > checkbox 3 = true
// richtextbox 4 - > checkbox 4 = false
this is my code:
int n = TodoItems.Count;
RichTextBox[] RichtextBoxes = new RichTextBox[n];
CheckBox[] Checkboxes = new CheckBox[n];
for (int i = 0; i < n; i++)
{
//creating the richtextbox
RichtextBoxes[i] = new RichTextBox();
RichtextBoxes[i].Name = "TB" + i.ToString();
RichtextBoxes[i].Text = TodoItems[i].ToString();
RichtextBoxes[i].Location = new System.Drawing.Point(130, (10 + (60 * i)));
RichtextBoxes[i].Size = new System.Drawing.Size(300, 50);
RichtextBoxes[i].Visible = true;
RichtextBoxes[i].ReadOnly = true;
RichtextBoxes[i].SelectionAlignment = HorizontalAlignment.Center;
RichtextBoxes[i].BackColor = Color.White;
TodoList.Controls.Add(RichtextBoxes[i]);
//creating the checkboxes
Checkboxes[i] = new CheckBox();
Checkboxes[i].Name = "CB" + i.ToString();
Checkboxes[i].Text = "";
Checkboxes[i].Location = new System.Drawing.Point(440, (30 + (60 * i)));
Checkboxes[i].Size = new System.Drawing.Size(18, 17);
Checkboxes[i].Visible = true;
Checkboxes[i].CheckedChanged += new EventHandler(this.CheckedChange);
TodoList.Controls.Add(Checkboxes[i]);
}
I have modified your code please see below, you can access your desired rich text box on checkbox click.
RichTextBox[] RichtextBoxes { get; set; }
CheckBox[] Checkboxes { get; set; }
private void Form1_Load(object sender, EventArgs e)
{
int n = TodoItems.Count;
RichtextBoxes = new RichTextBox[n];
Checkboxes = new CheckBox[n];
for (int i = 0; i < n; i++)
{
//creating the richtextbox
RichtextBoxes[i] = new RichTextBox();
RichtextBoxes[i].Name = "TB-" + i.ToString();
RichtextBoxes[i].Text = TodoItems[i].ToString();
RichtextBoxes[i].Location = new System.Drawing.Point(130, (10 + (60 * i)));
RichtextBoxes[i].Size = new System.Drawing.Size(300, 50);
RichtextBoxes[i].Visible = false;
RichtextBoxes[i].ReadOnly = true;
RichtextBoxes[i].SelectionAlignment = HorizontalAlignment.Center;
RichtextBoxes[i].BackColor = Color.White;
TodoList.Controls.Add(RichtextBoxes[i]);
//creating the checkboxes
Checkboxes[i] = new CheckBox();
Checkboxes[i].Name = "CB-" + i.ToString();
Checkboxes[i].Text = "";
Checkboxes[i].Location = new System.Drawing.Point(440, (30 + (60 * i)));
Checkboxes[i].Size = new System.Drawing.Size(18, 17);
Checkboxes[i].Visible = true;
Checkboxes[i].CheckedChanged += checkBox1_CheckedChanged;
TodoList.Controls.Add(Checkboxes[i]);
}
}
void checkBox1_CheckedChanged(object sender, EventArgs e)
{
CheckBox cb = sender as CheckBox;
string cbName = cb.Name;
int sbNumber = int.Parse(cbName.Split('-')[1]);
RichtextBoxes[sbNumber].Visible = true; // you can get desired richtextbox here and can any thing with it :)
}
I have found the answere, and I'll post it to make your life easyer
when I made the richtextboxes and the checkboxes I set there names to a number
Checkboxes[i].Name = i.ToString();
then I used the event that was provided for me by Mirza Danish Baig
Create and event void checkBox_CheckedChanged(object sender, EventArgs e) { } and then assign this event name Checkboxes[i].CheckedChanged += checkBox_CheckedChanged; –
and after that I started to try things eventualy I came to this :
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox ThisCheckbox = (CheckBox)sender;
if (ThisCheckbox.Checked == true)
{
//finding the richtextbox by id...
RichTextBox ThisRichtextbox = this.Controls.Find("TB" + ThisCheckbox.Name, true).FirstOrDefault() as RichTextBox;
try//try and catch for testing, this can be removed later.
{
MessageBox.Show(ThisRichtextbox.Text);
}
catch (Exception Exc)
{
MessageBox.Show(Exc.Message);
}
}
}

Categories

Resources