Is ViewModel inheritance acceptable in MVVM? - c#

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.

Related

C# WPF declaring interface upon ViewModel

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!).

Does anything speak against making all domain objects inherit from INotifyPropertyChanged?

I'm refactoring and redesigning the domain objects of my application which uses MVVM to some extent. Is there anything that speaks against making all Domain objects (POCOs) inherit from INotifyPropertyChanged, so anyone can observe the objects as they wish.
In combination with https://stackoverflow.com/a/1316566/448357 this does not even have to be very ugly.
On the other hand, what about polluting my domain object with stuff that might not be required at all, because there will be a separate View-Model anyway? Margabit points out: UI Model != Domain Model
IMO, Domain objects shouldn't implement INotifyPropertyChanged. The one who should be implementing it is your ViewModel.
The reasons for that is:
You would probably mostly need to raise a PropertyChanged event inside your viewmodel which holds your POCOs
You would be implementing it only once.
If your POCO wants to raise an event and notify that something has occured inside it, im not sure PropertyChanged would be the most meaningful event to raise.
I think it depends a little bit on the scope of the project: if this is a small project, where Domainmodels are also used as UI-mmodels, sure go ahed an do so if you like.
But if you frequently NEED UI-models, e.g. because there are a lot of properties / methods which are not part of your domain model, don't bother - you create overhead for little or no reason.
When do you need a UI-model? My rule of thumb: If you are introducing a property with an[NotMapped] (Entity Framework) Attribute, go ahead and make a UI-model with this property.
Alsoif there is a chance that parts of this project are used in another context( Webapp, phone etc. pp) , I would advise against it- you will need UI models anyway.
To avoid to insert code in your classes you can make a transparent proxy.
You can use Castle
http://www.castleproject.org/dynamicproxy/index.html
The only limitation is that you have to create instances of your classes via factory.
You could also use System.Runtime.Remoting.Proxies.RealProxy class but your base class must derive from MarshalByRef (is still POCO? :) ).
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=IT-IT&k=k(SYSTEM.RUNTIME.REMOTING.PROXIES.REALPROXY)%3bk(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22)%3bk(DevLang-CSHARP)&rd=true

In a layered architecture using Entity Framework, should I return POCO classes from the BLL? (Architecture guidance needed)

