Still feeling my way through MVVM, and have come up against this issue:
I have a top level ViewModel, lets call it ModelLevel1.
I have a sub ViewModel that belongs to it, that a control uses for all its bindings, lets call that ControlViewModel1. The Control only binds to ControlViewModel1.
In the Top level Viewmodel, there is a Repository, and a method to get a record from the repository from an id.
What is the best way to allow ControlViewModel1 to access the method so it can get a record from the repository?
Cheers,
Rob
Following the Single Responsibility Principle extract the logic of getting the record to a class that knows how to do it and inject that dependency to both ViewModels.
This approach can be reused by other classes, can be easily tested and is performant (unlike the aggregated events proposal).
What is the best way to allow ControlViewModel1 to access the method so it can get a record from the repository?
IMHO Controls are self contained units which have dependency properties which serve the function of a VM; hence no VM is needed.
Create a Dependency property on the control which takes in the target VM and hence has access to the method.
Create a static property on the app which will contain the VM in question and access it as a static call.
MVVM is simply a separation of concerns, remember Xaml ultimately gets compiled into C# code which is executed along side the code. Whatever process you use in code to access methods and objects can also be carried over to control instances on the page.
Related
I have a scenario where there are two pages to display orders in progress and delivered orders. The pages have almost identical binding and commands, so making separate ViewModels would result in code duplication
I was recommended to use the same ViewModel for both pages since the they would represent the same model, only order statuses would differ. The data comes from different endpoints, so I have two service methods. I don't like the idea of making one ViewModel for both pages, because this would make me to tell the ViewModel that it should get the Orders from one of the service methods when initializing the ViewModel.
The solution that I've thought of is to have OrdersViewModel as a base class, where all the common members are there, and create two derived classed called OrdersInProgressViewModel and DeliveredOrdersViewModel.
My every ViewModel has a method called InitializeAsync, if I decide to go with the first approach and have single ViewModel for both pages, I would probably have to pass down the status as navigation data to InitializeAsync and decide there which service method use to fetch orders.
With the second approach, I could have two separate ViewModels and in their InitializeAsync call the corresponding service method.
Which approach would adhere to MVVM more?
I also need to keep in mind, that more page specific behavior might be requested (another argument against single ViewModel for both pages)
I would suggest you to use the second approach you've described. Using a base viewmodel class and then implement derived classes.
EDIT
The answer to a similar question, in fact, is very similar to what I mean.
Generally I would recommend you not to have inheritance between different ViewModel classes, but instead having them inherit directly from a common abstract base class.
This is to avoid introducing unnecessary complexity by polluting the ViewModel classes' interfaces with members that come from higher up in the hierarchy, but are not fully cohesive to the class's main purpose.
The coupling that comes with inheritance will also likely make it hard to change a ViewModel class without affecting any of its derived classes.
I'm currently working on an application that implements the MVVM architecture, where I am trying to do the login logic.
I have a pretty good idea of what the main responsibilities of both INotifyPropertyChanged and ICommand are, and have already implemented them to all my view models that need them.
Here's a short of my code:
I have an ApplicationViewModel.cs that handles the main window ApplicationView.xaml.
The main
window has a sidebar menu on the left, and a <ContentControl> that that is binded to the CurrentViewModel property of type ViewModelBase in ApplicationViewModel.cs.
All child view models are contained in a List<ViewModelBase> property. It gets its views from a DataTemplate with the corresponding view model, thus providing me a working navigation system.
So here's what I initially thought of doing:
In a child view model called LoginViewModel.cs, I thought it was logical to do the login logic, as it also handled the view itself. I wrote a model class User.cs with corresponding properties to the database columns. I wrote some classes that would help me get the data from the database to the application.
The view model checks for how many characters are entered and executes the Login once the user has entered 4 characters for the pin code, which instantiates a User object in LoginViewModel.cs
The problem here for me, is that I need the instance of the User to be application wide and therefore probably needs be in the ApplicationViewModel.cs instead.
So, from that, I have 2 questions:
Is there a better approach to this and a better way handle the login logic?
If the logic I already made is fine, how do I hand the instance of the User from the child view model LoginViewModel.cs to the parent view model ApplicationViewModel.cs?
Yes; it wasn't quite natural to come towards this solution when I first started, but you actually can add some kind of 4th layer in MVVM, the Services layer (well, it's more of a pattern than an actual MVVM layer).
Services are single-instance objects that you inject into your viewmodels, and serve exactly that kind of purpose, which is holding and potentially treating data that should circulate between viewmodels.
You will need a dependency injector, a class that will bother with finding the correct service for the classes injected with it.
So you have two concepts to study:
Services
Inversion of control/dependency injection
I can't just give you an implementation of a dependency injector, because I personally don't have one.
I'm using a MVVM framework that provides me with one already.
It's basically used this way:
You create an interface for each of your services; it keeps concerns separated (no coupling between service implementations and viewmodels).
You register your service implementation by their interfaces (something like myDependencyInjector.Register<IMyService>(typeof(MyService)) at the start of your program
You add the desired service interfaces to the relevant viewmodels' constructors (MyViewModel(IMyService myService))
You could implement custom authentication and authorization by creating classes that derive from the IIdentity and IPrincipal interfaces and override the application thread's default identity. Please refer to the following blog post for more information about how to do this.
Custom authorization in WPF: https://blog.magnusmontin.net/2013/03/24/custom-authorization-in-wpf/.
You basically create an IPrincipal and use the AppDomain.CurrentDomain.SetThreadPrincipal method to associate this principal with the AppDomain in your application. You can then use the Thread.CurrentPrincipal.Identity.IsAuthenticated property everywhere in your application to determine whether the user is authenticated.
In the code sample, the actual authentication is done by the AuthenticationService class. You could for example implement this one to check the passed in credentials against a remote database. The view model uses this service to perform the authentication.
I am trying to understand what is the point of declaring interface upon specific ViewModel. The only advantage I could think of is that we can specify common variables that we can use to our ViewModel that is used for design time purposes. This way we can be sure, that both (runtime & design time view models) will have the same variables with the same name.
Is there any other advantage to this?
One of the advantages to use interface is to use DI. This way you can specify in IoC container what concrete VM should be injected for that specific interface. Another advantage of using interface in VM is for unit tests when you need to mock your VM and instead of calling concrete VM you mock it with you mocking library (e.g. moq)
One thing I need the interface for is that I have a list of different view models that have some common properties like a "caption" that can be used as the header content when they are displayed as a tab control. While this basically could be done without the interface (by using a list of object), it gives me more confidence that there will be less runtime errors.
Common interfaces like IDisposable etc. are also something one comes along more frequently.
Another thing is if the view needs to interact with the view model (e.g. notify when the user clicks the "close" button). An interface may provide methods that can be invoked by the view in this case.
As Vlad already mentioned: Using a interface will make it easier to mock it (but only if all properties are in the interface!).
I am using MVVM with WPF, but I am having a hard time understanding the concepts behind this desing pattern.
I have a "myclass" object that is the state of the application (it stores data loaded from the repository). All pages of my application will use this data and the object should be syncronized between them all.
My first approach was to store this data in the service layer, using a singleton class. So, all ViewModel should call this service to get the data. Any modification should also call this service, and a event would be fired to synchronize all views.
I am wondering now if it would be better to store this data in the model layer...
What's be best option?
EDIT:
Adding more information:
The data stored is a list of projects loaded into a solution. Since there must be only one solution, I implemented it as a singleton. The must can interactively load, change, or remove any project.
A Service to my understanding is just something that abstracts a piece of functionality(access the file-system, access a database...) which say implements a given interface that the VM's can then use when requiring that functionality.
A Model however holds the business logic of your application and anything that will assist performing that business logic (which can / cannot implement INPC if desired)
So in essence you use a service to get something done and let go of it, a Model is more ingrained to your application
For your given use-case, I'd have the stored info in the Model and implement INPC on it so that the ViewModels get notified of changes automatically if another ViewModel makes a change to the Model.
I'm been experimenting with the oft-mentioned MVVM pattern and I've been having a hard time defining clear boundaries in some cases. In my application, I have a dialog that allows me to create a Connection to a Controller. There is a ViewModel class for the dialog, which is simple enough. However, the dialog also hosts an additional control (chosen by a ContentTemplateSelector), which varies depending on the particular type of Controller that's being connected. This control has its own ViewModel.
The issue I'm encountering is that, when I close the dialog by pressing OK, I need to actually create the requested connection, which requires information captured in the inner Controller-specific ViewModel class. It's tempting to simply have all of the Controller-specific ViewModel classes implement a common interface that constructs the connection, but should the inner ViewModel really be in charge of this construction?
My general question is: are there are any generally-accepted design patterns for how ViewModels should interact with eachother, particularly when a 'parent' VM needs help from a 'child' VM in order to know what to do?
EDIT:
I did come up with a design that's a bit cleaner than I was originally thinking, but I'm still not sure if it's the 'right' way to do this. I have some back-end services that allow a ContentTemplateSelector to look at a Controller instance and pseudo-magically find a control to display for the connection builder. What was bugging me about this is that my top-level ViewModel would have to look at the DataContext for the generated control and cast it to an appropriate interface, which seems like a bad idea (why should the View's DataContext have anything to do with creating the connection?)
I wound up with something like this (simplifying):
public interface IController
{
IControllerConnectionBuilder CreateConnectionBuilder();
}
public interface IControllerConnectionBuilder
{
ControllerConnection BuildConnection();
}
I have my inner ViewModel class implement IControllerConnectionBuilder and the Controller returns the inner ViewModel. The top-level ViewModel then visualizes this IControllerConnectionBuilder (via the pseudo-magical mechanism). It still bothers me a little that it's my inner ViewModel performing the building, but at least now my top-level ViewModel doesn't have to know about the dirty details (it doesn't even know or care that the visualized control is using a ViewModel).
I welcome additional thoughts if there are ways to clean this up further. It's still not clear to me how much responsibility it's 'okay' for the ViewModel to have.
An option which works well for interaction between viewmodels is to bind directly to observer classes sitting between the viewmodel classes.
I think you want to make your top-level ViewModel aware of the existence of the NestedViewModel, it makes sense from a hierarchical standpoint, the master view contains the child view.
In my opinion, your instinct is right, it doesn't feel correct for the nested ViewModel to expose behaviours which are initiated by user actions on the top-level. Instead, the top-level ViewModel should be providing behaviors for the view it is associated with.
But I'd consider moving responsibility for connection construction into an ICommand, and exposing this command via your top-level ViewModel. The OK button on your master dialog you would then bind to this command, and the command would just delegate to the top-level ViewModel, for example, call ViewModel.CreateConnection() when it is executed.
The responsibility of your nested control is then purely collecting and exposing the data to its NestedViewModel, for consumption by the containing ViewModel, and it is theoretically more re-usable in different contexts that require the same information to be entered (if any) - let's say you wanted to re-use it for editing already-created connections.
The only wrinkle would be if the different types of NestedViewModel expose a radically different set of data.
For example, one exposes HostName and Port as properties, and another exposes UserName and Password.
In which case you may need to do some infrastructural work to have your top-level ViewModel.CreateConnection() still work in a clean manner. Although if you have a small amount of nested control types, it may not be worth the effort, and a simple NestedViewModel type-check and cast may suffice.
Does this sound viable?
I recently experimented with Unity (Microsoft Enterprise library) to use dependency injection. That might be a route to go when using interfaces that completely define what both viewmodels need to no from each other. MEF would be another option for dependency injection I'm aware of.
HTH