Reputation: 2345
I currently have a hierarchy that looks like this
MainWindowViewModel
TabViewModel
EditorViewModel
ReviewingServices
ConflictFinder
The issue I'm running into is that TabViewModel
wants to be notified of conflicts (from ReviewingServices
) as well as other things. I could create public getters for all my dependencies and subscribe to whatever I want with DependencyA.DependencyB.DependencyC += SomeHandler;
but that's rather messy. I'm finding myself creating far too many events that I wish to count. Essentially, I've created a messy web of events. I love the separation of responsibilities that I've created for every class but when every class has 2-3 events each it's rather difficult to maintain. I'm having no issues creating and maintaining events if the subscriber is only 1 level above. The mess comes when say MainWindowViewModel
wishes to be notified of new reviews (published from ReviewingServies
.
Is there a better of doing these types of events where a subscriber could want to subscribe to events that are deeply nested in the application?
Upvotes: 0
Views: 219
Reputation: 13196
Chaining DependencyA.DependencyB.DependencyC
is generally considered breaking the Law of Demeter (you are effectively relying on a dependency of a dependency, etc).
I recently solved a similar design problem by using a Mediator defined by an interface such as IMyOperationNameContext
which allowed me to share/inject the combined context of two ViewModels with/into a WinForms control which uses a third ViewModel and all of that without coupling the three models together directly.
Something like this (note how in the sample the IAlbumContext
acts more as a proxy, but that's just because the sample is simplified):
interface IAlbumContext
{
public AlbumInfo SelectedAlbum { get; set; }
}
class AlbumContext
{
AlbumSelectionViewModel _model;
public AlbumContext(AlbumSelectionViewModel model)
{
_model = model;
}
public Album SelectedAlbum {
get { return _model.Album; }
}
}
class PhotoUploadDialog : Dialog
{
public PhotoUploadDialog(IAlbumContext context, PhotoUploadViewModel viewModel)
{
}
}
While this solution worked for me and I like that it's with high cohesion and decoupled it's ultimately not massively scalable (e.g the number of such context interfaces can grow rapidly depending on the app). However with a more generic solution the trade-off is that the code gets harder to follow.
Upvotes: 1
Reputation: 33252
I don't know if I really got your trouble, but I suggest to look at some kind of event aggregator. Try to check out the Caliburn one, but is not so different to implement one yourself. With this you name the event with a type and subscribe to it from everywhere.
Upvotes: 1