Passing more objects with eventhandler - c#

I was reading similar questions about overloading eventhandlers by not using eventhandlers but delegates or by calling other functions from within the eventhandler. But I really can't see how I can bind the delegate to the custom control like I am binding ButtonClick in the code below. I have a form with let's say 10 custom controls. Each custom control has 5 buttons. The way I am passing the key presses from each button of each custom control is:
This is in my custom control's cs file (GlobalDebugMonitorControl.cs)
namespace GlobalDebugMonitor
{
public partial class GlobalDebugMonitorControl : UserControl
{
public GlobalDebugMonitorControl()
{
InitializeComponent();
}
public event EventHandler ButtonClick;
private void MultiControl_Click(object sender, EventArgs e)
{
if (this.ButtonClick != null)
this.ButtonClick(sender, e);//**How Do I put here both sender and this**
}
}
}
Then all the buttons in the custom control.designer.cs have something like this:
this.openFileBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.editFilePathBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.delControlBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.addControlBTN.Click += new System.EventHandler(this.MultiControl_Click);
this.editCompanyNameBTN.Click += new System.EventHandler(this.MultiControl_Click);
And then in my form1
namespace GlobalDebugMonitor
{
public partial class Form1 : Form
{
protected void UserControl_ButtonClick(object sender, EventArgs e)
{
Button tempButton = (Button)sender;
GlobalDebugMonitorControl tempParentControl = (GlobalDebugMonitorControl)((tempButton.Parent).Parent).Parent;
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (string item in tempGlobalPaths)
{
GlobalDebugMonitorControl tempGDMcontrol = new GlobalDebugMonitorControl();
tempGDMcontrol.Name = item.Split(',')[0];
tempGDMcontrol.companyNameLBL.Text = item.Split(',')[0];
tempGDMcontrol.globalPathTXT.Text = item.Split(',')[1];
tempGDMcontrol.ButtonClick += new EventHandler(UserControl_ButtonClick);
flowLayoutPanel1.Controls.Add(tempGDMcontrol);
}
}
}
}
As you can see I create a tempButton by the sender to do some things based on which button was pressed of the 5 and by sender.parent.parent (the custom control is inside a table that is inside a flowlayout that is inside another panel etc)I finally reach the custom control that tells me which of the 10 custom controls had it's button pressed.
So the question is, is there a way to pass both the sender(button that was pressed) and the great grandfather (the custom control that owns the sender button)? I mean it works but this way I need to now how many "generations" I need to go up.
Thank you for reading me.

You could introduce your own type of EventArgs
public class CustomEventArgs : EventArgs
{
public GlobalDebugMonitorControl Control { get; set; }
public CustomEventArgs(GlobalDebugMonitorControl control)
{
this.Control = control;
}
}
and then change eventHandler to use it:
public event EventHandler<CustomEventArgs> ButtonClick;
so the calling code would be:
this.ButtonClick(sender, new CustomEventArgs(this));
and of course the implementer of the event:
protected void UserControl_ButtonClick(object sender, CustomEventArgs e)
{
Button tempButton = (Button)sender;
GlobalDebugMonitorControl tempParentControl = e.Control;
}

Related

C# Event name is null

