2008-09-18 22 views
12

我很喜歡自己在這裏的一個角落。在C#中繼承事件處理程序#

我有一系列的UserControl繼承自一個父級,它包含一些方法和事件來簡化事情,所以我不必寫行和幾乎相同的代碼行。像你一樣做。父級不包含其他控件。

我想要做的只是在父UserControl中有一個事件處理程序,它去做只有父控件才能做的事情(即有條件地調用一個事件,因爲事件在父級中定義) 。然後,我會將此事件處理程序連接到我的子控件中的所有輸入框,並且子控件將排除解析輸入並告知父控件是否拋出該事件的任務。不錯,乾淨,沒有重複,複製粘貼代碼(對我來說總是會導致錯誤)。

這是我的問題。 Visual Studio認爲我太聰明瞭一半,並警告說「方法'CheckReadiness'[父項中的事件處理程序]不能成爲事件的方法,因爲這個類派生出來的類已經定義了該方法。」是的,Visual Studio,這就是要點。我想想要有一個事件處理程序,它只處理子類拋出的事件,它的唯一工作就是使我能夠連接子程序而不必編寫一行代碼。我不需要那些額外的處理程序 - 我需要的所有功能自然就是在兒童處理用戶輸入時調用的。

我不知道爲什麼Visual Studio現在開始抱怨這件事(因爲它讓我這麼做),我不知道如何讓它消失。最好,我想這樣做,而不必定義一個只調用CheckReadiness的方法。是什麼引起了這個警告,是什麼導致它在不是一個小時之前就出現了,我怎樣才能讓它消失,而不是在所有的子類中做出小小的處理程序?

回答

7

聲明父虛擬方法,在子類覆蓋它,並從子類中調用

base.checkReadyness(sender, e); 

(或其derevation)。這允許將來的設計演變,如果你想在調用父事件處理器之前做一些特定的錯誤檢查代碼。您可能不需要爲每個控件編寫數百萬個事件處理程序,您只需編寫一個事件處理程序,將所有控件掛接到此事件處理程序,然後調用父級的事件處理程序。

我注意到的一件事是,如果所有這些代碼都放在dll中,那麼您可能會遇到性能問題,試圖從dll中調用事件處理程序。

+0

這將解決這個問題,但我希望避免基本上是空的錯誤處理程序,因此我的問題。 – Merus 2008-09-18 07:11:33

0

如果您的活動已在您的父級中定義,則不需要在您的子級中重新連線。這將導致事件發生兩次。

請確認這是否發生了什麼。 HTH :)

0

這篇關於MSDN的文章應該是一個很好的出發點:Overriding Event Handlers with Visual Basic .NET。看看如何處理子句可能導致衍生類部分中的問題。

+0

這是一篇Visual Basic文章。他們討論的問題在C#中不會成爲問題。這也許可以解釋爲什麼VS酒吧應該是合法的東西,儘管如此。 – 2012-05-05 14:08:27

0

爲什麼不在父類中聲明該方法爲虛擬的,然後可以在派生類中重寫它以添加額外的功能?

+0

所以我不必爲每個相同的類編寫處理程序。這些都是非常小的控制。沒有多少額外的功能,我需要。 – Merus 2008-09-18 07:02:02

0

忘記它是一個事件處理程序,只是在子類中做適當的常規方法覆蓋。

3

我剛剛遇到過這一個,我同意這感覺就像你正在做的一切正確。宣稱虛擬方法最好是解決方法,而不是解決方案。

正在做的事是有效的 - 只存在於派生類中的控件,派生類將事件處理程序附加到該控件的某個事件中。處理事件的方法在基類中定義的方法既不在這裏,也不在那裏,它在綁定事件的時候可用。這個事件沒有被附加到兩次或者任何其他愚蠢的事情上,它只是一個處理事件的方法被定義的地方。

絕對不是虛擬方法 - 我不希望方法被派生類重寫。非常令人沮喪,在我看來,dev-studio中存在一個bug。

1

我剛剛遇到了Merus第一次提出的確切問題,和其他發佈響應的人一樣,我完全不清楚爲什麼VS(我現在使用Visual C#2010 Express)對象具有事件處理函數在基類中定義。我發佈響應的原因是,在通過使基類代碼成爲派生類在其(基本上爲空)事件處理程序中簡單調用的受保護方法解決問題的過程中,我做了基本的重構重命名並注意到VS設計師停止抱怨。也就是說,它重命名了事件處理程序註冊(所以它不再遵循VS設計人員使用ControlName_EventName命名事件處理程序的慣例),並且這似乎滿足了它。當我然後試圖通過在適當的VS事件中輸入名稱來註冊(現在重命名的)基本事件處理程序與派生類控件,設計師在派生類中創建了一個新的事件處理程序,然後我刪除了它,從而保留了派生類控件到基類(事件處理程序)方法。網絡,正如你所期望的那樣,C#可以找到我們想要做的事情。當您遵循設計器的事件處理程序命名約定時,只有VS設計師不喜歡它。我不認爲設計師需要這樣工作。任何人,時間繼續。

0

這裏就是我做得到的基礎方法調用幾個類似的尋找方式,他們每個人有一些額外的功能,以共同的:

 protected override void OnLoad(EventArgs e) 
    { 
     try 
     { 
      this.SuspendLayout(); 
      base.OnLoad(e); 

      foreach (Control ctrl in Controls) 
      { 
       Button btn = ctrl as Button; 
       if (btn == null) continue; 

       if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnAdd_Click); 
       else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnEdit_Click); 
       else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnDelete_Click); 
       else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnPrint_Click); 
       else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal)) 
        btn.Click += new EventHandler(btnExport_Click); 
      } 

使用正確的固定器脫落的機會按鈕名稱對我來說看起來是一樣的,因爲沒有手動連接繼承的處理程序。

請注意,您可能需要測試this.DesignMode,以便根本跳過VS Designer中的代碼,但即使沒有檢查,它也可以正常工作。

2

我也經歷過這個問題,因爲在早期版本的VS中,你可以「繼承」事件處理程序。所以我找到的解決方案無需重寫方法,只需在表單的初始化階段將事件處理程序分配給某處。就我而言,在構造函數中完成(我敢肯定的OnLoad()會工作以及):

public MyForm() 
    { 
     InitializeComponent(); 
     btnOK.Click += Ok_Click; 
    } 

...在Ok_Click處理程序駐留在基本形式。食物的思想。