In rationalizing about this, I'd suggest that we first have to acknowledge that in real world systems, some coupling is totally normal. Although you typically want this to keep this on a higher abstractional level and avoid coupling on implementation.
For example, you might have a database in your system. You are not going to be able to remove the coupling of the database from all parts of the rest of the system, some other components will have to be aware of that you have a database, because they will have to interact with it is some way, either implicitly or explicitly. Your abstract components in your system can simply not live in total isolation.
You might have stakeholders that would benefit from the ability to switch out the database implementation easily, like going from MSSQL to MySql, so then you'll have to make sure abstract the database properly and keep it's implementation details hidden so that the system is not coupled to a specific database engine. And in contrast, sometime your best choice can be to choose a particular database engine and expose it fully in the system, like if you have performance requirements that overweight the requirements of modularity.
Coupling is normal, and we should reason about where to put it in the system, not solely on how to avoid it.
And when we have coupling, we should put it where it belongs contextually without trying to indirect it away.
Do you have a view component that triggers something like
UserWantsToSeeDetailsForObject(id)? That's something that easily can be seen to contextually belong to the abstraction of the application itself, so I'd put that in something like a "ApplicationEvents"-class. It makes sense that many different components in your application could trigger this.
Do you have a component like
NetworkAnalyzer that checks your network connectivity and triggers event like "Reconnected", "Disconnected", "Unstable" and such? Those kinds of events would not make sense to trigger somewhere outside of
NetworkAnalyzer, so just avoid some indirection and place it where it belongs: Inside that very component.
Do you then get the need to implement different implementations of the
NetworkAnalyzer? Put the event definition in the base class.
Do you then discover that your system not only have to be aware of network connectivity but also about things like available memory, cpu resources and temperature? Then you'll might realize that you have a new abstractional context that you could name something like "EnvironmentTelemetry", where it makes sense to collect those event definitions.
Does the event have a clear owner? Just put it with the owner and avoid unnecessary indirection.
Does the event make sense in the application without what very component that you just wrote? It probably belongs to the application in it's whole, so place it in a shared structural construct (e.g. an ApplicationEvents-class).
Do your specific event contextually belong with a certain group of other events, not on a application level but above a individual component? Consider creating a class containing those specific events.