I am making a program that does database navigation with relation tables.
For example you have a person class and a car class, and when adding a new person you need to also add which car they drive.
So you have a browse button which opens the same window you used for people, and creates another instance of that view model. Keep in mind that my viewmodel is generic, so it works on all types.
What I need is some pattern that communicates between those two viewmodels so that it can, in a way, return a selected car if you know what i mean.
Any suggestions?
I cant comment, so here it goes.
So you have 2 instances of your ViewModel object and you need to know what type each represents to convert stored in ViewModel generic object to that type.
Try store Type in ViewModel so you can Convert.ChangeType(object, Type) in your ViewModel any object to specific type.
What you are looking for is referred to as the Mediator Pattern.
https://en.wikipedia.org/wiki/Mediator_pattern
In Prism and various MVVM libraries it is sometimes referred to as the "EventAggregator". There are various versions you can implement, but the basic idea is to inject in the mediator and the VMs subscribe or publish to a known event. The event can pass any data you need with it.
This ensures your VMs do not become coupled and allows them to communicate and is scalable as you can just keep adding new events to the event aggregator and VMs can pub/sub as they need to.
Related
My Desktop WPF application has a repository (of type Person) which resides in the Model layer, and is called by a ViewModel which has a PersonList property which is databound to a DataGrid.
When I open my Application, the list is shown by default. During initialization, the following code applies:
public class PersonScreenViewModel : ViewModelBase
{
PersonRepository _person_repository;
public ObservableCollection<Person> PersonList { get; set; }
public PersonScreenViewModel() {
_repositorio_pacientes = new RepositorioPacientes();
PersonList = new ObservableCollection<Person>(_person_repository.GetAll());
}
// ... ///
}
My doubts are based on some difficulty to understand how to implement "Save / Update" method(s).
Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ]". So, the most logical thing would be to databind the repository itself to the DataGrid. That could be done if I created a class which inherit from ObservableCollection and implements repository logic. Currently, what I do is take a copy of the repository items, using _repo.GetAll(), and work in that copy, having to commit back after my changes are done.
Specifically, my workflow involves selecting a row in the DataGrid, changing some properties of the selected object, and commiting these changes, expecting that the same object is persisted with the new property values.
Usually, if you take an object in a collection and modify it, you don't need to "update" anything, since you already changed the object itself.
The question is: "How can I data bind my view to the repository itself? Should the repo inherit from ObservableCollection? How is it supposed to be done? Is some part of my reasoning flawed?"
It is important to say that my application is not data-oriented, the Person class is very basic (POCO marked as [Serializable], with a few properties), and my repository uses plain XML serialization and the filesystem structure.
Thanks for reading!
"Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ".
What you originally have is sort of correct. First of all ObservableCollection works perfectly with the View because every add/update/delete will automatically propagate back to the user interface. If you implemented it with repository, then you would have to go call the database reload the control bound to your repository
"How can I data bind my view to the repository itself? Should the repo
inherit from ObservableCollection? How is it supposed to be done? Is
some part of my reasoning flawed?"
You don't want to data bind the Repository to the DataGrid itself, because you lose caching and every time the user loads the user control you always have a trip back to your database.
You don't want to inherit a repository to an ObservableCollection, ObservableCollection has more overhead vs simple IEnumerable given you already database returned you a collection already.
You always don't want ObservableCollection as your collection for your data because it is expensive. A simple enumerable of data is enough depending on your scenario (Read-only data).
In my personal opinion, what you are currently doing is correct... it is generally good practice to have some separation between the various layers of your application; Models, View Models, Views and DataAccess (sometimes combined into Models). Having said that, it really depends on your application... it might not be worth doing this on small applications as it adds a lot of code and time to set up and maintain.
However, the main reasons for providing this separation (called separation of concerns) is to enable unit tests to be able to test the individual layers without concerning the other layers. For example, if we wanted to write unit tests for our view models, we wouldn't want to test their functionality on the actual data objects in the database. If we have this separation (through the use of interfaces) then we can simply mock up data objects to use during these tests.
Another reason, although less common in practice, is to enable whole layers to be 'swapped out' without affecting the code in the other layers. Examples of this would include changing the database used in the application, or maybe changing the views from a desktop application into web pages in a web application. If we have separate layers, then these changes won't affect the other layers.
So to answer your question directly, I wouldn't bind your views to the repositories at all... keep your current separation. After all, how long does it take to copy a collection sourced from the database into a view collection property?
UPDATE >>>
I'm not sure that I fully understand the question in your comment. I'm guessing that you are binding your PersonList property in your view model to the DataGrid.ItemsSource property to display the data. Any changes made in the DataGrid should affect the items in your PersonList. If you were to add a 'Save' Button, then you could update the database in that click or command handler.
If you were enquiring how to find out which elements had been changed, there are several methods for accomplishing this. There is a good tip in the How to get only modified Items from WPF Data Grid post here, but I prefer to use a duplicate collection and just compare them to find the changed elements (you'd need to implement the Equals method for this to work).
Please let me know if that does not answer your question.
I have a WPF application which follows the MVVM pattern. The application defines two views and view models so far:
LoginView(Model)
ProjectsView(Model)
Both view models need to access several properties from other view models.
Example:
LoginViewModel has a property ProjectList. ProjectsViewModel needs to access this property as well.
This is only a simple example. Later there will be several UserControls which all need to interact with each other.
Would it be a better idea to create one huge view model which all UserControls (views) set as their DataContext? If not, how can all the different view models interact with each other?
Remark:
This question is closely related to this one but with a different approach.
You should definitely not make a huge "main view model" -- this is an anti-pattern not dissimilar to a god object.
The key idea here is that your viewmodels do not need to access several properties from other view models; rather, all of the viewmodels need to access specific pieces of information.
Right now you are most likely injecting this information into each viewmodel at the time of instantiation. Instead of doing this, provide each viewmodel with a reference to a service -- an application module that exposes this information through properties and/or methods. The information can be exposed in the form of scalar values if it's extremely simple in nature, or in the form of models if it's anything more complicated than that.
Schematically this would look like
/--------------\
| ViewModelA |
| | <=======\
| | |
\--------------/ | <--- information is pulled /================\
+=========[model]===[model]====== | Service |
/--------------\ | \================/
| ViewModelB | |
| | <=======/
| |
\--------------/
The service should be injected into the viewmodels upon construction (either manually or by the DI container if you are using one). Each viewmodel should only require a reference to the service and enough information to tell to the service which model it's interested in; it will then request that model from the service and populate its "interesting" properties based on that.
This way of doing things is more involved than simply constructing a viewmodel object and setting its properties externally, but it will allow your application to grow in complexity without becoming unmanageable.
For example, if there are lots of views that bind on different viewmodels and these viewmodels depend in complex ways on a number of models, a sane manner to work would be:
A view/viewmodel pair is constructed
The viewmodel requests any models it needs to know about from the service; it subscribes to an event that the service exposes to let subscribers know that a model has changed
Changes are performed to the models through databound controls
The view invokes a "save" command on the viewmodel
In response to that, the viewmodel invokes a "save this model" method on the service
The service persists the information and publishes a "model changed" event (see step 2)
Other viewmodels interested in the same model know that the model has changed and can query the service for its new state
This is possible if everything is routed through the service. Imagine what it would take to keep everything synchronized otherwise -- the only way to cope would be to put all the information into a giant viewmodel and reference that from everything else. Ugly.
Usually I do one of 4 things:
Make my ViewModels reference each other, and pass the property around. For example, LoginViewModel might set ProjectsViewModel.ProjectList on successful login. How you implement this depends on how your ViewModels are related to each other, and where logical points of connection would be.
Make an ApplicationViewModel which manages things like which page is current, and application-wide objects like the current user or current project list. It would handle transferring shared data to the ViewModels that needs it.
Use some kind of Event system to broadcast a message anytime an application-wide property changes, and have any ViewModel that's interested subscribe to receive those messages. The message typically contains the new object as well, so anyone subscribed to receive that message type has access to the new object. (I have a brief summary of Event Systems in my blog article Communication between ViewModels with MVVM if you're interested)
Depending on if any of the other options work better, I may consider creating a singleton to hold application-wide data instead. For example, if the User is set on Login and is accessed from many of my ViewModels, I may create a singleton to set the user on first login, and then all my ViewModels can access it.
The one thing I would not do is make one big ViewModel holding all available data. ViewModels should only contain the data specific to it.
If you are using some sort of dependency injection tooling, you could inject a class that provides those values, for example, an IProjectService, that can return the list of projects on each of those view models.
The idea of one giant view model does not sound appealing, nor does strong coupling between view models by accessing each other's public properties. And if you want interaction between the view models, like when a project gets added, use a publish / subscribe model for each of the events you expect to occur.
Your Model should contain things like a project list, or give you the ability to access it. The ViewModel is simply meant to be a layer between the Model and View, giving you the chance to bring different Model objects together and mold them into a shape which the View can readily display and to handle commands from the View (modifying the Model in response).
Create one Base View Model keep all common Properties in that, Create singleton to BaseViewModel and add that singleton property in all View Models. All Viewmodels will get synced at one time.
Okay, so I am working with Microsoft Prism in WPF using a MVVMC(or MVCVM) pattern.
In my ChatModule I have a series of Views, ViewModels, and one Controller.
For the Views I have
ChatAreaView - Displays the chat messages that come in to be read. This is hosted inside of a TabControl region so that I can have chat windows between the user and other users, or maybe file transfer windows, etc.
UserAreaView - This is a list of the users. Right clicking has context menu to interact with them... like sending a file or whispering.
MessageAreaView - This is where the user types in messages to be sent to all of the others.
For each view, I have a corresponding ViewModel. ChatAreaViewModel, UserAreaViewModel and MessageAreaViewModel. These ViewModels essentially only contain properties.
For example, the UserAreaViewModel defines a struct of type User which is essentially just a Name. Actually this is defined outside of the class, but still... it uses it. It has an ObservableCollection to store a list of all the Users who are currently connected. It also has ICommand properties defined to interact with the user. Right now I have SendFile, Whisper and Nudge... with intent on adding more in the future.
The Controller creates these views and ViewModels, and marriages them. It news them up, assigns the ViewModel as the corresponding View's DataContext, and sets all the initial properties of the ViewModel. Over the lifetime of the module, it will react to user interaction and execute DelegateCommands that it has assigned to each of the ViewModel's ICommand properties. These will further alter the state of the properties in a ViewModel.
I am using the actual types of Views and ViewModels, instead of interfaces, like such.
#region Views
ChatAreaView viewChatArea;
UserListView viewUserArea;
MessageView viewMessageArea;
LoginPromptView viewLoginPrompt;
#endregion
#region ViewModels
ChatAreaViewModel viewModelChatArea;
UserAreaViewModel viewModelUserArea;
MessageAreaViewModel viewModelMessageArea;
LoginPromptViewModel viewModelLoginPrompt;
#endregion
Would things be a lot more neat, less coupled if I defined interfaces for the Views and ViewModels, and operated on these interfaces within the controller instead of the concrete implementations? Could I then just register them with my Container in the Module class(which is essentially the root of each Module)?
What do I have to gain from doing this? How would I implement an interface for each view to distinguish them from the others? They don't really do ANYTHING except have XAML... and teh ViewModel's don't really do anything either except have certain properties. And those properties might be subject to change. On the UserAreaViewModel for instance, I will definitely want to add more commands so a user can interact with another user in different ways.
Can somebody help me out here? In my mind I'm thinking I should be abstracting this stuff, but I don't really know a logical way I should be going about it, or even if it's a wise idea to do so. What do I have to gain?
Thank you for your time. The below image is an example of what I'm working on. Ignore the Add new Item button and the styling of everything... that's not what I'm working on right now.
loosely coupled - can replace an entire class with altogether different implementation in future.
independent development.. can inject a dummy UI / view until final UI gets ready. two pieces can evolve at the same time (after having a common contract).
no need to add references to the modules (implementing the view). can use ConfigurationModuleCatalog to discover types from config file.
I am new to MVVM and now doing some MVVM refactorying work on a silverlight project, suppose it is a book shopping application.
The View is a book list, I bind the title of the books to the ViewModel. So I have a public string Title { get; set; } in ViewModel, also a public string Title { get; set; } in Model (am I right?)
Now I want put a event handler to update the book title, should I put the event handler in ViewModel or Model? and what is the Model used for?
In my opinion "Neither"... Add controller classes to the mix of MVVM instead.
The problem with putting controller code in view models is that is makes them harder to test independantly. In many ways I see this as just as bad as code behind.
It seems to me that everyone assumes MVVM has no controllers as they left out the C. MVVM is really a variation of MVC "that just adds ViewModels".
Maybe it should have been called MVCVM instead?
ViewModels are only there to offload the "GUI" code from the view and to contain any data for binding. ViewModels should not do any processing. A good test is that your ViewModel is testable via automated unit tests and has no dependencies on data sources etc. They should have no idea where the data is actually coming from (or who is displaying it).
Although it can be overlooked/avoided, a Controller should be responsible for deciding what data model to display and in which views. The ViewModel is a bridge between Models (the M in MVVM) and Views. This allows simpler "separated" XAML authoring.
The pattern we are using successfully on all recent projects is to register controllers only, in modules, and initialise them at startup. The controllers are very light/slim and the only thing that needs to hang around for the life of the app listening for, or sending, messages. In their initialise methods they then register anything they need to own (views and viewmodels etc). This lightweight logic-only-in-memory pattern makes for slimmer apps too (e.g. better for WP7).
The basic rules we follow are:
Controllers make decisions based on events
Controllers fetch data and place it in appropriate View Model properties
Controllers set ICommand properties of View Models to intercept
events
Controllers make views appear (if not implied elsewhere)
View Models are "dumb". They hold data for binding and nothing else
Views know they display a certain shape of data, but have no idea
where it comes from
The last two points are the ones you should never break or separation of concerns goes out the window.
In simplest terms, the Model is the 'real' underlying data model - containing all the info for the booklist that might be needed by the application, able to get and set data from your database.
The ViewModel is an object that exists primarily to provide data binding for your View. It might be a subset of the Model, or it might combine properties from multiple Models into a single object. It should contain the necessary and sufficient properties to allow the View to do its job.
If the event handler relates to the View, then it belongs in the ViewModel. You might try using the Command Pattern (see Custom WPF command pattern example) if it fits your purpose.
I am writing a fairly large scale WPF desktop application using the MVVM pattern. I have been stuck for a while on getting my common properties to update in a View other than the one that updated it.
I have a RibbonWindow MainView that contains a ContentControl that displays the remaining Views one at a time dependant on the user's selection. I have a BaseViewModel class that all the ViewModels extend. Among other things, this class exposes the INotifyPropertyChanged interface and contains a static property of type CommonDataStore. This class also implements the INotifyPropertyChanged interface and contains the properties that are to be available to every ViewModel.
Now, although I can access and successfully update the CommonDataStore properties from any ViewModel, the problem is that the WPF Framework will only notify properties that have changed in the current View. Therefore, although the common values have been updated in other ViewModels, their associated Views do not get updated.
One example from my application is the login screen: As the user logs in, my LogInView updates with the new information (ie. full name) from the database, but the user details in the MainView do not.
After reading a few other posts, I also tried implementing the CommonDataStore class as a Singleton, but that didn't help. I could also just pass a reference to this common data object to the constructor of each ViewModel from the MainViewModel, but I'm not sure if this is the right way to go.
I have also discovered that in WPF, static properties are treated a bit like constant values. It seems that they just read the value once.
So anyway it's clear, my attempts have all failed. I was wondering what the standard way of doing this was? In particular, I need to be able to bind to the common properties and have all of my ViewModels and Views update when any common value is changed. Any help would be greatly appreciated. Many thanks in advance.
Edit >> Really? No one uses application wide variables in an MVVM WPF application?
I have now removed the static part of the Common property declaration and am simply passing a copy into each ViewModel individually. This seems to work, but I'd really like to know how others approach this situation. Please answer by simply letting me know how you organise this application wide data.
I have done something similar to what you describe last. I have class called SecurityContext that holds some of the application-wide data. One instance is created when the application starts up and then that instance is passed into the constructors of all the ViewModels through dependency-injection. I have a base class for ViewModels which exposes that object through a regular instance property (implementing INotifyPropertyChanged).
Have you looked into implementing the Observer Pattern? We have done so with IObservable and IObserver. This describes the "IObservable/IObserver Development Model" as follows:
The IObservable/IObserver development model provides an alternative to using input and output adapters as the producer and consumer of event sources and sinks. This model is based on the IObservable/IObserver design pattern in which an observer is any object that wishes to be notified when the state of another object changes, and an observable is any object whose state may be of interest, and in whom another object may register an interest. For example, in a publication-subscription application, the observable is the publisher, and the observer is the subscriber object. For more information, see Exploring the Observer Design Pattern on MSDN.