對象FrameworkElement
有DataContextChanged
事件。但是,沒有可以覆蓋的OnDataContextChanged
方法。WPF - 爲什麼沒有「OnDataContextChanged」覆蓋方法?
任何想法爲什麼?
對象FrameworkElement
有DataContextChanged
事件。但是,沒有可以覆蓋的OnDataContextChanged
方法。WPF - 爲什麼沒有「OnDataContextChanged」覆蓋方法?
任何想法爲什麼?
如果方法是虛擬的,那麼用戶可以選擇通過調用基類方法來擴充基本功能,或者通過調用基類方法來替換基類功能。對於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發生變化時會自動引發該事件,並且在任何其他時間引發該事件都沒有意義。
沒有理由靜態OnDataContextChanged事件不能調用非靜態OnDataContextChanged事件。當然,他們想重新命名以使事情更清楚。提供一個可重寫的OnXxx方法是標準的.NET練習。誠然,你提到了一些陷阱,但也有緩解措施和開發者的一定的責任,以便知道他們在做什麼。 – 2009-08-18 14:22:06
這是有效的,但並沒有回答這個問題:「用戶什麼時候能夠提高事件的意義?」如果該方法受到保護,則只要用戶決定這樣做,就可以引發該方法。 我們錯過了一些信息:有可能這個事件被很多內部WPF類以非公共知識的方式使用,並且讓用戶以任何方式改變行爲都是危險的。 – OwenP 2009-08-18 18:08:53
好問題。
我只是在猜測,但看着反射器我會說這只是懶惰,也許是一小撮(毫無根據的)性能問題。 FrameworkElement
有一個通用的EventHandlersStore
,它負責維護大量事件的事件信息(委託)。 CLR事件中的添加和刪除邏輯(例如DataContextChanged
)可以用適當的密鑰簡單地調用EventHandlersStore
。
有一個通用的RaiseDependencyPropertyChanged
方法被調用來引發所有不同類型的事件。還有一個私人的OnDataContextChanged
方法,它調用RaiseDependencyPropertyChanged
方法。但是,它是靜態的並且被註冊爲d-prop元數據的一部分。
所以,總之,我沒有看到沒有技術原因不包括可覆蓋的OnDataContextChanged
方法。只是看起來像是我執行的捷徑。
這僅僅是學術性的,還是你想在這裏做點什麼?
老實說,我只是想知道是否有一些背後的邏輯。這對我來說也沒有任何意義。 註冊活動同樣適合我的需求。 謝謝你的偉大答案! – Elad 2009-08-18 13:58:31
的Silverlight注:
在測試版的Silverlight 4的沒有DataContextChanged
事件(以及其在不公開至少)。
Microsoft Connect bug report已被標記爲'固定',但沒有指出實際的含義。
與此同時,您需要一種解決方法,如this one from CodeProject--這非常簡單,如果微軟真正將事件公之於衆,應該很容易轉換出來。
依賴屬性通常沒有用於引發事件的相應虛擬方法,因爲預期更改事件將由依賴屬性系統本身管理。
但是你可以重寫什麼,以處理任何依賴屬性變化的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
}
}
}
球!我又做了一次,回答了一個在頭版上出現的非常古老的問題。哎呀.... – Josh 2009-12-18 05:10:32
爲什麼你需要重寫呢?不能只聽DataContextChanged事件觸發? – sisve 2009-08-18 13:41:44
嗯,這是我最終做的。不過,我很好奇缺乏這種方法的原因。 – Elad 2009-08-18 13:48:21