Avoid circular refence while classes have to communicate with eachother (Dependency injection) - c#

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 of TopViewModel
and requiring the TopViewModel in the constructor of ContentViewModel.
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?

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

Related

Initialize program correctly using MVVM

I've been dabbling with MVVM. In fact, I've religiously tried to follow it's rules and best practices.
How is program initialization handled properly?
Specifically, I am confused as to why you would call the view (from the App.xaml) first.
My assumptions has been, that a controller still owns the abstraction of the view (ViewModel) and uses it to update the view. (I prefer to separate presentation and processing into different classes, which I guess would make this "MVVMC").
So in my eyes, the view should not be the first thing to be initialized.
This being said, my solution has been to start the controller from the app.xaml code-behind and pass the ViewModel to the controller.
Even though I get a nice information pipline, I have the feeling that this is not the correct way, since I am still using the app.xaml code-behind.
This is what my application looks like:
So, what is the best/most-efficient/most-accepted way to initialize an application?
First of all, MVVM isn't a very strict ruleset and it definitely leaves space for a wide variety of flavors.
Based on whether View or ViewModel is instantiated first, you can differenciate two aproaches:
ViewModel first approach, where instance of ViewModel is created first and then typically based on some convention a View is selected. DataTemplateSelector is a good example.
View first approach, where view is created first (typically a Window or UserControl) and using some convention view is selected. It might be a responsibility of a View to create a ViewModel instance for itself, or it might be delegated to somebody else.
When it comes to initialization, it must always be done in app.xaml resp app.xaml.cs as it is the entry point for your app. You also must realize, the application process is
bound to the Dispatcher loop. When the last Window in your app is closed, dispatcher loops ends and the application process exits. The last window is typically the MainWindow.
Also, take the application startup time into account. You want to display some Window as soon as possible. So if you want to do any logic before the Window is shows, make sure you don't do any I/O, database or API calls, etc.
I typically have Bootstrapper.cs class that I invoke from App.xaml.cs. It's responsibility is to setup IoC and display the UI. It might be a loading window and then MainWindow.
In Bootstrapper.cs you might create instance of MainWindowViewModel first, the create MainWindow and assign the ViewModel to it's DataContext, or you might just create MainWindow and leave the ViewModel creation up to the MainWindow itself. I tend to do the latter.
There is nothing wrong with either of the approaches and neither violates the MVVM principle.
My biggest recommendation to you is - if you can't decide between two or more options, choose the simpler. Or in other words, don't complicate things unless you have very good reason to. KISS

Registering message recipients at the Application level in MVVM Light from XAML?

Specifically, in this case the Application itself would be the recipient. My thought process is that this would allow for the least possible linkage between Views and View-Models when dealing with the scenario where a new View would be created: They would deal strictly in messages and the App level of the WPF application would handle these messages, creating new views (and implicitly view models through the DataContext of those Views) as appropriate.
This is straightforward enough, as far as I can tell, if I go into the codebehind (app.xaml.cs). However, I would ideally like to handle this message recipient registration in the xaml if at all possible since the behavior is fairly straightforward, all it would really be doing is calling ShowDialog for the appropriate View (I don't think any further handling would be needed, but I may be forgetting something).
For the life of me, I can't think of a way to avoid the codebehind though (I know that MVVM does not really forbid the use of codebehind and I'm making things harder on myself with this, but I think it would make for better code organization if it is possible without violating some other MVVM principle). I thought I had it when I considered the use of System.Windows.Interactivity and tying an EventTrigger to the Startup event of the Application class, but was foiled when I discovered that it needs to extend DependencyObject for that to work.
To summarize, my question is twofold:
A. Is it even possible to handle message recipient registration within the app.xaml for the subset of messages that involve the creation of Views.
B. Is this even an appropriate structure to try and apply or am I way off-base with my thoughts on how to organize responsibility for the handling of messages that relate to other views. If it is not an appropriate approach, is there an easier way or a better way?
The View should contain all view-related code and no programme logic - this is MVVM separation. If your view needs to display a message box, this must then be handled by code in the View. This is the same as animation which must be defined in the View but can be easier in the code behind.
MVVMLight messages allow a simple way for a ViewModel to say "I want to show this" and the View to decide how to show it. The View registers to receive the required type of message and deals with the UI part of showing it - be it a MessageBox or other.
A purely XAML, and probably prettier way would be to build a custom message box.
As for part B: I would receive messages where I wanted to handle them.

WPF, MVVM, Navigation, Keeping Dependency Injection In-Tact

