I've recently started develping an application using WPF and I'cant really wrap my mind around following thing:
I have a Domain Model of my application which is simple POCO objects serialized to/from harddisk. Then I have the WPF application and I'd like to bind it to various parts of the model. I need to be able to notify UI of changes to underlying model (eg. implement INotifyPropertyChanged) BUT I want to do that without interfeering with my model (read without modifying current implementation of the model). How can I implement changes notification other than modifying the model?
Reason why I want to do that is that I share the model among multiple projects, only one being WPF, and I don't want to add unncecessary code to the model.
One thing that came to my mind was to create "copy" of the model (with INotifyPropertyChanges and BindingLists etc.) but that seems to be hard to maintainn...
Thanks in advance.
Ondrej
Check this out MVVM
Download its source code see the hierarchy.
Basically you still keep simple POCO objects as your models. Then you create a ViewModel around the model like this:
public class CustomerViewModel : INotifyPropertyChanged
{
readonly Customer _customer;
public CustomerViewModel(Customer customer)
{
_customer = customer;
}
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
OnPropertyChanged("FirstName");
}
}
...
}
I see two possible solutions here:
Use a separate model for WPF screens only (MVVM pattern). This will require maintaining two different models, also be prepare for lots of mapping code.
Use PostSharp to "enhance" your model with all necessary boilerplate code. Here you can find example of automatic INotifyPropertyChanged implementation. Remember that introducing PostSharp to the project is an important decision, so I suggest getting familiar with it first.
Related
So I was looking at https://github.com/xamarin/Sport as an example I came across when googling something for my current project. It is similar to what Im working on because I use an azure backend as well.
I have a question about their mvvm layout. I thought that in mvvm the models were sort of POCOs and not supposed to implement INotifyPropertyChanged. Arent they acting as both a Model and a ViewModel in this case? Look at the Athlete model and the AthleteViewModel. The VM has a property for for Athlete and so the model is used as a VM as well.
In my project, if I had the same types, I would have an Athlete model, an AthleteViewModel and an AthletePageViewModel. Where the Athlete and AthleteVM would be automapped. The only reason to populate and or create the Athlete is to persist it to the service or local storage.
Is one way more "correct" than the other way? Or am I just doing it wrong and over complicating it? I almost don't want to continue with the way I'm doing it because I dont want to have a bunch of "extra" model files if I can just use some of my VMs as models.
Thanks.
There's no ultimate master set of strict rules that you need to follow in order to implement the MVVM design pattern. In fact, the guidelines are generally quite blurry.
From what I've seen, there are a couple of different methods of which a model may be exposed to the view. Here they are:
Method 1 - INotifyPropertyChanged in the Model
public class Car : INotifyPropertyChanged
{
private string _Model;
public string Model
{
get { return _Model; }
set
{
_Model = value;
NotifyOfPropertyChange();
}
}
...
}
public class CarViewModel
{
//The entire model is exposed to the view.
public Car Model { get; set; }
...
Method 2 - INotifyPropertyChanged in the View Model
public class CarViewModel
{
private Car _Car;
//The model property is exposed to the view, not the model itself.
public string CarModel
{
get { return _Car.Model; }
set
{
_Car.Model = value;
NotifyOfPropertyChange();
}
}
...
In terms of a preferred method, I would say method 2 is the better option. Why?
The Model object is not exposed to the view.
The View Model only exposes what the View needs.
Method 2 does have its downsides. Imagine if you needed to expose lots of model properties, or imagine if your model changes, it is certainly easier to simply implement INotifyPropertyChanged in the model and expose it to the view. Programmers are lazy by nature, therefore in order to save hassle, you'll see method 1 just as much as method 2.
But that isn't a bad thing.
Is one way more "correct" than the other way? Or am I just doing it wrong and over complicating it?
Remember, the MVVM design pattern is just a pattern. Neither options are correct, it's mostly down to the developers preference how they choose to approach the implementation of the pattern, as long as the main MVVM concepts are there, that's all that matters.
I'm having some issues with the setup i'm currently using with my mvvm application. Having seen some posts on here, i get the feeling i may be doing this slightly wrong.
I have several models which contain lists of child models such as:
Project - Contains a list of proformas
Proforma - Contains a list of shipments orderedItems
Shipment - Contains a list of Containers
Container - Contains a list of packages
We do not have any viewmodels that relate directly to these model currently, we instead simply have viewmodels that represent the list of models, for example we have a proformalistviewmodel which simply contains a list of proformas.
My issue is, that with this setup i'm a little confused as to what viewmodel should own which data, for example the ProfomalistViewModel has a reference to the currently selected Project, all the data management for these models (the loading and saving of the list of proformas) is done via manager classes which are loaded via DI.
My question is should i instead be following what I'm seeing and having a ProjectViewModel which contains a list of proformas, and a ProformaViewModel which contains a list of shipments and ordereditems and so on.
The reason for this, is that originally none of the models we're linked, projects did not own a list of proformas they were instead loaded separately via the managers using the selected project ID (using a relational db) and we're currently changing the models to the system i described above.
A viewmodel should be a model of the user interaction for a particular area of functionality
For instance, if you have a project list page and the user can do certain things like delete a project, edit a project, print information about the project then you should design a viewmodel that contains the data and actions associated with this interface:
e.g. the viewmodel should contain:
* A bindable container for the project data (list of projects)
* Actions that handle edit/delete interaction
* An action to handle the print functionality
The actual functionality inside these actions may not be contained within the viewmodel (the VM may have received injected services such as the print service or the project repository) but the responsibility of execution of these actions lies with the VM.
It may also be necessary to wrap each data item (project) in a viewmodel so that additional interaction dependent properties/actions can be added - such as the 'selected' property (imagine the user wants to multi-select a load of projects in the view - you could add a selected property to the ProjectViewModel which will wrap each project which makes binding easy)
You may end up with something like the following:
public class ProjectOverviewViewModel
{
public IList<ProjectViewModel> Projects { get;set; }
public ProjectViewModel SelectedProject { get;set;}
public void EditSelected()
{
// Code to open edit page for the selected project
}
public void Print()
{
}
}
and the ProjectViewModel with a selectable property
public class ProjectViewModel
{
// Either put the actual data item in here and wrap it:
public Project Project {get;set;}
// Or copy properties onto the viewmodel using automapper or some other mapping framework...
// or manually :(
// e.g. properties mirrored from the entity object:
public int ProjectId { get;set;}
public string ProjectName { get;set;}
// The selected property - now your 'Selected' logic is a function of the view/viewmodel
// not the entity. The entity should only be concerned with data persistence
public bool IsSelected {get;set;}
}
You may also want to composite viewmodels together in order to build more complex views. Imagine you have a projects page and a "users involved in a project" page, and you wanted another page that showed both side by side (and allowed you to click a project which would refresh the users pane) - this is possible by compositing the viewmodels (by creating another viewmodel which contains the two viewmodels as properties and wires up the interaction between the two)
public class ProjectAndUserOverView
{
public ProjectOverviewViewModel ProjectOverview {get;set;}
public ProjectUsersViewModel ProjectUsers {get;set;}
// Code here to listen for property changes in ProjectOverview and if SelectedProject changes
// call ProjectUsersViewModel to refresh the data for the selected user
}
Ultimately you are just modelling the user interaction, and the more modular you can make it, the easier it will be to make cleaner more maintainable code
There are some good MVVM frameworks - my personal fave is Caliburn Micro as it makes the above very easy (it heavily uses conventions by default) and is easy to get into.
MVVM is design pattern which have 3 parts: Model, ViewModel, View. DIagram looks like this:
http://en.wikipedia.org/wiki/Model_View_ViewModel#Pattern_description
You use ViewModels wrong. Only data for displaying should be in ViewModel.
Your Model for example:
public class Project
{
public Proforma Pr{get;set;}
}
public class Proforma
{
public string Name{get; set;};
}
You have View for project display(I inject ViewModel to constructor, tou can use DataContext instead):
public partial class ProjectView
{
private ProjectViewModel vm;
public ProjectView(ProjectViewModel vm)
{
this.vm = vm;
}
}
If you want to display proforma name on Project view, you should provide it as string in ViewModel.
public class ProjectViewModel
{
private Project pr;
public string ProformaName{get{return pr.Pr.Name;}}
}
If you provide Proforma like proforma, your View will know about model. It will be a violation of the pattern.
My five cent is that MVVM is a pattern, not a religion. I use it at far as it goes and makes sense. There's many parts where MVVM is undefined (like user interaction from commands), and I read a lot about ViewModels being created just to fit MVVM (which bloats both design and object count). I would suggest you think more DataContext-wise, like "Selections of global interest are kept in a global DataContext, Proforma related data is kept in a Proforma DataContext" and so forth, where DataContext is some sort of ViewModel. In the end, you'll probably wind up rigging those up with UI.
You shouldn't create ViewModels for your model objects.
Generally speaking, a ViewModel should belong to a UserControl. Its role is to wire your view (your XAML) together with your model (business logic).
In your case, if I understand it correctly, you have a bunch of classes that implement business logic (Project, Shipment etc.). Your ViewModel will have access to the business logic, and provide properties for your view to bind to.
I do not see any problem with having view models that wrap model data objects. Viewmodels do not have to be "one per view". They can represent a row in a list or whatever.
Having said that, I am quite happy binding directly to model objects and I do it a lot. The only time I create a view model to wrap it is if I need extra state per object that is required by the view.
I'm creating an application that enables a user to insert, update and delete data that has been entered and then shown in a data-grid (CRUD operations).
In my View Model, it contains properties which are bound to the xaml (Firstname for example). It also contains a navigation property as well as validation attributes.
[Required(ErrorMessage = "First Name is a required field")]
[RegularExpression(#"^[a-zA-Z''-'\s]{1,20}$", ErrorMessage = "First Name must contain no more then 20 characters and contain no digits.")]
public string FirstName
{
get { return _FirstName; }
set
{
if (_FirstName == value)
return;
_FirstName = value;
OnPropertyChanged("FirstName");
}
}
Furthermore, it contains commands for the xaml to execute, which creates an instance of the CRUD operation;
private void UpdateFormExecute()
{
var org = new OrganisationTypeDetail();
UpdateOrganisationTypeDetail(org);
}
And lastly, it contains the CRUD operations as well. Such as the Insert, Update and Delete.
Which leads me to my question. if I want to implement the correct MVVM way, is all this code too much for the view model to contain?
Should I use the model and create a collection within my View-model and bound that to my xaml? Would this be the correct way of doing it?
Should I use a Repository system for the CRUD operations? If so, how would I pass the data from the text fields through to the model to get updated?
Im new to WPF, MVVM and finding it hard to adapt without proper guidance.
I would say that this is a correct way to implement MVVM, but not the correct way to implement MVVM.
What I mean by this is that there is no one correct way to implement this pattern. if you have created a ViewModel that can be bound to your View, without having any extra logic within your View (i.e. code-behind) then you have captured the essence of MVVM.
Whether or not you add more patterns and structure to your code is entirely up to you. If this is a simple application, I would keep the patterns light. Go ahead and have your ViewModel talk directly with a repository. You current code looks just fine to me in that respect.
If this is a large application, you might want to add further layers, like a service layer, data access layer. You might want to think about dependency injection.
But don't just adopt a pattern, or add an extra layer just because you think you should. Dependency Injection sounds cool, but in many cases it is more hassle than it is worth!
For me it’s not the correct way, I think defining the properties like FirstName in view model is not good idea. view should contain model only and your view model should be wrap the model which should be bounded to XAML(if required).
Also model object creation should be completely independent of view model. View model should know only about unit operations on models and validations should be inside the model e.g in your case FirstName validations are in ViewModel means you are only limiting GUI to validate the FirstName property, but what if someone set it from other place.
I am investigating WPF's MVVM design pattern. But am unsure where to put the Data Acess code?
In some examples I have looked at, data access is performed directly in the ViewModel. It seems odd to put something like linq to sql in the ViewModel? Other examples have a seperate project for Data Access, this seems more like it?
Is this there a general approach? I feel like I am missing something here!
Thanks
Here's how I've been organizing my MVVM w/ LINQ projects:
Model - I think of the Model as the state of the system. It provides an interface to the data, and it keeps track of system status. The Model does not know about the ViewModel or View--it just provides a public interface to its data and various events to let the consumers (usually ViewModels) know when the state has changed.
ViewModel - The ViewModel is in charge of organizing or structuring all the data needed by the View, keeping track of the status of the view (such as the currently selected row of a data grid), and responding to actions on the view (such as button pushes). It knows what the view needs, but it doesn't actually know about the view.
View - The View is the actual look and feel of the UI. It contains all the built-in and custom controls, how they arranged, and how they are styled. It knows about the ViewModel, but only for the purpose of binding to its properties.
Gateway - This is the part that directly addresses your question. The Gateway (which is basically my way of saying "DataAccessLayer") is its own separate layer. It contains all the code (including LINQ queries) to CRUD or select, insert, update, and delete data from/to your data source (database, XML file, etc.). It also provides a public interface to the Model, allowing the Model to focus on maintaining system state without having to concern itself with the details (i.e., the queries) needed to update the data source.
DataAccess Classes - In C#, these are very simple classes that model your elemental data objects. When you select something using a LINQ query, you will usually create an IEnumerable<T> or List<T> where T is one of your data objects. An example of a data object would be:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
The big advantage of a design like this is that it really separates your concerns. Everything has a specialized job, and it's (usually) pretty easy to know what kind of thing goes where.
The disadvantage is that it may be overkill for small projects. You end up creating a lot of infrastructure for public interfaces that basically pass a single wish through several layers. So, you might end up with a scenario like this: [user clicks Submit, ViewModel tells Model to AddNewPerson, Model tells Gateway to InsertPerson] instead of a scenario like this [user clicks Submit, ViewModel adds new record to the database directly].
Hope that helps.
I would add another layer, essentially what you want is a data factory. You want to create a set of classes that will CRUD to the database for you and return clean POCO objects to the ViewModel.
A good example to look at would the Nerd Dinner book. It covers MVC not MVVM but the patterns are very similar and the way they access data in that solution would be good starting point.
Hope this helps.
Data access should not be in the view model, as this is supposed to be a view specific (possibly simplified) representation of the domain model.
Use a mapper of some sort to map your view model (the VM in MVVM) to your model (the first M). New objects in your model can be created using the factory pattern. Once created, you can store them in a database using the repository pattern. The repositories would then represent your data access layer. In your repository you could use an O/R mapper like NHibernate or Entity Framework.
EDIT:
I see that GraemeF suggests putting the data access code in the model. This is a NOT a good approach, as this would force you to update your domain model if you were to move from e.g. SQL Server to Oracle or XML files. The domain objects should not have to worry about how they are persisted. The repository pattern isolates the domain from its persistence.
MVVM stands for Model, View, and ViewModel. The piece you are missing is the Model, which is where your data access code lives.
The ViewModel takes the Model and presents it to the View for display, so typically you would have something like this:
class PersonModel : IPerson
{
// data access stuff goes in here
public string Name { get; set; }
}
class PersonViewModel
{
IPerson _person;
public PersonViewModel(IPerson person)
{
_person = person;
}
public Name
{
get { return _person.Name; }
set { _person.Name = value; }
}
}
The PersonView would then bind to the properties of the PersonViewModel rather than directly to the model itself. In many cases you might already have a data access layer that knows nothing about MVVM (and nor should it) but you can still build ViewModels to present it to the view.
Your ViewModel should be a thin layer that just services the view. My rule of thumb: if it has to do with the presentation of the UI, then it belongs in the ViewModel, otherwise it should be in the Model.
The WPF Application Framework (WAF) contains a sample application that shows how the Model-View-ViewModel (MVVM) pattern might be used in combination with the Entity Framework.
I'm writing an application (Silverlight and WPF) using the MVVM pattern and the Prism framework. In my application I have a grid that contains a list of customers. Under that, I various views that present customer details. All of the information is fed from a WCF service that provides data from queries as well as callbacks which fire events when the data has been received. The detail information is updated when the selected item in the grid is changed. There is also a filtering view that controls the date range for the detailed information.
I also need to implement a similar set of views, but for a specific customer. The information presented is the same, so obviously it would be best to reuse the same view and model classes.
My initial thought was to build a separate intermediate service that sat between the models and the WCF service for both scenarios. I would then bind the models to the specific service by registering instances by name.
Unfortunately, this would mean that I would have to instantiate a lot of the classes myself instead of relying on dependency injection which I would prefer.
So, for all the MVVM gurus out there, how should the views, models, and services be structured to best use the features of the Prism framework and promote code-reuse?
Many thanks!
==== Edit: added following text and example ====
Here is a simple example that I hope explains what I'm trying to accomplish.
public class CustomerViewModel : ICustomerViewModel
{
public ICustomerView View { get; private set; }
private readonly ICustomerService customerService { get; set; }
private Customer customer;
public CustomerViewModel(ICustomerView view, ICustomerService service, IEventAggregator eventAggregator)
{
customerService = service;
eventAggregator.GetEvent<SelectedCustomerChangedEvent>().Subscribe(CustomerChanged);
eventAggregator.GetEvent<CustomerInfoUpdatedEvent>().Subscribe(CustomerUpdated);
View = view;
View.Model = this;
}
public string Name
{
get
{
return customer.Name;
}
}
public string Email
{
get
{
return customer.Email;
}
}
public void CustomerChanged(int customerId)
{
customerService.RequestCustomerInfo(customerId);
}
public void CustomerUpdated(Customer customer)
{
this.customer = customer;
}
}
This customer view model based on the current design where the customers are in a grid. Selecting a customer fires the SelectedCustomerChangedEvent which will cause the view model to request information.
It is fed from an underlying WCF service that is using a callback mechanism to provide data (the data can take a long time to retrieve / calculate so a simple WCF call won't work). This works just fine. The problem is that I want to reuse this same view and model in a different area of the application that displays information about a specific customer instead of the current selected customer.
My initial thought was to create an intermediate service that handled the SelectedCustomerChangedEvent for the list and a similar event when the customer-specific view is opened. It would then provide data to the model through the same CustomerInfoUpdatedEvent.
The problem is that since I would now have 2 services that implement the same interface, I would need to name them and then have the view model somehow know which one to retrieve from the container.
I know I've probably made a design error. The good news is that I have time to fix it, but I'm not sure how to fix it.
If the Customer class is the same for all customers (including your specific customer), then use a single service, the same views, and the same model.
Can you tell us why this would not work?
Hmm... there is a lot of information here, but I will take a stab at this.
There's really no reason to complicate this as much as you are trying. It feels like you are receiving callback events from your WCF service... am I right? If so, you want to update the UI if the incoming WCF callback pertains to a customer that the user is viewing. I'll work from these assumptions... let me know if I misunderstand.
I think you have almost what you need. I think all you need to do is the following:
From your WCF callback handler, raise an event with the EventAggregator passing the new customer information along with the customer ID.
From any ViewModel's constructor, subscribe to the CustomerUpdated event and add a filter for the customer ID you are looking at in your view model. You are missing this, but it's critical, otherwise you will get a firehose of events that don't pertain necessarily to your instantiated ViewModel. There is a sample of this technique in this quickstart: http://msdn.microsoft.com/en-us/library/dd458918.aspx
Again, this is my best effort at understanding what you are trying to accomplish. Let us know if it's not.