c# access button click event from inside a UserControl

I have a form that contains several user controls.

I need to call code on 1 user control when a button is clicked on another user control.

How is this best achieved?
LVL 1
jetbetAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Karrtik IyerSoftware ArchitectCommented:
My suggestion at a high level: The button click on user control1 should be exposed to the form.
The form registers for a call back (delegate)  for that click event exposed from user control1.
In the code of delegate, form calls the user control2 functionality exposed as public method.
0
it_saigeDeveloperCommented:
At it's simplest:

UserControl1.cs -
using System;
using System.Windows.Forms;

namespace EE_Q28822020
{
	public partial class UserControl1 : UserControl
	{
		[NonSerialized]
		private EventHandler fClick;
		public event EventHandler Click 
		{
			add { fClick += value; }
			remove { fClick -= value; }
		}

		protected void OnClick(object sender, EventArgs e)
		{
			EventHandler handler = fClick;
			if (fClick != null)
				handler(sender, e);
		}

		public UserControl1()
		{
			InitializeComponent();
			button1.Click += OnClick;
			button2.Click += OnClick;
		}
	}
}

Open in new window

UserControl1.Designer.cs -
namespace EE_Q28822020
{
	partial class UserControl1
	{
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Component Designer generated code

		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(4, 4);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(75, 23);
			this.button1.TabIndex = 0;
			this.button1.Text = "button1";
			this.button1.UseVisualStyleBackColor = true;
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(86, 3);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(75, 23);
			this.button2.TabIndex = 1;
			this.button2.Text = "button2";
			this.button2.UseVisualStyleBackColor = true;
			// 
			// UserControl1
			// 
			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			this.Controls.Add(this.button2);
			this.Controls.Add(this.button1);
			this.Name = "UserControl1";
			this.Size = new System.Drawing.Size(167, 34);
			this.ResumeLayout(false);

		}

		#endregion

		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
	}
}

Open in new window

Form1.cs -
using System;
using System.Windows.Forms;

namespace EE_Q28822020
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void OnClick(object sender, EventArgs e)
		{
			if (sender is Button)
			{
				Button btn = sender as Button;
				if (btn.Parent == this)
					MessageBox.Show(string.Format("I am {0} from the main form.", btn.Name));
				else if (btn.Parent == userControl11)
					MessageBox.Show(string.Format("I am {0} from the user control.", btn.Name));
			}
		}
	}
}

Open in new window

Form1.Designer.cs -
namespace EE_Q28822020
{
	partial class Form1
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.userControl11 = new EE_Q28822020.UserControl1();
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// userControl11
			// 
			this.userControl11.Location = new System.Drawing.Point(5, 41);
			this.userControl11.Name = "userControl11";
			this.userControl11.Size = new System.Drawing.Size(167, 34);
			this.userControl11.TabIndex = 0;
			this.userControl11.Click += new System.EventHandler(this.OnClick);
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(10, 12);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(75, 23);
			this.button1.TabIndex = 1;
			this.button1.Text = "button1";
			this.button1.UseVisualStyleBackColor = true;
			this.button1.Click += new System.EventHandler(this.OnClick);
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(91, 12);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(75, 23);
			this.button2.TabIndex = 2;
			this.button2.Text = "button2";
			this.button2.UseVisualStyleBackColor = true;
			this.button2.Click += new System.EventHandler(this.OnClick);
			// 
			// Form1
			// 
			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			this.ClientSize = new System.Drawing.Size(184, 87);
			this.Controls.Add(this.button2);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.userControl11);
			this.Name = "Form1";
			this.Text = "Form1";
			this.ResumeLayout(false);

		}

		#endregion

		private UserControl1 userControl11;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
	}
}

Open in new window

Which produces the following output -The top row buttons are the form buttons.  The bottom row buttons are the user control buttons.Pressing button2 from the top row produces the following message.Pressing button1 in the second row produces the following results.-saige-
0
jetbetAuthor Commented:
Forgive me if I am wrong, but all these answers seem to assume I want to pass total control to either the main form or to the other control.

What I need to do is call a function on the Main form or other UserControl as PART of the onClick method of the first user control.

The user control has a reference to an object on the main Form that I could use but I only seem to be able to pass a generic Form object not the actual MainForm object so I could call the method there.

inRaceSceneControl = new InRaceSceneControl(vizCommand, vizCommandPreview, this);

Open in new window


public InRaceSceneControl(Viz_ability.VizCommands.VizCommand _vizMain, Viz_ability.VizCommands.VizCommand _vizPreview, Form _parent)

Open in new window


namespace NZRB_GUI
{
    public partial class FrmMain : Form
    {

Open in new window


If I could pass a FrmMain rather than a Form then the problem would be solved but even adding a using NZRB_GUI clause does not work as it cannot find Frm or NZRB_GUI from the InRaceSceneControl class.
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

jetbetAuthor Commented:
@it_saige
I am trying your code with the idea of calling the main code and then calling the UserControl code from the Main form.
Unfortunately fclick is always null and I cannot see where it is set
0
Karrtik IyerSoftware ArchitectCommented:
Two options I can think of :
1) type cast last parameter _parent which is of Form type to FrmMain, something like
FrmMain var =_parent as FrmMain
2) Change the type of the last parameter of your user control constructor to FrmMain _parent instead of Form.
But I don't suggest either of this, if
1) User control could be a generic user control which ideally should not be aware of specific Forms like FrmMain. In both the above solutions, the user control needs to know that the type of form creating it is or shall be of type FrmMain. This makes a tight coupling between the user control and the form which uses it.
For me it defeats the whole purpose of user control if it was designed to be used across different forms which are not necessarily of type FrmMain.
2) I still suggest, as I mentioned in my earlier comment to expose a new event in user control, and on button click in the user control, raise that new event.
3) This new event shall be handled by the form, and in that event handling code form shall invoke necessary functionality of user control 2.
0
it_saigeDeveloperCommented:
fClick is set when you bind to the Click event handler of the user control.  If you look in Form1.Designer.cs you will find the line that shows where I bind to the Click event.Capture.JPG-saige-
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jetbetAuthor Commented:
Thanks for that. Yes I had somehow missed that binding.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.