I have a WinForms application wherein I have my main application with a separate class that is part of the solution. In the class which is defining a User control with Dev Express buttons, I have defined my event delegate, event, method and eventargs.
In the main program, i have defined my listener.
I am getting a null value in my event method and cannot see why. I have reviewed this a number of times and as far as I can see, it is completely correct.
I would appreciate any comments/corrections that would be useful here.
This is the code in my class.
public partial class XtraUserControl1 : XtraUserControl, IAnyControlEdit
{
public delegate void ButtonClickedEventHandler(object sender, ClickEventArgs e);
public event ButtonClickedEventHandler ButtonClicked;
public XtraUserControl1()
{
InitializeComponent();
}
public void OnButtonClicked(ClickEventArgs e)
{
if (ButtonClicked != null)
{
ButtonClicked(this, e);
}
}
public class ClickEventArgs : EventArgs
{
public readonly SimpleButton buttonClicked;
public ClickEventArgs(SimpleButton button)
{
this.buttonClicked = button;
}
}
This is the main code where I have defined the listener.
private void frmEHHeaders_Load(object sender, EventArgs e)
{
// Create the button group from the User Control XtraUserControl1 and add it to the grid repository
btnGroup = new User_Controls.XtraUserControl1();
RepositoryItemAnyControl riAny = new RepositoryItemAnyControl();
riAny.Control = btnGroup;
grdEHHeaders.RepositoryItems.Add(riAny);
colButtons.ColumnEdit = riAny;
// Add event handlers
this.grdEHHeaders.Views[0].MouseDown += gridView1_MouseDown;
gridView1.CustomRowCellEdit += GridView1_CustomRowCellEdit;
// Listener for the button class
btnGroup.ButtonClicked += new User_Controls.XtraUserControl1.ButtonClickedEventHandler(btnGroup_ButtonClicked);
GetData();
}
private void btnGroup_ButtonClicked(object sender, User_Controls.XtraUserControl1.ClickEventArgs e )
{
SimpleButton myButton = e.buttonClicked;
MessageBox.Show("You clicked " + myButton.Text);
}

How do I can call event from usercontrol to main form

I have a userControl and I've a button there, I'd like to call event when I'm clicking on the button in my main form from userControl. I do this:
UserControl
public UserControlerConstructor()
{
_button.Click += new EventHandler(OnButtonClicked);
}
public delegate void ButtonClickedEventHandler(object sender, EventArgs e);
public event ButtonClickedEventHandler OnUserControlButtonClicked;
private void OnButtonClicked(object sender, EventArgs e)
{
// Delegate the event to the caller
if (OnUserControlButtonClicked != null)
OnUserControlButtonClicked(this, e);
}
Form
public Form1()
{
userControlInstance.OnUserControlButtonClicked += new EventHandler(OnUCButtonClicked);
}
private void OnUCButtonClicked(object sender, EventArgs e)
{
throw new NotImplementedException();
}
It doesn't work because when I click in the form do nothing in the form code, but it does in userControl code. But I'd like to do in form code. I don't know how to call event from userControl to the form.
Well now I don't know if you're explicity want to use the delegate, no? If not, why don't you just do:
public Form1()
{
userControlInstance._button.Click += OnUCButtonClicked;
}
private void OnUCButtonClicked(object sender, EventArgs e)
{
throw new NotImplementedException();
}
up to now your code does not compile. You are using the wrong event handler type. It should show the following compiler error:
EventHandler cannot be converted to ButtonClickedEventHandler
Do the following steps:
1) put the declaration of the delegate outside of the class UserControlerConstructor:
public delegate void ButtonClickedEventHandler(object sender, EventArgs e);
public partial class UserControlerConstructor: UserControl
{
1) then change the type of the handler when registering the event in Form:
public Form1()
{
userControlInstance.OnUserControlButtonClicked += new ButtonClickedEventHandler(OnUCButtonClicked);
}
This way it should work

Field System.MulticastDelegate._invocationCount is not available c#

I've tried to use event from an userControl to a form, but when I'm creating it in a form constructor I've an issue. I don't know where is a fail. There is my code.
UserControl
public GameField()
{
InitializeComponent();
button.Click += Button_Clicked;
}
public event EventHandler ButtonClicked;
private void Button_Clicked(object sender, EventArgs e)
{
if (this.ButtonClicked != null) this.ButtonClicked(sender, e);
}
Form
GameField gameField = new GameField(); //Instance of the derived class UserControl
public Form1()
{
InitializeComponent();
gameField.ButtonClicked += new EventHandler(this.btn_Click);
}
private void btn_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
There is an issue
enter image description here
I think you wanted to subscribe to Button_Clicked instead of ButtonClicked in GameField.
button.Click += Button_Clicked;
Edit
I see, I have a hunch that you have two instances of GameField. The one that you added through the forms designer, probably named gameField1 and the one that you added in code to your form called gameField.
If you open Form1.Designer.cs can you see a gameField1 in there (or whatever name you gave when you added it through the designer)?
Can you try the following:
gameField1.ButtonClicked += new EventHandler(btn_Clicked); // name can be other than gameField1, gameField1 is just the automatically generated name by VS

Invoke my forms method from my custom control within my other custom control

