2010-11-16 47 views
4

我在C#WinForms中有一個名爲BaseControl的自定義控件,那裏有一個名爲Selected的屬性。如何覆蓋C#中的WinForm UserControl中的方法和事件?

我想在基控制的事件SelectedChanged和虛擬方法OnSelecteChanged和它們應以相同的方式表現,因爲我們有在Control類許多屬性即Click事件和OnClick方法。

意味着從我的BaseControl派生的任何人都可以綁定到該事件,或者可以覆蓋OnSelectedChanged方法。

因此,當Selected屬性值被更改時,應該觸發事件,並且如果方法被覆蓋,則應該轉到該方法。

我知道如何解決事件,但不知道如何爲方法做。

請指引我...

回答

3

下面是事件應該如何實現的例子:

public class BaseControl : Control 
{ 
    private object _selected; 

    public object Selected 
    { 
     get { return _selected; } 
     set 
     { 
      if (!Equals(_selected, value)) 
      { 
       _selected = value; 
       OnSelectedChanged(EventArgs.Empty); 
      } 
     } 
    } 

    public event EventHandler SelectedChanged; 

    protected virtual void OnSelectedChanged(EventArgs e) 
    { 
     if (SelectedChanged != null) 
      SelectedChanged(this, e); 
    } 
} 

有了這個例子,你可以在被覆蓋的類中重寫OnSelectedChanged,就像這樣:

public class MyControl : BaseControl 
{ 
    protected override void OnSelectedChanged(EventArgs e) 
    { 
     base.OnSelectedChanged(e); 

     // My own logic. 
    } 
} 
+0

你的OnSelectedChanged實現包含一個潛在的線程問題(如果在null檢查和最後一個listener退訂事件觸發之間會發生什麼? - >你得到一個NullReferenceException) – 2010-11-16 13:58:46

+0

@SchlaWiener - 對於UI編程,這不是問題,因爲它是接受UI控件是**不是**多線程安全,只能從一個線程訪問。但是,是的,你是對的。 – 2010-11-16 14:00:58

0

基本上你不會從你的Selected的屬性設置觸發事件 - 你調用該方法,使方法調用事件。任何覆蓋該方法的人都應該致電base.OnSelectedChanged以確保事件仍然發生。所以,你的方法應該是這個樣子:

protected virtual void OnSelectedChanged(EventArgs e) { 
    EventHandler handler = Selected; // Or your own delegate variable 
    if (handler != null) { 
     handler(this, e); 
    } 
} 
+0

爲什麼要複製事件處理程序? – 2010-11-16 13:56:02

+0

這是爲了防範多線程問題嗎? – 2010-11-16 14:01:39

1
private bool _selected; 

public bool Selected 
{ 
    get { return _selected; } 
    set 
    { 
     if (value != _selected) 
     { 
      _selected = value; 
      OnSelectedChanged(); 
     } 
    } 
} 

public event EventHandler SelectedChanged; 

protected virtual void OnSelectedChanged() 
{ 
    var handler = SelectedChanged; 
    if (handler != null) 
     handler(this, EventArgs.Empty); 
}