I'm working on an application written in C# and WPF.
There's a view with a layout that consists of three separated sections (sub views).
- A "content" view that contains the current main content (say, a listview of products).
- A view located on top of it, containing tools and option controls.
- The main menu view on the left.
I use the .NET dependency injection for my application (Microsoft.Extensions.DependencyInjection
, Microsoft.Extensions.Configuration.Abstractions
)
When a ViewModel is set for the content view, I also want to set a ViewModel for the top view. These ViewModels have to communicate/reference eachother.
Like, when a command on the top ViewModel is executed, the content ViewModel should be notified and/or do something, and vice-versa.
Say I have a TopViewModel
and a ContentViewModel
.
One bad thing I could do is:
- Requiring the
ContentViewModel
in the constructor ofTopViewModel
- and requiring the
TopViewModel
in the constructor ofContentViewModel
.
Of course that won't work, because it's a circular reference.
The alternative I can think of, is just requiring the TopViewModel
in the constructor of ContentViewModel
and don't do this same kinf of thing with the other class.
The constructor code of ContentViewModel
could then listen to events of TopViewModel
. The TopViewModel doesn't know anything about ContentViewModel
, which can be a problem if it needs to reference it for some logical reason.
Some content views can have multiple top views (they change like when the user selects something)
I'm taking this quite serious. Everything I can think of seems ugly and bad practice to me. While I think this is a quite simple and common situation. What is the best, generally accepted solution to this that doesn't break the OOP rules?
CodePudding user response:
What is the best, generally accepted solution to this that doesn't break the OOP rules?
Instead of storing a direct reference from one view model to another, you should consider using an event aggregator to communicate between the view models in a loosely coupled way.
This removes the tight coupling between the view model classes and makes your application easier to maintain and evolve over time.
The idea is that a subscriber observes the event aggregator instead of the publisher and the publisher knows only about the event aggregator and not about the subscriber(s). Please refer to the following blog post for more information.
Using the event aggregator pattern to communicate between view models