I have a simple WPF application which utilizes the Unity Framework for Dependency Injection. Currently, I am trying to simplify my method for navigation between views in my MVVM pattern implementation; however, many of the examples throughout Stack Overflow do not take into consideration the Dependency Injection caveat.
I have two entirely separate views.
One, Main acts as the main window into which content is loaded (pretty typical; unnecessary content eliminated):
<Window x:Class="Application.UI.Main">
<Grid Background="White">
<ContentControl Content="{Binding aProperty}"/>
</Grid>
</Window>
The constructor receives a ViewModel via constructor injection (again, very simple):
public partial class Main
{
private MainViewModel _mainViewModel;
public Main (MainViewModel mainViewModel)
{
InitializeComponent();
this.DataContext = _mainViewModel = mainViewModel;
}
}
I then have a UserControl, Home, to which I want to "navigate" the main window (i.e. set the ContentControl. It's constructor also receives a ViewModel via constructor injection in the same way Main does. It is equally simple:
public Home(HomeViewModel homeViewModel)
{
InitializeComponent();
// Set Data Context:
this.DataContext = homeViewModel;
}
The main problem, here, is that I want to enable constructor-based injection while maintaining as pure an MVVM implementation as possible.
I am in the View-first camp of MVVM, about which you can find a good discussion in these comments.
I have seen some allusions to the idea of a navigation based service; however, am unsure if that maintains the separation of concerns strived for by MVVM. DataTemplates require View constructors that do not take arguments and I have read criticisms of DataTemplates that argue ViewModels should not participate in the instantiation of Views.
This solution (in my opinion) is just straight wrong as the ViewModel becomes aware of its View and relies on a service for ViewModel instantiaion which makes real Dependency Injection to resolve ViewModel and View dependencies all but impossible. This issue is very evident in the use of RelayCommand in this MSDN article.
Does a navigation service which maintains a global, singleton-like reference to the Main view make the most sense? Is it acceptable for the Main view to expose a method, e.g.:
public void SetContent(UserControl userControl) { //... }
That is then accessed by that service?
This is my articulation of the motivations behind my implementation of the solution provided by another author. I do not provide code as great code examples are provided by the linked article. These are, of course, my opinions but also represent an amalgamation of my research into the topic
No-Container Needed Solution
Rachel Lim wrote a great article, Navigation with MVVM, which describes how to take full advantage of WPF's DataTemplates to solve the challenges presented by MVVM navigation. Lim's approach provides the "best" solution as it greatly reduces the need for any Framework dependencies; however, there really is no "great" way to solve the problem.
The greatest objection to Rachel's approach in general is that the View Model then becomes responsible for - or, "defines" - it's own relationship to the View. For Lim's solution, this is a minor objection for two reasons (and does nothing to further justify other bad architectural decisions, described later):
1.) The DataTemplate relationship is not enforced by anything other than an XAML file, i.e. the View Models are, themselves, never directly aware of their Views nor vice versa, so, even our View's constructor is further simplified, take for example the Home class constructor - now without need for a reference to a View Model:
public Home()
{
InitializeComponent();
}
2.) As the relationship is expressed nowhere else, the association between a particular View and View Model is easy to change.
An application should be able to function (model the domain) sufficiently without a prescribed View. This ideal stems from the effort to best decouple the application's supporting architecture and to foster further application of SOLID programming principles, most specifically dependency injection.
The XAML file - not a third-party dependency container - becomes the pivotal point for resolution of the relationship between the View and the View Model (which, consequently, directly contradicts the OP).
Dependency Injection
An application should be designed to be entirely agnostic of its container and - even better - any implementation-specific information regarding service dependencies. What this allows us to do is to "assign" (inject) services that oblige by a certain contract (interface) to various classes that make up the meat of our applications' functionality.
This leaves us with two criteria for "good design":
Application classes should be able to support a variety of services that perform the same task, as long as they oblige by a described contract.
Application classes should never be aware of - or reference - their container, even if the container is Unity, PRISM, or Galasoft.
The second point is of utmost importance and is a "rule" that is broken, commonly. That "rule breaking" being the inspiration behind the original post.
The response to the navigation problem in many applications is to inject a wrapped dependency injection container which is then used to make calls out of the implementing class to resolve dependencies. The class now knows about the container and, worse, has even greater, more concrete knowledge of what specifics it needs in order to perform its operations (and some might argue more difficult to maintain).
Any knowledge of a dependency resolution container on the part of the View, View Model, or Model is an anti-pattern (you can read more about the justification for that statement elsewhere).
A well written application that relies on dependency injection could function without a dependency injection Framework, i.e. you could resolve the dependencies, manually, from handwritten bootstrapper (though that would require a great deal of careful work).
Lim's solution enables us to "not need" a reference to a container from within the implementation.
What we should be left with are constructors that look like:
// View:
public Home() { //... }
// View Model
public HomeViewModel (SomeModelClass someModel, MaybeAService someService)
If one goal is modularization and reusability, then the above achieves that, well. We could continue to abstract this out further by ensuring those passed-in dependencies are contract fulfillments via interfaces.

ShellView or MainWindow as the master view in application?

I have a View base class, derived from UserControl that I use for all views. It allows for later addition of shared functionality to all my views without code duplication. I have now worked up to a level where I have an application whose top level views comprise only a 'NavBarView' and a 'WorkingView'. The latter is empty and merely a host for other child views provided by MEF plugins.
My question is, is it enough to host these two views in the MainWindow 'view' of the application, or should I rather create a ShellView containing them, and have that as simply the only child of MainWindow?
Don't forget, the purpose (of MVVM, MVC, MVP, et al) is to expose testable UI. In my case for an MVP WinForms application I simply have abstracted the implementation of actually showing views (as in, the underlying Forms etc). I would suggest MainWindow will suffice for bootstrapping, but if you intend to put substantial logic in it then go with ShellView in order to later test that logic. To me it sounds as though this is thin and I would personally start with MainWindow to get up and running. You can always refactor later.

MVP and presenter granularity

We've been using the MVP pattern and Winforms with a fair amount of success. However, a question always pops-up about MVP:
What is a good granularity for presenters?
What I mean by that is: With Winforms, a fine-granularity usually works quite well for user controls. That way, it's easy to reuse user controls and use them as building blocks while designing more complex GUIs. However, having the same (fine-)granularity with presenters seems to be a problem.
On one hand, having coarse-grained presenters hinders the ability to use "plug-in" controls and it sorts of violate the DRY principle: Multiple presenters often need to implement the same logic (populate a list of customers, for instance), which is used by multiple, more complex, controls.
On the other hand, fine-grained presenters seem to limit the ability to reuse controls in different situations. For instance, an editing view might sometimes need to save the customer right away; sometimes it needs to link it to something else; sometimes is just needs to validate it; and so on. It often depends on the more complex control. But there's also a fair amount of shared behaviour.
Note that, in both cases, 1-presenter-1-view is achievable. What is considered "1-view" changes.
What is usually considered best-practices for presenter granularity using MVP and Winforms?
Fine-grained presenters and customizable behaviour through options or something of that nature?
Coarse-grained presenters and low presenter reusability?
Something else?
Disclaimer: We mainly use Supervising Controller but I think it also applies to Passive View. Sorry for the long question, too.
We use MVP at all of our clients and this is definitely a conversation that comes up in more than one occasion. How clean should our code behind classes and presenters be? Having said that, we have chosen to use the coarse-grained presenter approach. Basically, every form would have its own presenter and would only get and set properties of any of the controls on a particular form using its view. Populating controls-a call to a db to populate a combobox for example-is located in a public service class. Any validation of user inputted data is located in a BO class which can be reused by any and/or all of the presenters. I hope this helps.
In my CAD-CAM system my presenters don't use user controls. User controls reside in the view which reside in a EXE assembly that implement the view interfaces the presenter use.
If want to display a list of customers I hand it off to the view which has a DisplayCustomerList and it uses whatever combination of user controls it needs to display the customer list. If multiple views show the customer list in the same way then in the ExE/View assembly they share a user control or class for doing that. That class doesn't go outside of that assembly.
Our software is adapted to run many different types of metal cutting machine. So we place a lot of emphasis on being able to rip off the UI and replace it with a completely different UI (corresponding to a different machine). All of these UIs reference the same set of core assemblies.
The hierarchy looks like this
View EXE
Presenter Implementation
Command Assembly - commands are executed by the presenter that modify the model
Presenter Interfaces
Model Assemblies
Off to the side are loadable assemblies that define dynamic content like what file types can be loaded, reports, cutting device drivers, etc. These implement various interfaces found in the model assemblies
One thing I do is that I don't impelment a view presenter for every dialog. If the dialog is tightly bound with a command then it is defined, created, and used along side the command class. Occasionally a group of related commands will share a dialog (File handling for example).
The essential question I ask when using MVP is "What happens if want to completely replace the forms with something else?". The answers to that question will identify where you are too dependent on a particular user control or form engine.
The biggest problem (and one that I haven't got a good answer for) of my setup is that current IDEs and langauges make it very easy to tie user controls to database records. It is so productive compared any other setup it tends to dominate the design. I haven't had to deal with the issue much in my CAD-CAM application so I don't have any answer other than passing the dataset to the view and let it handle it. This site has some patterns that may be of use in this situation.

Categories

Resources