Essentially, my problem is that I have a program that dynamically creates controls. The Controls included are buttons and on click I want the buttons to remove themselves and all related data. The problem is I'm not sure how to identify the buttons from within the delete method.

The important part of the code is this :

...
        public void loadEntries()
        {
            TextReader input;
            try
            {
                input = new StreamReader("data.txt");
            }
            catch (IOException) //file does not exist, can not load previous entries.
            {
                return;
            }
            data = new Entry[Int32.Parse(input.ReadLine())];
            Label[] list = new Label[data.Length];
            Button[] del = new Button[data.Length];

            for (int i = 0; i < data.Length; i++)
            {
                data[i] = new Entry();
                list[i] = new Label();
                del[i] = new Button();

                data[i].name = input.ReadLine();
                
                list[i].Left = 0;
                list[i].Top = i * 25;
                list[i].Text = data[i].name;

                del[i].Top = i * 25;
                del[i].Left = 100;
                del[i].Text = "delete";
                del[i].Click += new EventHandler(delete);
                
                splitContainer1.Panel2.Controls.Add(list[i]);
                splitContainer1.Panel2.Controls.Add(del[i]);
            }
            
        }
...
        private void delete(object sender, EventArgs e)
        {
               /*Essentially this method needs to delete(dispose if you want to be technical) its sender; however, the programmer doesn't know which Control calls this eventhandler*/
        }

I'm sorry if this is a simple problem.

Dani AI

Generated

Good catch by — casting the event sender to the control type is the right first step. Relying on the control position (Top / LINELENGTH) as the unique identifier will work in simple cases but is fragile: resizing, a layout container, DPI changes, insertion/removal that shifts controls, or switching to a different layout will break the math.

A more robust pattern is to attach the identity or the actual data object to the button when it is created, or capture the item in a lambda so the handler already knows which Entry to remove. For example, capture the Entry reference when wiring the click (no positional math required):

var entry = data[i];
del.Click += (s, e) => RemoveEntry(entry);

RemoveEntry should remove the Entry from the backing collection, remove/dispose the associated controls (or rebuild the UI from the collection), and persist the change to disk if needed.

Practical notes: storing an index in Button.Tag is simple but then indices must be updated after removals; storing the Entry object in Tag or using the closure avoids that. Use a FlowLayoutPanel or TableLayoutPanel to avoid manual Top calculations so repositioning is automatic. When controls are removed, either update remaining controls' identifiers or rebuild the UI from a List<Entry>. Dispose controls and, if handlers are long-lived, unsubscribe to avoid leaks. For larger apps, consider a UserControl per entry or a bound grid (DataGridView/ListView) with a delete column for cleaner, maintainable code.

Doh I figured out the answer.
Sorry about that.
In case someone else has a similar problem the Answer my own problem.

The question can be rephrased to "How do you access elements of the sender"
You can do a typecast for the sender as follows:

private void delete(object sender, EventArgs e)
        {
            Button temp = (Button)sender;
        }

That will allow you to access the individual elements. After this the actual issue of identifying the control is really dependent on what the control is. What I did is I checked all of the members of the array and compared their unique data to the sender.

For simplicity I have seperated the load function previously shown and broken it into the actually retrieving from the file and the actual displaying to the form.

public void display()//complete
        {
            int line = 0;
            for (int i = 0; i < data.Length; i++)
            {
                
                if (data[i].name == null)
                {
                    continue;
                }
                
                list[i].Left = 0;
                list[i].Top = line * LINELENGTH;
                list[i].Text = data[i].name;

                del[i].Top = line * 25; // <== ***IMPORTANT: Unique Identifier***
                del[i].Left = 100;
                del[i].Text = "delete";
                del[i].Click += new EventHandler(delete);

                splitContainer1.Panel2.Controls.Add(list[i]);
                splitContainer1.Panel2.Controls.Add(del[i]);
                line++;
            }
        }

The comparison goes like this :

private void delete(object sender, EventArgs e)
        {
            Button temp = (Button)sender;
            int num = 0;
            while (num != (temp.Top / LINELENGTH))
                num++;

            list[num].Dispose();
            del[num].Dispose();
            data[num].name = data[num].ally = null;
            data[num].x = data[num].y = 0;
        }

Sorry about the waste of time for those of you who read, it came to me after I posted.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.