Had a look on here and found several examples but they don't seem to fit my exact problem and through experimentation I can't work it out.
Current code for form...
public partial class Form1 : Form
{
DualCombo dc = new DualCombo();
public Form1()
{
InitializeComponent();
this.Controls.Add(dc);
}
private void MyMethod()
{
MessageBox.Show(dc.c1.Text + dc.c2.Text);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
The control that contains 2 of my custom combos...
public class DualCombo : UserControl
{
public CustomCombo c1 = new CustomCombo();
public CustomCombo c2 = new CustomCombo();
public DualCombo()
{
c1.Items.Add("One");
c1.Items.Add("Two");
c1.Items.Add("Three");
c2.Left = c1.Right;
c2.Items.Add("One");
c2.Items.Add("Two");
c2.Items.Add("Three");
this.Controls.Add(c1);
this.Controls.Add(c2);
}
}
I have left the code from the custom combo blank to keep the example simple...
public class CustomCombo : ComboBox
{
}
I would like my custom combo OnSelectedIndex changed to trigger the following method that is in the form...
private void MyMethod()
{
MessageBox.Show(dc.c1.Text + dc.c2.Text);
}
The easiest solution is to subscribe to that event directly:
public Form1()
{
InitializeComponent();
this.Controls.Add(dc);
dc.c1.SelectionChangedEvent += (s, e) => MyMethod();
}
But this is bad idea to make c1 public, read further.
UserControl is encapsulated control with some functionality. If you need to inform someone who is using that UserControl about something simple create an event:
Add event to UserControl
public EventHandler SomeEvent;
protected void OnSomeEvent() => SomeEvent?.Invoke(this, EventArgs.Empty);
Fire it when selection is changed from within UserControl
protected CustomCombo c1 = new CustomCombo();
public DualCombo()
{
c1.SelectedIndexChanged += (s, e) => OnSomeEvent();
...
}
Now you can subscribe to that event in your form (where this UserControl is used):
DualCombo dc = new DualCombo();
public Form1()
{
InitializeComponent();
this.Controls.Add(dc);
dc.SomeEvent += (s, e) => MyMethod(); // call your method
}
Tips: do not make controls inside UserControl public. Think about UserControl as a black box.

Can't access event in

I've got a problem with subscribing from a form to an event in an user control.
MainForm-Code:
public partial class mainForm : Form
{
public mainForm()
{
InitializeComponent();
UserControl menuView = new mnlib.mnlibControl();
newWindow(menuView);
}
public void newWindow(UserControl control)
{
this.mainPanel.Controls.Clear();
this.mainPanel.Controls.Add(control);
}
mnlibControl.OnLearnClick += new EventHandler(ButtonClick); //Error in this line
protected void ButtonClick(object sender, EventArgs e)
{
//handling..
}
}
UserControl-Code:
public partial class mnlibControl : UserControl
{
public mnlibControl()
{
InitializeComponent();
}
private void btn_beenden_Click(object sender, EventArgs e)
{
Application.Exit();
}
public event EventHandler LearnClick;
private void btn_lernen_Click(object sender, EventArgs e)
{
if (this.LearnClick != null)
this.LearnClick(this, e);
}
}
Now, visual studio marks the "mnlibControl.OnLearnClick ..." line as wrong. "mnlibControl" would not be found, maybe a missing using directive etc. .
All this code and both forms are located in the same project file.
I tried around and googled like hell but just can't find a solution for my problem.
In the UserControl form there is a button - when it's clicket it shall trigger the newWindow method in the mainForm and open up another window.
My source for this solution of my problem is: How do I make an Event in the Usercontrol and Have it Handeled in the Main Form?
There is no OnLearnClick in your component. You need to subscribe to LearnClick. You also need to subscribe in function block. You also should use concrete type (mnlib.mnlibControl), not UserControl:
public mainForm()
{
InitializeComponent();
mnlib.mnlibControl menuView = new mnlib.mnlibControl();
menuView.LearnClick += new EventHandler(ButtonClick);
newWindow(menuView);
}
Your code mnlibControl.OnLearnClick += new EventHandler(ButtonClick); must be within any of functional block (i.e. method, property, ...).
You have to place this line inside an actual method:
mnlibControl.LearnClick += new EventHandler(ButtonClick);
Like this:
public mainForm()
{
InitializeComponent();
UserControl menuView = new mnlib.mnlibControl();
newWindow(menuView);
mnlibControl.OnLearnClick += new EventHandler(ButtonClick);
}

Categories