I am deriving a class from Gtk.Button that is supposed to run some code when the button is clicked, but only after the user-defined event handlers.
Based on .NET conventions, this wouldn't be a problem. The following exemplary Windows Forms code shows a subclass of System.Windows.Forms.Button that executes some code before the event handlers, then invokes the event handlers (by calling the inherited OnClick method; the same would work in WPF with System.Windows.Controls.Button.OnClick), and then executes some code after the event handlers:
using System;
using System.Windows.Forms;
using System.Drawing;
namespace ButtonClickedTestSWF
{
class Program
{
private class MyButton : Button
{
protected override void OnClick(EventArgs e)
{
Console.WriteLine("before");
base.OnClick(e);
Console.WriteLine("after");
}
}
[STAThread]
public static void Main(string[] args)
{
using (Form win = new Form() {
Text = "Test"
}) {
win.StartPosition = FormStartPosition.CenterScreen;
win.Size = new Size(300, 200);
MyButton btn = new MyButton();
btn.Text = "Button";
btn.Click += delegate {
Console.WriteLine("event");
};
btn.Dock = DockStyle.Fill;
btn.Parent = win;
Application.Run(win);
}
}
}
}
As expected, the output is:
before
event
after
However, I have so far failed to replicate this behaviour in Gtk#. Contrary to .NET conventions, the inherited OnClicked method of Gtk.Button does not seem to fire the Clicked event. In fact, the docs call the OnClicked method a "default handler".
To verify that Gtk# behaves differently, here's some sample code:
using System;
using Gtk;
namespace ButtonClickedTest
{
class Program
{
private class MyButton : Button
{
public MyButton()
{
}
public MyButton(IntPtr raw) : base(raw)
{
}
protected override void OnClicked()
{
Console.WriteLine("before");
base.OnClicked();
Console.WriteLine("after");
}
}
[STAThread]
public static void Main(string[] args)
{
Application.Init();
using (Window win = new Window("Test")) {
win.WindowPosition = WindowPosition.Center;
win.SetSizeRequest(300, 200);
win.Hidden += delegate(object sender, EventArgs e) {
Application.Quit();
};
MyButton btn = new MyButton();
btn.Add(new Label("Button"));
btn.Clicked += delegate {
Console.WriteLine("event");
};
win.Add(btn);
win.ShowAll();
Application.Run();
}
}
}
}
Unfortunately, the output is
before
after
event
i.e. even code at the end of OnClicked runs already before the Clicked event handlers.
My question is: What is the proper way in Gtk# to execute some code upon an event only after the event handlers?
I have found two dissatisfying workarounds so far:
The first is to define a replacement for the Clicked event, say, a Clicking event (with an according OnClicking method that fires the Clicking event handlers). I could invoke OnClicking in my overridden version of OnClicked and thus run code before and after the event handlers as I like. Additionally, any subclasses of my button class could use OnClicking in the expected way, i.e. calling base.OnClicking when the Clicking event handlers should run.
This is not very clean, though, because nothing would prevent users of my button class from registering their event handlers with the original Clicked event rather with the new Clicking event that is properly embedded into the button's logic. In particular, I could not even modify the API documentation for the inherited Clicked event to express there that Clicked should not be used and users should turn to Clicking instead.
The other workaround works only in this specific case, as there happens to be an OnReleased method that is always executed after the Clicked event handlers. I could use that method to insert some code that is guaranteed to run only after any Clicked event handlers, but obviously, this solution couldn't be transferred to events that are not conveniently followed by some other events.