Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to call a callback function on a GUI event? Delegates?

I’m very new to C# and I’m wondering if using delegates is the right way here:

I created a UserControl in Visual Studio Windows Forms Designer.
In a TableLayoutPanel I have 3 x 3 of these UserControls. Each of them gets a row and col index through the constructor.

Now in my Form that contains the TableLayoutPanel I want to call a function whenever one of the UserControls is clicked and have the row and col index in that function call.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I know how to process the Click event in the UserControl. But I don’t know how I can call some kind of callback that I can register with the UserControl.
So the UserControl’s Click event handler would call something like Callback(Row, Col);

But I don’t know how to get method of my Form into the UserControl. In C I would use a function pointer. Do I need a delegate here?

So in my UserControl partial class I would have something like:

public delegate void DoubleClickHandler(int row, int col);
public DoubleClickHandler Callback;

public void On_Click(object sender, EventArgs e)
{
    Callback(Row, Col);
}

And when creating the form I would do something like:

MyControl elem = new MyControl(1, 3);
elem.Callback = delegate (int row, int col) { Console.WriteLine("row {0}, col {1}", row, col); }

It works but I don’t know if this is the right way to do it.

>Solution :

Winforms would probably use events for this; same idea, different keywords e.g.

For the event prop

//old
public DoubleClickHandler Callback;

//new
public event EventHandler<(int Row, int Col)> SomethingDoubleClicked;  //use a past tense name if you raise after, or a "SomethingDoubleClicking" if you raise before - probably hard to raise a click event before but..

OnClick might have code like

var eh = SomethingDoubleClicked;
eh?.Invoke(this, (theRow, theCol));

And subscription might look like:

//"modern"
yourcontrol.SomethingDoubleClicked += (s, e) => Console.WriteLine("row {0}, col {1}", e.Row, e.Col);



//"classic"
yourcontrol.SomethingDoubleClicked += SomeControl_SomethingDoubleClicked;

void SomeControl_SomethingDoubleClicked(object sender, (int Row, int Col) e)
{
    Console.WriteLine("row {0}, col {1}", e.Row, e.Col);
}

Note the += rather than = – an event is conceptually a list of methods that shall be invoked in an undefined order

Feel free to vary that tuple in the EventHandler to be a class or something.. Could also derive from EventArgs, but doesn’t have to.

If you have no userstate to report, you can simplify to using:

public event EventHandler SomethingDoubleClicked; 

//onclick
var eh = SomethingDoubleClicked;
eh?.Invoke(this, EventArgs.Empty);

ourcontrol.SomethingDoubleClicked += (s, e) => ...;

But I would perhaps avoid deriving from EventArgs to provide custom user state, and then using the EventHandler form immediately above – it’ll work because when you do:

eh?.Invoke(this, new MyCustomEventArgs(...));

MyCustomEventArgs derives from EventArgs so you can pass the child class in the parent type, but it means the dev that uses it will have to cast it back:

void SomeControl_SomethingDoubleClicked(object sender, EventArgs e)
{
    var mcea = e as MyCustomEventArgs;
}

and it’s a bit nasty; better to use EventHandler<MyCustomEvenArgs> to make using it a TAB TAB/no casting affair

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading