2009-08-18 69 views
4

對象FrameworkElementDataContextChanged事件。但是,沒有可以覆蓋的OnDataContextChanged方法。WPF - 爲什麼沒有「OnDataContextChanged」覆蓋方法?

任何想法爲什麼?

+0

爲什麼你需要重寫呢?不能只聽DataContextChanged事件觸發? – sisve 2009-08-18 13:41:44

+0

嗯,這是我最終做的。不過,我很好奇缺乏這種方法的原因。 – Elad 2009-08-18 13:48:21

回答

2

如果方法是虛擬的,那麼用戶可以選擇通過調用基類方法來擴充基本功能,或者通過調用基類方法來替換基類功能。對於OnEvent()方法,如果您不調用基類方法,則不會引發事件(這是基類方法的責任。)如果基類在OnEvent方法內執行某種狀態管理,這意味着如果用戶選擇省略對基類方法的調用,則派生類可能會意外地使對象的狀態無效。文檔可以指定「請始終調用基類方法」,但是沒有辦法執行它。

當我看到一個沒有虛擬OnEvent()方法的事件時,我通常假定該方法執行某種內部狀態管理,並且該類的設計者希望確保其狀態管理運行。在FrameworkElement中情況並非如此,它不是唯一不遵循該模式的事件,所以我很好奇它的推理是什麼。

我在Reflector中挖掘,看看我是否能找到一個理由。有一個OnDataContextChanged()方法,但它是一個依賴屬性更改處理程序,並不遵循標準事件模式。這可能是不使其受到虛擬保護的原因。這是非標準的,所以會令人困惑。它是靜態的,因此無論如何您都無法覆蓋它。由於它是由依賴屬性框架自動調用的,你無法覆蓋它,所以我相信我們有它爲什麼是私有的,而不是靜態虛擬的原因。

你可以使用不同的圖案,以暴露正常事件模式:

class FrameworkElement 
{ 
    // difference: use DataContextPropertyChanged as the change callback 
    public static readonly DependencyProperty DataContextProperty = ... 

    protected virtual void OnDataContextChanged(...) 
    { 
     // raise the DataContextChanged event 
    } 

    private static void DataContextPropertyChanged(...) 
    { 
     ((FrameworkElement)d).OnDataContextChanged(...); 
    } 
} 

我猜他們爲什麼不這樣做呢?通常你調用OnEvent()來引發事件。 DataContext發生變化時會自動引發該事件,並且在任何其他時間引發該事件都沒有意義。

+0

沒有理由靜態OnDataContextChanged事件不能調用非靜態OnDataContextChanged事件。當然,他們想重新命名以使事情更清楚。提供一個可重寫的OnXxx方法是標準的.NET練習。誠然,你提到了一些陷阱,但也有緩解措施和開發者的一定的責任,以便知道他們在做什麼。 – 2009-08-18 14:22:06

+0

這是有效的,但並沒有回答這個問題:「用戶什麼時候能夠提高事件的意義?」如果該方法受到保護,則只要用戶決定這樣做,就可以引發該方法。 我們錯過了一些信息:有可能這個事件被很多內部WPF類以非公共知識的方式使用,並且讓用戶以任何方式改變行爲都是危險的。 – OwenP 2009-08-18 18:08:53

1

好問題。

我只是在猜測,但看着反射器我會說這只是懶惰,也許是一小撮(毫無根據的)性能問題。 FrameworkElement有一個通用的EventHandlersStore,它負責維護大量事件的事件信息(委託)。 CLR事件中的添加和刪除邏輯(例如DataContextChanged)可以用適當的密鑰簡單地調用EventHandlersStore

有一個通用的RaiseDependencyPropertyChanged方法被調用來引發所有不同類型的事件。還有一個私人的OnDataContextChanged方法,它調用RaiseDependencyPropertyChanged方法。但是,它是靜態的並且被註冊爲d-prop元數據的一部分。

所以,總之,我沒有看到沒有技術原因不包括可覆蓋的OnDataContextChanged方法。只是看起來像是我執行的捷徑。

這僅僅是學術性的,還是你想在這裏做點什麼?

+0

老實說,我只是想知道是否有一些背後的邏輯。這對我來說也沒有任何意義。 註冊活動同樣適合我的需求。 謝謝你的偉大答案! – Elad 2009-08-18 13:58:31

0

的Silverlight注:

在測試版的Silverlight 4的沒有DataContextChanged事件(以及其在不公開至少)。

Microsoft Connect bug report已被標記爲'固定',但沒有指出實際的含義。

與此同時,您需要一種解決方法,如this one from CodeProject--這非常簡單,如果微軟真正將事件公之於衆,應該很容易轉換出來。

0

依賴屬性通常沒有用於引發事件的相應虛擬方法,因爲預期更改事件將由依賴屬性系統本身管理。

但是你可以重寫什麼,以處理任何依賴屬性變化的DependencyObject.OnPropertyChanged像這樣:

class MyClass : FrameworkElement { 

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { 
     base.OnPropertyChanged(e); 
     if (e.Property == FrameworkElement.DataContextProperty) { 
      // do something with e.NewValue/e.OldValue 
     } 
    } 

} 
+1

球!我又做了一次,回答了一個在頭版上出現的非常古老的問題。哎呀.... – Josh 2009-12-18 05:10:32