Composite ViewModels in a WPF application - c#

I came accross the following situation:
I have 2 view models and a single view which contains 2 user controls on which the view models will be bound to. The first VM is a Search functionality which returns a list of Persons, and the second VM is a more detailed description of each person.
I want to do the following:
public CompositeVM
{
public SearchVM SearchViewModel{get;set;}
public DescriptionVM DescriptionViewModel{get;set;}
}
As I have said, the search view model also incorporates a list of found persons, so I wish that when I select a person the DescriptionVM to be updated accordingly.
How can I achieve this type of communication between VMs? Should I set a SelectedPerson property on the SearchVM and pass it to the DescriptionVM when the selected list item changes (pretty high coupling to me)? Is there a more simple approach to this matter?

It's possible for CompositeVM to subscribe to SearchViewModel's PropertyChanged event and set DescriptionViewModel.SetSelectedPerson(SearchViewModel.SelectedPerson).
There is no coupling here between SearchVM and DescriptionVM, since they're not aware of each other. CompositeVM knows them both, and is also who's in charge of their interaction.

Alternatively you can use the Mediator-Observer pattern, such as the Messenger class in MVVM Light:
http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx

Related

What's the point of having models in WPF?

So far I have yet to see the value of having models in WPF. All my ViewModels, by convention, have an associated Model. Each of these Models is a virtual clone of the their respective ViewModel. Both the ViewModel and Model classes implement INotifyPropertyChanged and the ViewModel just delegates everything to the Model anyway.
Why bother having Models then? Why can't I just move my Model logic up into the ViewModel and call it a day?
It seems rather redundant (that is, not DRY) to have MVVM, and just use VVM by default unless some special edge case demands a Model.
If using explicit model classes better supports unit testing, for example, or some other best practice, I can see the value.
The model is just the low level application data.
The view model is more specific.
It's like a window tapping into the data tailored for the view.
It also augments the model with details needed for the view. A good example is pagination.
A model can have more than one view model. These view models would offer different aspects of the data.
You can create a mashup of different data sources. A view model cleanly façades the models involved.
That means there is no 1:1 relationship between models and view models.
So, if you just display the low level data without a lot of additional logic, features, summaries, aggregations, filters, etc. you can do away with view models and just use the model directly. This seems to be the case with your project.
The model can be auto-generated (Entity Framework), or it might not be a specific class at all (think of a DataTable).
I assume that if you say "I don't use a model", you do in fact use a model, you just don't call it that way.
First of all, even in MVVM you can expose your Model directly in the VM and bind through it to the Model. {Binding MyModel.MyModelsProperty} where DataContext = ViewModel that way you don't have to necessarily wrap everything unless that is just your style to do so.
The ViewModel and Model have different responsibilities. For example, consider designing a file explorer with a tree view of folders. Each node in the tree view is a Directory/Folder. The directories are the models and they have properties related to the file system. The ViewModel may wrap or expose these properties for the TreeView nodes to display (For example the Name of the directory), but it also adds additional information such as "IsEditing" and "IsExpanded" to determine the state that the node is in.
You're just talking about one pattern in MVVM, actually there are more.
In Stateful viewmodel you don't actually delegate things to Models, Viewmodel itself maintains its state, so as you said in this pattern you can almost ignore the model as you can have state in VM itself.
To create isolation between business logic and presentation, data
should be removed from the view. The stateful view model pattern moves
data into the view model using XAML data binding. This allows the view
model to be tested without constructing a view, and it allows the view
to change with minimal impact on the business logic.
In Stateless viewmodel you delegate the calls to Model, which is what you're probably referring to.
Note that you don't necessarily implement INotifyPropertyChanged in Model. Just implementing it in VM is fine as long as you don't change the properties directly in Model.
So why do we need VM and Model? VM is for supporting view like providing Commands, etc and Model is just to hold the piece of data abstract the same.
If you think of it as an abstraction, let's say you need to build a screen to display a list of Employees and make a Selection, Search or Filter. Then we break it up in components. You will require:
An Employee class (Model)
An EmployeeManagementViewModel to prepare and present your list of Employees and manage state changes for your View (e.g. can contain a SelectedEmployee, Filter Search text, etc) to be used by your EmployeeManagementView
A list of Employees (Which will live in your EmployeeManagementViewModel)
Most likely you will already have an Employee class. If that's the case then you just need to expose that model in your EmployeeManagementViewModel as an ObservableCollection of Employees.
In case you don't already have an Employee class you may decide to create an EmployeeViewModel and add your Employee properties there like FirstName, LastName, etc.
Technically this will work but conceptually it bothers me because an EmployeeViewModel is not an Employee (it contains an employee). If you're abstracting reality then, the blueprint of an Employee should not include properties or methods to be used by a View. To me Employee should be a POCO which could implement INotifyPropertyChanged and nothing more than that. You're separating View state from the Model itself. Having an Employee POCO makes it easier to UnitTest, create mock employees, map it to a database table through an ORM, etc.
As the name implies the ViewModel is the model for your View and the Model is the model for your business domain
Anyway that's how I see it. When I started doing MVVM work I had that same question but over the years seems like it makes sense.
In general, my Models end up being a Data Access Layer, be it through Entity Framework, a WCF proxy, or some other class.
Depending on concurrency issues, the class could be static or instanced. If you can separate the behavior enough, you could "split" the DAL classes into a separate model for each view model, but duplicate code could become a problem.
Wikipedia: MVVM
Model: as in the classic MVC pattern, the model refers to either (a) a domain model which represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).
Your ViewModel isn't a substitute for your domain Model. It acts as an intermidiate between your view and the model, including commands, binding collections to your view, validation, etc.
Your domain model should also be reusable across ViewModels. If you implement it all in the VM you will end up abusing the DRY principle by sharing specific VM logic across multiple VMs.
In my experience when you just use Domain models as the ViewModel (as a property of the VM) you end up with a lot of Keys that require you to either go get the text value and store somewhere else or you end up adding the property to the VM anyway. Your view typically has more info than just one single domain model (e.g. related objects, display values, text status values etc..), something that the Domain model has no need for and would ultimately weigh it down. The view model is dedicated to the needs of the view, it keeps coding the View simple and non-complex.

MVVM: How to pass ObservableCollection to other viewmodels?

I'm designing an MVVM framework and I need to know if my understanding of MVVM pattern is correct or not. My question is simple. How should I pass the ObservableCollection object between the VieModels? or shouldn't I?
I have a CustomerViewModel which has an ObservableCollection to hold a list of customers. I also have an InsertCustomerViewModel which is responsible for insertng new customer models in to that ObservableCollection. in the InsertCustomerViewModel I have a method called Insert() which is called everytime the user clicks on the Insert button.
What I'm doing so far is passing the ObsertvableCollection from CustomerViewModel to the constructor of the InsertCustmerViewModel and then in the Insert method I have Items.Add(newCustomer).
Is my implementation correct? or is there any better way to do the job?
I would pass the CustomerViewModel to the InsertCustomerViewModel and expose a property for the collection. That way you can use and modify that collection from InsertCustomerViewModel directly.
From my point of view InsertCustomerViewModel does not make any sense here. When user insert a customer it should only add in CustomerCollection Class which should be a Model for multiple ViewModels.
I think the idea should be share the same CustomerCollection model among the two ViewModels via some common instance.

WPF - MVVM Viewmodel setup

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.

Is this correct way to implement MVVM?

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.

MVVM where to put Data Access Layer?

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.

Categories

Resources