It's not virtual as it's an important method of the framework: the event must be raised to make the framework work. If we made it virtual, users would override it and might forget to call the base or do different things and avoid calling the base method, resulting in side effects which would be hard to track down.
For v4 we created a datascope, which monitors a conceptual scope with data. It keeps track of whether data in the scope is changed. We built this on top of the context. You could do that too: subclass the context, make sure you bind to the EntityContentsChanged event when an entity is added to the context, and this way use the context as an observer for the event. You might run into edge case problems though this way (we needed to make some changes internally to make it work 100%) but for simple cases you could do it this way.