I have a parent viewmodel which has list of person which is the domain object
public class ParentViewModel
{
public List<Person> Persons{get;set;}
}
I have another viewmodels in different window which uses the person collection.
I am communicating changes by raising Prism Events. The code is bloated with if any changes are in single person or the list, the child viewmodels in different window have to bunch of stuffs.
Is there a way in WPF/.NET to track changes on person which is domain object so that I can raise prism events without going through specific code in which the person (domain object) are changed.
If i understood your need correctly then i would offer 2 options:
Use ObservableCollection instead of a List
That will make sure that whoever bind to this list is notified in case of change in the list, a good example you can read in the answer for this question.
But actually i would prefer a cleaner approach which is possible with MVVM-Light so i assume it is possible in Prism as well, and that is - Adding identifier to each person (better is when you can use one of the field as identifier). and then publish a message with the same Identifier so the listeners will subscribe to changes of a person Object with a specific Id.
in other words:
A--> Listener are subscribing to a PersonChangedMessage with a specific person identifier.
B--> Person object change - its publish a message with its identifier.
C--> Only listeners with the correspond id get notified.
A good example you can see here Subscription Filtering
Related
I am building a WPF project and have implemented Prism.
I have a DAL where I have a library that handles the connection to the DataBase called Persistence, this library uses EntityFramework and has some Entities.
Furthermore I have some DomainModels, now - what do I do with the given scenario:
I have 2 ViewModels that both have a reference of the ActiveUser (the one that is currently logged in) as an IUser type DomainModel, that we get via a service called IUserService.
Lets say that this IUser has a property called Funds, if ViewModel1 changes IUser - how do i Notify ViewModel2 that it there are changes to IUser and Funds should be updated so the View is displaying the correct data.
Do i Implement INotifyPropertyChanged in my Models as well as my ViewModels, and then each ViewModel should then listen to the PropertyChanged event, and depending on the property that has changed, update accordingly? (I find this kind of ugly though)
Do I use the EventAggregator and publish/subscribe the events, publishing from my DomainModels(?) and subscribing on my ViewModels?
Do I implement something like a PropertyObserver<TPropertySource> : IWeakEventListener class?
Thanks
1. and 2. should both do the job, I'd go for 2. if there are few events like this, otherwise 1. because it keeps everything on a more local scale.
And btw, if you go for 1., go for 3. also. The PropertyObserver makes handling INotifyPropertyChanged a lot simpler, because you do not have to consider the lifetime of involved objects (not to speak of the nicer syntax).
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.
As the title states... how can I find a different viewmodel....
My first guess would be to search for the usercontrol it's bying used by and go through that... but it seems a lot of work for something that must be easy to find....
You can Make use of Messenger Class.
When you want to execute the method present in one Viewmodel in Other ViewModel.. You can simply send a message to the ViewModel(which holds the event you want to execute) from the ViewModel(From which you want to acess) and can execute that event.
Register the Message in the Constructor of class in which the event is declared.
Send the Message from the viewmodel(in which you want to access) at the point you want to use that event.
You probably need to use a general messaging mechanism that allows you to communicate between VM's - see MVVM Light for example
How do the two view models relate? Is one a parent of the other? In this best case scenario, you can just expose an event or delegate in one that the other subscribes to.
Similarly, if they have a common parent, this could be done in the parent view model.
If there is no relation, how about putting all common functionality into a base view model class. If the event or delegate is exposed in the base view model, then every view model that extends it can subscribe to it internally.
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.
There are lots of great examples around on MVVM but I'm still confused.
Lets say you have a CustomerModel and a CustomerViewModel. It seems there would be a Name property on the CustomerModel and one on the CustomerViewModel. The setter on the CustomerViewModel will set the CustomerModel Name property and then call the OnPropertyChanged(PropName) so that the UI will update. Is this really right? Seems like the getter/setters will be defined twice. If you have a model with 50 properties then thats going to get real tedious.
Also, lets say I set a Qty property. The ViewModel updates the Model. The Model updates its Value property based on the new Qty. How does the ViewModel get notified that the Model property changed?
Your ViewModel doesn't have to encapsulate the Model that strictly. In your scenario, the CustomerViewModel might have a Customer property, which in the end means your View binds to the Model properties... it just does so through the ViewModel. That's perfectly legitimate. That said, however, there's often a benefit to encapsulating this. Your business model may not include change notification. You may not want the user interaction to modify the business model until the user clicks an OK button. Your business model may through exceptions for bad input, while you want to use another form of validation. I'm sure you can think of other things. In fact, I'd guess that most of the time you're going to want the encapsulation, so it's not really "tedious" in the sense of just writing a lot of pointless relay methods.
In the customer example that you give, the CustomerModel contains all the information that is stored by your database (or other backend). The CustomerViewModel contains similar information if it's going to be shown on the UI (Name etc., potentially 50 other properties if you have a large class) but as uses the INotifyPropertyChanged interface to show them as properties that the View (i.e. the XAML) can bind to.
e.g.
public int Name
{
get
{
return this.name;
}
set
{
if (this.name!= value)
{
this.name= value;
this.OnPropertyChanged("Name");
}
}
}
The ViewModel also contains other bits of UI state - Visibility flags, current Tab index, more complex bits of text built out of data in several fields, ObservableCollection<> of child items, etc. All are there to be bound to the XAML.
I have seen the ViewModel created from the Model as a one-time, one-way process, e.g. with a constructor:
CustomerViewModel viewModel = new CustomerViewModel(customer);
or as an extension method
CustomerViewModel viewModel = customer.ToViewModel();
I haven't seen any provision for updating a ViewModel for changes to the Model - the point of the ViewModel is that it's isolated from the model. It keeps a separate copy of the data. It does not propagate changes back to the model, not until you press a "save" button. So if you cancel instead, nothing in the model has changed and there's nothing to undo.
You may be trying too hard to keep the ViewModel up to date with the Model - most cases like save or load you can just throw away the current ViewModel and make a new one from the current state of the model. Do you need to keep the ViewModel's UI state and change the data in it? It's not a common requirement but it could be done with a method or two called when the save or load happens.
So there's also the assumption that this wire-up logic happens somewhere. This is why most patterns that involve views also involve controllers that are responsible for acting on commands (e.g. show a customer, save a customer) and setting up new UI state afterwards.
Exactly how this is done, will depend in part on your business model as wekempf has already stated.
Depending on how your displaying Customer info in your UI, you might have an ObservableCollection of Customer(your model) types in your ViewModel. If, for example, you're displaying a master/detail scenario, where you might have a list of customers and show details below when a particular customer is selected.