I've been reading too much probably and am suffering from some information overload. So I would appreciate some explicit guidance.
From what I've gathered, I can use VS2010's T4 template thingy to generate POCO classes that aren't tied directly to the EF. I would place these in their own project while my DAL would have an ObjectContext-derived class, right?
Once I have these classes, is it acceptable practice to use them in the UI layer? That is, say one of the generated classes is BookInfo that holds stuff about books for a public library (Title, edition, pages, summary etc.).
My BLL would contain a class BooksBLL for example like so:
public class BooksBLL
{
ObjectContext _context;
public void AddBook(BookInfo book) { ... }
public void DeleteBook(int bookID) { ... }
public void UpdateBook(int bookID, BookInfo newBook) { ... }
//Advanced search taking possibly all fields into consideration
public List<BookInfo> ResolveSearch(Func<BookInfo, bool> filter) { ... }
//etc...
}
So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?
Furthermore, MVVM posts on the Web suggest implementing IDataErrorInfo for validation purposes. Is it okay if I implement said interface on the generated POCO class? I see from samples that those generated POCO classes contain all virtual properties and stuf and I hope adding my own logic would be okay?
If it makes any difference, at present, my app does not use WCF (or any networking stuff).
Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.
Update (Additional info as requested):
I'm trying to create a library automation application. It is not network based at present.
I am thinking about having layers as follows:
A project consisting of generated POCO classes (BookInfo, Author, Member, Publisher, Contact etc.)
A project with the ObjectContext-derived class (DAL?)
A Business Logic Layer with classes like the one I mentioned above (BooksBLL, AuthorsBLL etc)
A WPF UI layer using the MVVM pattern. (Hence my sub-question about IDataErrorInfo implementation).
So I'm wondering about stuff like using an instance of BooksBLL in a ViewModel class, calling ResolveSearch() on it to obtain a List<BookInfo> and presenting it... that is, using the POCO classes everywhere.
Or should I have additional classes that mirror the POCO classes exposed from my BLL?
If any more detail is needed, please ask.
What you're doing is basically the Repository pattern, for which Entity Framework and POCO are a great fit.
So, my ViewModels in my MVVM UI app will be communicating with the above BLL class and exchanging BookInfo instances. Is that okay?
That's exactly what POCO objects are for; there's no difference between the classes that are generated and how you would write them by hand. It's your ObjectContext that encapsulates all the logic around persisting any changes back to the database, and that's not directly exposed to your UI.
I'm not personally familiar with IDataErrorInfo but if right now your entities will only be used in this single app, I don't see any reason not to put it directly in the generated classes. Adding it to the T4 template would be ideal if that's possible, it would save you having to code it by hand for every class if the error messages follow any logical pattern.
Also, if you see something terribly wrong with the way I'm trying to build my BLL, please feel free to offer help in that area too.
This isn't terribly wrong by any means, but if you plan to write unit tests against your BLL (which I would recommend), you will want to change your ObjectContext member to IObjectContext. That way you can substitute any class implementing the IObjectContext interface at runtime (such as your actual ObjectContext), which will allow you to do testing against an in-memory (i.e. mocked) context and not have to hit the database.
Similarly, think about replacing your List<BookInfo> with an interface of some kind such as IList<BookInfo> or IBindingList<BookInfo> or the lowest common denominator IEnumerable<BookInfo>. That way you're not tied directly to the specific class List<T> and if your needs change over time, which tends to happen, it will reduce the refactoring necessary to replace your List<BookInfo> with something else, assuming whatever you're replacing it with implements the interface you've chosen.
You don't need to do anything in particular... as Mark said, there is no "right" answer. However, if your application is simple enough that you would simply be duplicating your classes (e.g. BookInfoUI & BookInfoBLL), then I'd recommend just using the business classes. The extra layer wouldn't serve a purpose, and so it shouldn't exist. Eric Evans in DDD even recommends putting all your logic in the UI layer if you app is simple and has very little business logic.
To make the distinction, the application layer should have classes that model what happens within the application, and the domain layer should have classes that model what happens in the domain. For example, if you have a search page, your UI layer might retrieve a list of BookSearchResult objects from a BookSearchService in the application layer, which would use the domain to pull a list of BookInfo.
Answers to your questions may depend on the size and complexity of your application. So I am afraid there will be valid arguments to answer your questions with Yes and No as well.
Personally I will answer your two main questions both with Yes:
Is it acceptable practice to use POCO (Domain) classes in the UI layer?
I guess with "UI layer" you don't actually mean the View part of the MVVM pattern but the ViewModels. (Most MVVM specialists would argue against letting a View directly reference the Model at all, I believe.)
It is not unusual to wrap a POCO from your Domain project as a property into a ViewModel and to bind this wrapped POCO directly to the View. The big Pro is: It's easy. You don't need additional ViewModel classes or replicated properties in a ViewModel and then copy those properties between the objects.
However, if you are using WPF you must take into account that the binding engine will directly write into your POCO properties if you bind them to a View. This might not always be what you want, especially if you are working with attached and change-tracked entities in a WPF form. You have to think about cancellation scenarios or how you restore properties after a cancellation which have been changed by the binding engine.
In my current project I am working with detached entities: I load the POCO from the data layer, detach it from context, dispose the context and then work with that copy in the ViewModel and bind it to the View. Updating in the data layer happens by creating a new context, loading the original entity from the DB by ID and then updating the properties from the changed POCO which was bound to the View. So the problem of unwished changes of an attached entity disappears with this approach. But there are also downsides to work with detached entites (updating is more complex for instance).
Is it okay if I implement the IDataErrorInfo interface on the generated POCO class?
If you bind your POCO entities to a View (through a wrapping ViewModel) it is not only OK but you even must implement IDataErrorInfo on the POCO class if you want to leverage the built-in property validation of the WPF binding engine. Although this interface is mainly used together with UI technologies it is part of System.ComponentModel namespace and therefore not directly tied to any UI namespaces. Basically IDataErrorInfo is only a simple contract which supports reporting of the object's state which also might be useful outside of a UI context.
The same is true for the INotifyPropertyChanged interface which you also would need to implement on your POCO classes if you bind them directly to a View.
I often see opinions which would disagree with me for several architectural reasons. But none of those opinions argue that another approach is easier. If you strictly would want to avoid to have POCO model classes in your ViewModel layer, you need to add another mapping layer with additional complexity and programming and maintenance effort. So I would vote: Keep it simple as long as you do not have a convincing reason and clear benefit to make your architecture more complex.

Pass values between UserControls

I have a main window, which has four user controls on it. These five entities need to communicate with each other. Is there an established method for passing values and objects between UserControls?
Edit: I'm familiar with MVVM, but I am asking for solutions outside of that paradigm.
There are a lot of ways and it depends on what you actual scenario is. The most straight forward one would be to expose public properties and/or events in your UserControls. This is the preferred way if you want to get view specific data across. If your the communication is more model related you should go the route through your ViewModel (and use MVVM).
Generally I think UserControls accessing each other directly is a strong hint toward desgin smell. It is very likely that there is a better aproach for you concrete scenario (Mediator, Eventaggregator, Controller or just the parent control).
You can communicate five entities using making delegates.
I think you need to decide upon domain model according to your project requirement and then create classes which represent entities in your model. Then pass objects of this entities as required.
There are many ways, one is to use events. There are no "direct" methods, you need to route your values through a form or a model class.
There is an established pattern called MVVM (just google for it) that has a unified way of communicating between different contols, databases, web services, calculations etc. MVVM is not a pattern for communicating between different controls, it is a much larger pattern, but it solves that part too.

MVVM: How to handle interaction between nested ViewModels?

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

Categories