Assume you designed a Form, 'Form1, and two UserControls, 'TestUC1, 'TestUC2.
Both UserControls have a Button Control: TestUC1 has 'btnShowTestUC2 ... TestUC2 has 'btnShowTestUC1.
I'll start with showing you two variations of the standard ways to create Events in C#, then, we'll show you a technique that is radically simpler.
Here's a quick sketch:
private void Form1_Load(object sender, EventArgs e)
{
testUC11.MakeUC2Visible += testUC11_OnMakeUC2Visible;
testUC21.MakeUC1Visible += testUC21_OnMakeUC1Visible;
testUC21.Visible = false;
}
private void testUC21_OnMakeUC1Visible(object sender, EventArgs e)
{
testUC11.Visible = true;
testUC21.Visible = false;
}
private void testUC11_OnMakeUC2Visible(object sender, EventArgs e)
{
testUC21.Visible = true;
testUC11.Visible = false;
}
The UserControls:
public partial class TestUC1 : UserControl
{
public TestUC1()
{
InitializeComponent();
}
public delegate void MakeUC2VisibleEventHandler(object sender, EventArgs e);
public event MakeUC2VisibleEventHandler MakeUC2Visible;
protected virtual void OnMakeUC2Visible(EventArgs e)
{
if (MakeUC2Visible != null) MakeUC2Visible(this, e);
}
private void btnShowTestUC2_Click(object sender, EventArgs e)
{
OnMakeUC2Visible(e);
}
}
public partial class TestUC2 : UserControl
{
public TestUC2()
{
InitializeComponent();
}
public event EventHandler MakeUC1Visible;
protected virtual void OnMakeUC1Visible(EventArgs e)
{
EventHandler handler = MakeUC1Visible;
if (handler != null) handler(this, e);
}
private void btnShowTestUC1_Click(object sender, EventArgs e)
{
OnMakeUC1Visible(e);
}
}
Note 0: EventHandlers for the UserControls defined in the Form
Note 1: The "older" style of Event declaration requires both Delegate and Event.
Note 2: The "newer" style ... available with .NET 2.0 and later ... does not require an explicit Delegate
Yes, you're right: we did a lot of shifting cargo just to get a notification of an event passed out to the UserControl's container (the Form). Is there a simpler way: try this:
private void Form1_Load(object sender, EventArgs e)
{
testUC11.BtnAction = setUCVisibility;
testUC21.BtnAction = setUCVisibility;
}
private void setUCVisibility(UserControl userControl)
{
if (userControl is TestUC1)
{
testUC11.Visible = false;
testUC21.Visible = true;
}
else
{
testUC21.Visible = false;
testUC11.Visible = true;
}
}
The UserControls:
public Action<UserControl> BtnAction;
private void btnShowTestUC2_Click(object sender, EventArgs e)
{
if (BtnAction != null) BtnAction(this);
}
public Action<UserControl> BtnAction;
private void btnShowTestUC1_Click(object sender, EventArgs e)
{
if (BtnAction != null) BtnAction(this);
}
We declared a Public delegate of Type Action (an Action always has no return value, and, in this case, takes one parameter) [
^] in each UserControl. In each UserControl's Button Click EventHandler we invoke the action, passing a reference to the UserControl instance the Button is 'in.
Technically, what this example does is
inject a reference to a method at run-time into the instances of the UserForms. One could argue that this, like the other ways of raising events shown, results in loose-coupling between the UserControls and their "consumers:" there's no direct-linkage, no dependency, between the Form and the UserControls code. The UserControls "don't know" who/what inserts a method whose signature matches the Action declared in their code, or what that method will do when executed.
In the Form we define one method, setUCVisibility, which is assigned to the 'Action delegate in both UserControls. In this method, we detect which UserControl fired the 'Action and do the right thing to modify which UserControl is visible, which is hidden.