Search code examples
c#user-controlsdetectbuttonclickeventhandler

Dynamically created User Control detecting button click from main Form


I have been trying to figure this out for the better part of two days and have searched everywhere to find a solution, so if this is easily answered I apologize up front. Also, I am fairly new to c# and programming in general.

I have a wherein one button creates a new . This user control has a listview (for now, at some point I'm probably going to change this to a datagridview) that is updated with information from an Access database. When another button (Save) on the Form is clicked, information is added to the database. I would like for my UserControl to detect when the Save button is clicked and update the listview.

Below is a sample from my code, trimmed down to what I hope are the important bits.

Form stuff.

public partial class Form1 : Form
{
    public event EventHandler saveClick;

    public Form1()
    {
        InitializeComponent();
    }

    public void buttonSave_Click(object sender, EventArgs e)
    {
        //Stuff happens here that saves all input to the database
        if (this.saveClick != null)
            this.saveClick(this, e);            
    }

    //Creates the UserControl TodayCallHistory as tch and expands Form1 window to accomodate the new control
    private void butListShow_Click(object sender, EventArgs e)
    {
        if (!expanded)
        {
            expanded = true;
            butListShow.Text = "\u25C0";
            TodayCallHistory tch = new TodayCallHistory();
            tch.Name = "tch";
            tch.SetParentForm(this); //This was added per the answer below
            List<int> pos = new List<int>();
            foreach (Control x in this.Controls)
            {
                int right = x.Right;
                pos.Add(right);
            }
            tch.Location = new System.Drawing.Point(pos.Max() + 10, 10);
            formWidth = this.Width;
            this.Width = this.Width + tch.Width + 10;
            this.Controls.Add(tch);
        }
        else
        {
            expanded = false;
            butListShow.Text = "\u25B6";
            foreach (Control x in this.Controls)
            {
                if (x.Name == "tch")
                    this.Controls.Remove(x);
            }
            this.Width = formWidth;
        }
    }
}

UserControl stuff.

public partial class TodayCallHistory : UserControl
{
    private Form1 frm = new Form1();

    public TodayCallHistory()
    {
        InitializeComponent();
        //frm.saveClick += new EventHandler(saveWasClicked); Removed based on answer below
    }

    //This following part was added per the marked answer below
    public void SetParentForm(Form1 parent)
    {
        frm = parent;
        frm.saveClick += new EventHandler(saveWasClicked);
    }

    private void saveWasClicked(object sender, EventArgs e)
    {
        refreshList();
    }

    private void refreshList()
    {
        //Sends query to database and then populates a listview with this information
    }
}

When the Save button is clicked on the Form, nothing happens on the UserControl. Just a big ole pile of nothing. If anyone can tell me what I'm doing wrong or a better way to approach this, I would be extremely grateful! I can also post more of my code if I'm not sharing enough.

EDIT 1: I should also mention that this is a WinForm, written in c# using Visual Studio Express 2015 for Windows Desktop.

EDIT 2: Added my code for creating the UserControl when a button is clicked on Form1. The same button also removes the control. Basically I wanted to have an "expand window" (I have no idea what the actual term should be) feature as part of my Form1.

EDIT 3: Using Harrison Paine's (not sure how to tag a username) suggestion below, I added the SetParentForm method to the UserControl. Since my UserControl isn't created until the button click on Form1, I had to add the SetParentForm on Form1 after it was created.

Right after

tch.Name = "tch";

I added

tch.SetParentForm(this);

EDIT 4: So as to avoid creating a new Form1, I made the following changes.

Form1

public static event EventHandler saveClick; //Added static modifier 

public void buttonSave_Click(object sender, EventArgs e)
{
    //Stuff happens here that saves all input to the database
    if (Form1.saveClick != null)
        Form1.saveClick(this, e); //Changed this.saveClick to Form1.saveClick 
}

private void butListShow_Click(object sender, EventArgs e)
{
tch.Parent = this; //All the other stuff from above, plus this now
}

I changed this.saveClick to Form1.saveClick since it is has the static modifier (I mostly guessed I had to do this and am still working on understanding exactly what 'static' does hah)

UserControl

    public TodayCallHistory()
    {
        Form1.saveClick += new EventHandler(saveWasClicked);
        InitializeComponent();
    }

I removed the Form1 frm = new Form1(); as well as the entire SetParentForm method.

For those wondering why I didn't just have the UserControl created and always there, with just a .Visible set to True or False, I determined after much reading that the "better practice" is to create and destroy controls as you need them, especially if you have a lot of them on a form. If I'm completely off-base/insane on this, please let me know so I can take the easy way out :)


Solution

  • It looks like your TodayCallHistory is creating its own Form1 and listening to an event on that object.

    You need to pass in the actual Form1 that has the user control and then register the event handler on that object.

    Something like this:

    In TodayCallHistory.cs:

    public void SetParentForm(Form1 parent)
    {
        frm = parent;
        frm.SaveClick += new EventHandler(saveWasClicked);
    }
    

    In Form1.cs:

    public Form1
    {
        InitializeComponent();
        this.myTodayCallHistory.SetParentForm(this);
    }
    

    The issue stems from the following:

    public partial class TodayCallHistory : UserControl
    {
        private Form1 frm = new Form1();
    

    The Form1 created here is an entirely different object than the "original" one, whose save button you are clicking. Instead of creating a brand new object, you need to pass the original one in somehow. The SetParentForm() method is just one way to do this.