ボタンがクリックされたときにコードを実行することになっているクラスを派生していますが、ユーザー定義のイベントハンドラーの後Gtk.Button
でのみです。
.NETの規則に基づくと、これは問題にはなりません。次のWindowsフォームコードの例は、イベントハンドラーの前System.Windows.Forms.Button
にいくつかのコードを実行し、イベントハンドラーを呼び出し(継承されたメソッドを呼び出すことによって;同じことがWPFでも機能します)、イベントハンドラーの後にいくつかのコードを実行するサブクラスを示しています。OnClick
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
メソッドはGtk.Button
Clicked
イベントを発生させないようです。実際、ドキュメントでは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#で、イベントハンドラーの後でのみイベントに対してコードを実行する適切な方法は何ですか?
これまでに、2つの不満足な回避策を見つけました。
Clicked
1つ目は、イベント、たとえばイベントの置換を定義することです(イベントハンドラーを起動Clicking
するそれに応じたOnClicking
メソッドを使用)。オーバーライドされたバージョンのをClicking
呼び出して、イベントハンドラーの前後で好きなようにコードを実行できます。さらに、ボタンクラスのサブクラスは、期待どおりに使用できます。つまり、イベントハンドラーを実行するタイミングを呼び出すことができます。OnClicking
OnClicked
OnClicking
base.OnClicking
Clicking
ただし、これはあまりクリーンではありません。ボタンクラスのユーザーが、ボタンのロジックに適切に埋め込まれClicked
た新しいイベントではなく、元のイベントにイベントハンドラーを登録することを妨げるものは何もないからです。Clicking
特に、継承されたイベントのAPIドキュメントを変更して、使用すべきではなく、ユーザーが代わりに使用する必要Clicked
があることを表現することさえできませんでした。Clicked
Clicking
他の回避策は、この特定の場合にのみ機能します。これは、イベントハンドラーの後に常に実行されるOnReleased
メソッドが存在するためです。Clicked
そのメソッドを使用して、イベントハンドラーの後でのみ実行されることが保証されているコードを挿入できますClicked
が、明らかに、このソリューションは、他のイベントが適切に続かないイベントに転送できませんでした。