The FrameworkElement
object has DataContextChanged
event. However, there is no OnDataContextChanged
method that can be overridden.
Any ideas why?
If a method is virtual, then the user has the option to either augment the base functionalty by calling the base class method or replace the base class functionality by failing to call the base class method. For OnEvent() methods, if you don't call the base class method then the event will not be raised (that's the responsibility of the base class method.) If the base class performs some kind of state management inside of the OnEvent method, this means that the derived class can accidentally invalidate the state of the object if the user chooses to omit a call to the base class method. Documentation can specify "please always call the base class method", but there's no way to enforce it.
When I see an event that doesn't have a virtual OnEvent() method, I usually assume the method performs some kind of internal state management and the designers of the class want to guarantee their state management runs. This isn't the case in FrameworkElement, and it's not the only event that doesn't follow the pattern, so I'm curious what the reasoning is.
I dug around in Reflector to see if I could discover a reason. There is an OnDataContextChanged() method, but it's a dependency property change handler and doesn't follow the standard event pattern. This is probably the reason for not making it protected virtual. It's non-standard, so it would be confusing. It's static, so you wouldn't be able to override it anyway. Since it's called automatically by the dependency property framework and you are unable to override it, I believe we have the reason why it's private instead of static virtual.
You could use a different pattern to expose the normal event pattern:
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(...);
}
}
My guess why they didn't do this? Usually you call OnEvent() to raise the event. The event is automatically raised when DataContext changes, and it doesn't make sense for you to raise it at any other time.
Good question.
I'm just guessing, but looking in Reflector I'd say it's just laziness, perhaps with a pinch of (unfounded?) performance concerns. FrameworkElement
has a generic EventHandlersStore
which is responsible for maintaining event information (delegates) for a whole bunch of events. The add and remove logic in the CLR events (such as DataContextChanged
) simple call into the EventHandlersStore
with the appropriate key.
There is a generic RaiseDependencyPropertyChanged
method that is called to raise all different sorts of events. There is also a private OnDataContextChanged
method that calls the RaiseDependencyPropertyChanged
method. However, it is static and registered as part of the d-prop metadata.
So, in short, I see no technical reason not to include an overridable OnDataContextChanged
method. Just looks like a short-cut in implementation to me.
Is this merely academic, or are you trying to achieve something here?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With