我從Gtk.Button
派生出一個類,當點擊按鈕時應該運行一些代碼,但只有之後的用戶定義的事件處理程序爲。什麼是事件處理程序後運行代碼的正確方法?
基於.NET約定,這不會是一個問題。下面的示例性Windows窗體代碼顯示的System.Windows.Forms.Button
之前事件處理程序執行一些代碼一個亞類中,然後調用該事件處理程序(通過調用繼承OnClick
method;同樣將在WPF工作與System.Windows.Controls.Button.OnClick
),然後執行一些代碼後事件處理程序:
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);
}
}
}
}
正如所料,輸出爲:
before
event
after
但是,我迄今未能在Gtk#中複製此行爲。與.NET約定相反,繼承的OnClicked
method of Gtk.Button
似乎並沒有觸發Clicked
event。實際上,文檔稱OnClicked
方法爲「默認處理程序」。
要驗證Gtk#的行爲不同,這裏的一些示例代碼:
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();
}
}
}
}
不幸的是,輸出
before
after
event
即連碼在OnClicked
運行已經是Clicked
事件之前結束處理程序。
我的問題是:什麼是Gtk#的適當的方式在事件只後事件處理程序,以執行一些代碼?
我已經發現了兩個不滿意的解決方法,到目前爲止:
首先是限定用於Clicked
事件,比方說,一個Clicking
事件的替代(具有根據OnClicking
方法觸發該Clicking
事件處理程序)。我可以在我的覆蓋版本OnClicked
中調用OnClicking
,從而在我喜歡的事件處理程序之前和之後運行代碼。此外,我的按鈕類的任何子類都可以以預期的方式使用OnClicking
,即當Clicking
事件處理程序應該運行時,調用base.OnClicking
。但是,這並不是很乾淨,因爲沒有任何東西可以阻止我的按鈕類的用戶向原始Clicked
事件註冊其事件處理程序,而不是將新的Clicking
事件正確地嵌入到按鈕的邏輯中。特別是,我甚至無法修改繼承的Clicked
事件的API文檔,以表示不應該使用Clicked
,用戶應該轉而使用Clicking
。
另一種解決方法僅適用於此特定情況,因爲碰巧有一個OnReleased
method總是在Clicked
事件處理程序之後執行。我可以使用該方法插入一些代碼,只有在任何事件處理程序之後才能運行該代碼,但顯然,此解決方案無法轉移到其他事件不方便遵循的事件。