I'm creating a game where I have a lot of different pages. For instance: loginpage, profilepage, playersfriendeditpage.
Do I create a ViewModel for each of them? They are all dealing with the model, "player", but in diffeent aspect. Whats common sense?
Well since a view model acts as interface to your model from your view, it makes sense that any time a view needs to modify a model differently than any other view has, you'll want a new view model.
In other words, even though various views may LOOK different, it's the interaction with the model/view model that dictates whether a new view model is necessary.
If your page contains a ton of stuff, it may make sense to break them up into sub VMs. I try to think of a ViewModel as just a class and like any other class, you don't want it to do EVERYTHING if it doesn't make sense to. If your page is logically broken up into a mini-views, then you should be able to easy encompass those needs in a sub-VM.
For example: say you have an edit page that contains all your info. Maybe the user information (name, address, phone #) is a VM, the work history is a VM and the hobbies section is a VM and your main VM basically does all of the stuff around it. You can use messaging and/or events to handle the communication needs.
ViewModels are useful when you want to create a model that contains an instance of another model. This is the case when you have a 1 to many relationship between one model and another (one table and another) and need to display both information on the same view, for example. Or not even 1 to many necessarily, but that's often the case.
If you have a drop down list that contains values populated from a table in a database, but your View should display all other information from a different model, for example, you would use a ViewModel in this example.
I would define a ViewModel as an abstraction of a view. The viewModel should contain properties and methods which provide the Data and behaviour that a view requires to function correctly.
Given this definition my instinct would be to provide a separate viewModel for each view as they are each likely to have their own unique behaviour.
The fact that all views depend on the same Player entity is an implementation detail and as has already been suggested this functionality should be moved into a base class that the other viewModels can derive from, something along the lines of this:
public abstract class ScreenViewModel : ViewModelBase // Implements INotifyPropertyChanged
{
private Player _currentPlayer;
public ScreenViewModel(IRepository<Player> playerRepository)
{
// Retrieve desired player from the repository.
this._currentPlayer = playerRepository.Find(...);
}
// This is an idea of the sort of thing you can do; derived viewModels
// do not need to worry about loading the player, they can just consume
// it and provide the screen specific behaviour.
protected Player CurrentPlayer
{
get { return _currentPlayer; }
}
}
I don't agree with the advice provided in the currently accepted answer as it is wrong; it is your views that should shape your viewModels not your database. The design of the database should have little or no bearing on the design of your viewModels. The whole point of having a viewModel between your view and your domain layer is to insulate your application from changes in the lower layers.
In fact, if you look at the example viewModel I have provided it is fairly well insulated from those sorts of changes. The Player would typically be exposed as a POCO (making it persistence ignorant) and the repository that provides access to those entities is hidden behind an interface.
This means I could change the way the database structure is implemented and these changes would be absorbed by the data layer (e.g. by changing the way Entity Framework maps the tables to the entities in the application) and the viewModel would require no changes. You could even change the persistence mechanism (I.E. save data to a custom file rather than a database) and as long as it mapped the data to the Player POCO and the new repository implemented the IRepository<Player> interface your viewModel would still work as expected, demonstrating that the database structure has little or no bearing on the design of your viewModels.
It depends on the way you design your database.
If you want all the fields to be in a same table you can keep them under the same view model and this is not the case with most of the cases because you wouldn't like to have any redundant information in your database and you want your database to be normalized. So you can structure your models depending on your database design so that your database has no redundant information.
Related
I'm writing a WPF desktop application. I'm trying to understand the MVVM flow of data. I'm using Entity Framework as a data access, and I'm using a code-first approach so I have my POCO entity classes that represent each SQL table.
With this configuration, it's my understanding that my model (M in MVVM) is my POCO entity class. My views (V in MVVM) are my WPF windows.
What populates my view models? Do I just make my EF queries inside my views, populating the view models? Do my view models perform their own querying (inside class constructor, perhaps)?
Typically the view is a WPF window and it's corresponding code behind. The view model is a simple class that is created to handle the data layer requirements for the specific view and to do the processing. It is common to use Commands in the XAML view on the controls and each command is bound to a command instance that is in the view model. The view model can be created by dependency injection or it can be passed into the constructor in the views code behind and it is stored as member/property in the code behind. Make sure to set the views data context to the instance of the view model so to allow binding to the properties and commands in the view model.
this.DataContext = new TheViewModelType();
The Entity Framework Plain Old CLR Objects are data models and the view should not typically know about these. The view model may have properties of the model types that the view can bind to for say Items controls and such. So in the view:
<ItemsControl x:Name="CarItems" ItemsSource="{Binding Vm.CarsCollection}"></ItemsControl>
So, since the view's DataContext is a instance of the view model type, the view controls may bind directly to properties in the view model. The example is the view model having a collection of Cars and the view model may call a service when needed to populate the Cars collection. Obviously the a Car is the model.
public MyViewModel( )
{
Cars = TheCarsDataLayerService.GetCars( );
}
private IObservable<Car> _cars;
public IObservable<Car> Cars
{
get { return _cars; }
set
{
if( _cars == value )
return;
_cars = value;
RasisePropertyChanged("Cars");
}
}
For the Cars service int the example, This may be a data layer repository or it could be a instance of the Entity Framework DbContext. So the view model can have a field of the DbContext derived type or a service of such and this can be passed into the constructor of the view model class or injected with dependency injection or maybe the service is a static factory or singleton that the view model just calls into to populate the its members with the data that the view is going to display to the user.
MVVM is a pretty basic design pattern that can be implemented in many different ways. Some developers will take the pattern to new heights and strictly obey many rules in which the components of the pattern communicate. Ultimately,using the pattern is much better than not using any pattern at all regardless of how it is implemented, as it will allow the code to scale much better and other developers might much more easily understand the code and expect certain things. Also, the MVVM pattern allows for WPF devs to unit test. When done well enough, the view models can be tested and since there is no code in the views code behind and the view doesn't do anything but display data that it doesn't even know about, testing the view model is good enough.
Strictly using your domain models as view models will eventually if not immediately cause you problems. Typically a domain model consists of raw data, it may or may not contain business operations, some may place that in a BusinessLayer manager class for example. But you VM ViewModel is strictly for the view, should exist only in the view project. Cluttering your domain with view related dropdowns etc... is not an appropriate place to put those "View" data sources.
So to put this in code terms, your view model can contain a property that references an instance of the domain model OR you could add every property that the view will expose. But by separating the ViewModel and Model (domain model) you are allowing the view to be able to expose/hide what it needs as well as convert some properties, for example an EntityFramework model may contain a string property but your view may want a strictly numeric representation of it on one screen while another may allow an edit as string property, point is your EF model (domain model) doesn't need to worry about those view issues.
Where do you create the VM?
The job of a controller is to interpret a request and determine the view and view model needed. So it would be in the controller that the VM is created using a EF domain model class (for an edit request as an example) as the source of the VM.
I've searched both SO and Google on this but have not found a relevant / acceptable answer.
Background:
* Using MVC 4.5
* I have some Generic Repo<T> that I am using over the top of EF5, which in turn are accessed by generic Service<T>
* I have domain models and view models and I am using Automapper to map between them, this mapping happens in the Service layer
* On top of that, I have my Controllers which again are generic as much as possible.
So, to the question; I have a couple of scenarios where I need to present a list of options to the user and they have to select one or more. The options are user specific, so my domain User has a List<Location> which is their saved locations, and when adding / modifying, an Item, they are required to select at least one Location.
I am resisting the temptation to fetch that List<Location> in my controllers because I want to keep them generic and slim, but at the same time, I'd rather not have two properties in my ItemView model, one for AvailableLocations and one for SelectedLocations, because this model is used not just for adding / modifying but for search results etc.
Options:
* Should I introduce a different model for adding / modifying an Item, e.g. ItemInput?
* Should I use some custom mapping and get Automapper to get the list of available locations?
* In which layer should I fetch these available locations?
What are people's suggestions on a neat and generic approach to this please?
Many thanks!
I would do something like this:
public IEnumerable<Location> GetLocations() {
return db.GetAll();
}
Then inside of your controller (I followed this from MVC scaffolding):
ViewBag.Locations = new SelectList(service.GetLocations, "name", "id");
(or your own checkbox list)
and put a listing control on the HTML/View page.
The reason I believe this is the best method is because the logic all resides inside the service. If you put it in your DTO/data model you may come against this problem:
What happens if you require additional logic to pull back locations? i.e. sub locations of locations.
You change your service (or override) to reflect the new changes, and this logic would go inside of the service:
public IEnumerable<Location> GetLocations(string parent) {
return db.GetAll().Where(loc => loc.parentname = parent);
}
p.s. I never use generic services, the reason I have a service is because some of the data access it provides contains logic that is not meant to sit with the generic DAL.
I could make an interface or abstract service to make my life a little easier for common operations between services but once you define say a concrete, a UserManagementSerive surely you are saying you want to manage an object that has Users, and Locations and Items each having its own specific functionality?
I don't think there is only one possible answer to this question.
I would recommend a simple, but not-so-generic approach. I would write what's called ViewModels, i.e. model classes that are related to your specific views. Then I would get your available locations from the controller, and populate an instance of the ViewModel in your controller using the fetched locations.
Basically I would expose some services like:
IEnumerable<Location> GetAvailableLocationsForUser(string userName);
Do note I've used IEnumerable<T>, not IQueryable<T>. Because the implementation will actually request the database, as it's too much bug-prone (at least IMO) if it's the role of the controller to do so (remember the deferred execution of IQueryable<T>).
And it returns a domain instance, i.e. an entity, not a mapped model. I wouldn't personally deal with anything but domain classes in the service layer. There could be domain classes that are not entities, but compositions of entities for example. This could help making efficient requests and avoiding using lazy-loading and deferred execution in the controllers. This is helpful when the controller needs a whole object graph and not only an entity.
Then I would write Models and ViewModels like the following, in the web application assembly:
public LocationModel
{
...
}
public CreateItemViewModel : ItemModel
{
public List<LocationModel> AssociatedLocations { get; set; }
public List<LocationModel> AvailableLocations { get; set; }
...
}
There are basically Models (ItemModel and LocationModel), which are objects related to the web application. This means there could be some web-related things in those models, for example computed read-only properties or attributes on properties (DisplayAttribute...etc.).
I would write those models multiple times, actually, because I don't think this is something that could be generalized: for example, one view could require the use of a navigation property while another view wouldn't. So this changes the depth of the mapping process depending on the views that uses the model. And I wouldn't use AutoMapper at all (only hand-written mappers).
There are also ViewModels (CreateItemViewModel), which are objects related to a single view (for example the view that allows to create an Item in this example). The difference between Model and ViewModel is that the ViewModel is related to a single view (and named according to this view). On the other hand, Models are related to multiple views (its namespace would help to know which views. For example, xxx.Item.Models for Models related to all views in the xxx.Item directory). ViewModels are built from scratch in the controller (or in a separate mapper) based on the domain classes.
In the above example, you could build a domain classes that would return AssociatedLocations and AvailableLocations, but it would require your service layer to be aware of the web part (I mean, your service interface and domain classes would know which properties are needed for a particular view). I'm not sure those properties are actually related to a single view in your application, but if it's not the case, you could also build a domain class as a composition of entities that would return AssociatedLocations and AvailableLocations:
public ItemExtended : Item
{
public List<Location> AssociatedLocations { get; set; }
public List<Location> AvailableLocations { get; set; }
}
ItemExtended GetItemExtendedById(long idItem);
I've recently started creating a WPF application, and am just hoping that someone can confirm to me that I'm building my overall system architecture properly, or correct me if I'm heading off in the wrong direction somewhere. Especially since I'm trying to do MVVM, there are a lot of layers involved, and I'm not sure I'm doing things properly.
Here's a simplified description of the system:
Data is stored in an SQL Server database, which is accessed through Linq to SQL. Let's say that the database contains two tables, USERS and USER_GROUPS. Each table has an auto-generated Linq to SQL class, DB_USER and DB_USER_GROUP.
Now in the application, I want to display a ListBox with each ListBoxItem containing various UI elements for displaying/modifying the users' info, which is done using a DataTemplate.
I have a view model class for the window, which uses a Linq to SQL query (joining the two tables) to populate an ObservableCollection<User> named UserList, which the ListBox in the window has bound as its ItemsSource. User is a class implementing INotifyPropertyChanged that handles all the formatting/getting/setting of database data into what's needed by the WPF controls. The section of code handling this is something like:
DBDataContext db = new DBDataContext();
var allUsers = from user in db.USERs
.Where(u => u.ENABLED == true)
from group in db.USER_GROUPs
.Where(g => g.GROUPID == u.GROUPID)
.DefaultIfEmpty()
select new { user, group };
foreach (var user in allUsers)
{
User u = new User(db, user.user, user.group);
UserList.Add(u);
}
So the User class is constructed with private properties for a DB_USER, a DB_USER_GROUP, and the database DataContext class. All of a User's public properties basically wrap the relevant columns, with their get methods returning the values for WPF to use, and set changing the column(s) and then calling SubmitChanges() on the private DataContext property to update the database.
This is all working fine, but it feels a little unwieldy, so I'm just wondering if I've missed something that would make it cleaner. Specifically, storing a DataContext inside each element of UserList seems odd, but I wasn't sure of a better method to be able to update the database whenever data was changed in the UI.
Any feedback is appreciated, and please let me know if anything's unclear, I'm not sure how well I've explained it.
Starting off, let's put some labels on what you are doing here: DB_USER is your Model and User is your ViewModel (I 'd have preferred UserViewModel for the latter just so that it's more clear what's going on).
One thing that's immediately obvious is that it's not really proper for your ViewModel to have functionality suited to your Model, i.e. that DataContext does not belong where it currently is. This is a piece of information that should either be in your Model, or alternatively encapsulated in some DataStore/DataService (take your pick) class. Your ViewModel would then be responsible, when the time comes to save any changes, to tell the DataStore "here's an updated snapshot of this model, please save it for me" (this would most likely be exposed to the UI through an ICommand). This feels cleaner and underscores the idea that your ViewModel is a layer that adapts the realities of your model to your choice of UI.
Other than the above, there's nothing in what you describe that I feel needs to be "corrected". However, I can offer some suggestions regarding things that you have not elaborated on.
Exposing data from a Model through a ViewModel is always something that can be implemented in many ways. When considering what approach to take, you should take into account the possibility of the same Model being exposed through different Views at the same time. In this case, IMHO the preferred approach is to have a separate ViewModel for each View (the Views may well be of different types, so they could have different expectations from the ViewModel adapter thus pointing to multiple types of ViewModels as well), so you would need to use a pattern that allows changes to be communicated from one ViewModel to any others in "real time".
One way to do this would be to make your Models implement INotifyPropertyChanged themselves and have each ViewModel hook into its Model for notifications, so when a change occurs ViewModel A pushes the change to the Model, and the Model notifies ViewModel B.
However personally I don't like polluting my Models with what is in essence code that only caters to the needs of the UI, so another approach is needed. That would be making the DataService I mentioned above expose functionality (methods and events) through which ViewModel A can tell the service "hey, the Model I 'm wrapping has had some changes" ; note that this is different from "I want you to persist the current snapshot of this Model". ViewModel B has already hooked into a suitable "ModelChanged" event, so it gets notified and pulls the updated information from the service. This has the added benefit that if at any time the service detects that the backing data repository has been updated by a source external to the current process, there's a ready made mechanism to broadcast a "Calling all ViewModels: Model X has been updated, any interested parties please talk to me about learning the details" message.
Above all, always keep in mind that there is no "one true MVVM style" and there are myriads of possible approaches. Which one to take depends not only on hard facts and the current position of the slider on the YAGNI/HyperEngineering scale, but also on, dare I say, your taste.
Tricky question, and I can see why people aren't jumping all over themselves to answer—mainly because you aren't doing anything technically wrong. But since you ask, I'll tell you what I'd change to tighten up both MVVM (which you asked for) and the data acess (which you didn't).
The way I approach a ViewModel is as a wrapper for my underlying data model, rather than as an enhancement to my View. It assists the view by providing INotifyPropertyChanged and all that, but I try to make the ViewModel useful for whatever view it'll end up inside. That's the main difference, IMO, between MVC and MVVM. What you have is more of an MVC with your User object acting as a controller for the View.
Also, I'd probably do away with UserList and use the ListBox.ItemsSource to manage the list after binding it once. Actually, in WPF, I've gotten more used to having a CollectionViewSource and binding the UI controls to that. Makes it simpler to track selected items and adding to them and removing from them isn't too onerous.
For the data access, I wouldn't feed those into the object at all. Data access belongs in your model and persisting changes should be handled there. The .Net framework does a pretty good job with connection management, to the point where re-instantiation and teardown are the next best thing to costless. That allows you to keep things tight and wrap data connections in using clauses. If you really feel like you have to persist to the database on every property change, have your model subscribe to the PropertyChanged event—that's what it's there for, after all. :)
Usually, I keep my models as dumb as possible (POCO). My viewmodel has the heavy logic of querying the database and setting its properties that are bound to the UI. In that layout, the viewmodel has a single instance of your DataContext and there is no need for it to be passed around inside of the models.
I generally follow that approach with some differences, big surprise there :) In larger projects I don't like to wrap or include my domain entities in my ViewModels. This is something I carried over from the ASP.NET MVC in Action books where you map (AutoMapper) domain entities to display models before the view receives them. Its nice when there is an impedance between the domain entity(s) and what needs to be displayed.
It also comes in handy when mocking up the screens, I can work from the screen backwards to the DisplayModel knowing I'll map what I need from the domain entity. I'm big on my Views being blendable so a designer can open the View up and it looks pretty close to run time View.
So in some cases I'll have my entity models (User/UserGroup), my DisplayModel (User), and my ViewModel (UserViewModel).
As mentioned in other answers I tend to keep the data business out of the ViewModel. I'll create a Repositiory or a service of some type and inject it into my ViewModels. So in my ViewModel I might call var user = UserRepository.GetUsers(); and then map the results to my DisplayModel. Or UerRepository.InsertOrUpdate(user); UserRepository.Save();
Unrelated, AutoMapper is a great tool as well as Caliburn Micro or MVVM-Light.
With MVVM, I think of a view-model as a class that provides all the data and commands that a view needs to bind to.
But what happens when I have a database entity object, say a Customer, and I want to build a class that shapes or flattens the Customer class for use in a data grid. For example, maybe this special Customer object would have a property TotalOrders, which is actually calculated using a join with a collection of Order entities.
My question is, what do I call this special Customer class? In other situations, I'd be tempted to call it a CustomerViewModel, but I feel like "overloading" the notion of a view-model like this would be confusing in an MVVM project. What would you suggest?
I believe you were correct in your original thoughts. The "View Model" classes are those that expose data objects in the domain Model such that these model objects are more easily consumed and managed.
Check out http://en.wikipedia.org/wiki/Model_View_ViewModel
Therefore, the Customer and Order classes are pieces of the "Model". What you describe and were considering calling the CustomerViewModel is indeed a "View Model" and then obviously your WPF page/control is the "View".
In terms of naming it... Go with whatever you like! But I like your original idea of CustomerViewModel. Or perhaps name it a little closer to that of the View. For example, CustomerOrderSummaryViewModel if the page is the CustomerOrderSummary page.
We call ours Data View Models.
For example, we may have Results.xaml that has the Results_ViewModel as the view model. The results page has a grid, where each row in the grid is a Customer. But, like you said, you want a view model for the customer so that you can have a property like 'Total Orders.' In this case, our grid would contain a collection of Customer_DataViewModel.
This comes up quite frequently where is some examples you have a List objects that aren't quite view models. Since you are changing the Customer model object into something more for the VM, you could name it CustomerDto or I agree with the rest of the posters, CustomerViewModel (CustomerVM) is fine too.
I do not like the CustomerDto as it implies another concept (ie. something representing data to be sent elsewhere). We use the term PresentationModel as it is basically 'presenting' an underlying model object with properties that do not belong in the model-layer. For me, I use the term ViewModel for when I can actually change the model and PresentationModel for read-only views.
In my ASP.NET MVC app, I have a fairly complex edit page which combines a number of models into one view.
I'm using the ViewModel pattern to combine all of this information and present one cohesive object to the View.
As an example, my ViewModel structure is something like this:
CompanyId
CompanyName
List<Employee> Employees
List<ContactMethod> ContactMethods
The Employee object has a number of basic properties, and a preferred contact method.
On the edit page, the user is given all of the employees of the company and they have the ability to add and remove (using javascript), as well as edit employee details. The ContactMethods list is used to populate the dropdown for each employee.
I've successfully translated my Models (read from the database) into this ViewModel and back again, so after an edit, I'm left with a ViewModel representing the current state of that company's employees.
I'm using a Repository pattern to communicate with the database, so my question is, should I call directly into the CompanyRepository, passing the ViewModel, or should I convert the ViewModel back into Model objects first before using the Repository to write them to the database?
In short, should the Repository know about my ViewModel objects?
I would convert the ViewModel back into Model objects first. I like keeping the dependency between my Web layer and Repository layers as loose as possible.
I don't think your Repository should know about your ViewModel, since that's a web level concept.
ViewModel is the model to the view (UI), so repository shouldn't know about the view model. Separating them will keep repository loosely coupled from the UI.
Use another layer like service layer, to encapsulate repository from the UI.
This layer also does the ViewModel - Model conversation and do respository call.
public class ServiceLayer
{
public void SaveModel(ViewModel viewmodel)
{
var model = viewModel.ToModel();
repository.Save(model)
}
}
I would agree with the previous answer of converting ViewModels back into "plain" Models, but would add that this task should probably be carried out by a separate service layer. This layer would be responsible for disassembling your ViewModels and acting appropriately.
This is essentially the definition of a service: something whose job is to carry out a logical unit of work that requires multiple models and/or complex logic.