2013-01-20 147 views
2

我從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事件處理程序之後執行。我可以使用該方法插入一些代碼,只有在任何事件處理程序之後才能運行該代碼,但顯然,此解決方案無法轉移到其他事件不方便遵循的事件。

回答

相關問題