WPF MVVM OnPropertyChanged Two ViewModels Communication - wpf

I have a WPF app that uses a business object called Visit, it has a lot of child objects like patient, exam, and others. There are views and view models for editing these various child objects, so there is a view and view model for editing patient info and one set for exam info, etc. There is also a main window view model.
When I need to open a new Visit, I have a search screen that also has it's own view model. It needs to open new visit from the database and notify all the other views that the visit has changed.
I've looked into WeakEventManager, and also having one view model that is the parent of all the others, but I'm not sure what is the best way to proceed. I'd like to know what the relationship between the view models should be and how the open/search view model should tell all the other views to update. I have been calling OnPropertyChanged("propname") in my view models when a property is updated, but since the other views don't know about the open/search view model, they don't care if I say OnPropertyChanged("Visit")

Have a look at this post on SO that talks about the Messenger. In your case you case post the Visit object and have the ViewModel capture that for display.
If you have a very data centric views where the Model data is pretty much presented directly on the View without a lot of modification you can easily expose the Model as a property on the ViewModel and have the View bind to its properties.
This way when one View updates the Model the other View's will update automatically without having to listen for property change events on the Model
Edit:
To elaborate on my second point: You may or may not need this but if your Model also implements INotifyPropertyChanged then any changes to that model will be propagated to the View automatically.
If you need to have 2 Views with the Visit object then you can have the Visit property directly bound in XAML
public class ViewModel1 : ViewModelBase
{
public ViewModel1(IMessenger messenger)
{
messenger.Register<Visit>(this, (v) => CurrentVisit = v);
}
public Visit CurrentVisit
{
get { _visit; }
set { _visit = value; RaiseNotifyPropertyChange("CurrentVisit"); }
}
}
public class ViewModel2: ViewModelBase
{
public ViewModel2(IMessenger messenger)
{
messenger.Register<Visit>(this, (v) => CurrentVisit = v);
}
public Visit CurrentVisit
{
get { _visit; }
set { _visit = value; RaiseNotifyPropertyChange("CurrentVisit"); }
}
}
public class CurrentVisit : INotifyPropertyChanged
{ ... }
Like I said this is only applicable if you need the same Visit object shared amounst 2 or more ViewModels and if the View's mostly are data centric or in other words the data from the Model is being presented directly on the screen. This is to avoid duplicating the properties in the ViewModels and having to raise the property change event all the time.

use global variable. simply use a Property in your base ViewModel class whose set part set the global variable and get part return that variable value... for setting that global variable create a class in other common project and create a static public variable or property.

Related

How can I trigger some code to run in the view from the view model?

What is the best way for the view model to "ask" the view to do something, (e.g. manipulate on of the controls)? I don't think that the view model sending events violates MVVM as after all the INotifyPropertyChanged interface is an example of view models sending events to views.
I realize that having code behind in the view is not considered ideal from a MVVM perspective, so I could use an attached behavior to manipulate a particular control for example but the problem remains - how do I ask the attached behavior to do something from my view model?
I could have Boolean dependency property on my view with property changed event handler which runs the code I need to run. I could then bind this property to a property on my view model and then toggle the value of this property whenever I want to trigger the code to run. However this seems like a hack.
I could have an event on the view model and then explicitly attach this event to an event handler in the view in code but this seems anti MVVM - I should be able to achieve the connection using binding.
This must be a fairly common scenario, are there any standard solutions?
You could for example use an event aggregator or a messenger to send an event or message from the view model that the view handles in a loosely coupled way. Both the view and the view model know only about the event aggregator but they don't know anything about each other. Please refer to this blog post for more information about the concept.
Another common approach is to implement an interface in the view and inject the view model with this interface, e.g.:
public interface IDoSomething
{
void DoSomething();
}
public partial class Window1 : Window, IDoSomething
{
public Window1()
{
InitializeComponent();
DataContext = new ViewModel(this);
}
public void DoSomething()
{
//do something...
}
}
public class ViewModel
{
public ViewModel(IDoSomething doSomething)
{
//...
}
}
This doesn't break the MVVM pattern as the view model knows about and is dependant only on an interface.

WPF MVVM: an issue of organising ViewModels

what I think I face is a problem of design - one I assume has been solved many times by many people since it seems like it would be very common.
I'm using WPF with XAML and a simple MVVM approach, for the record.
My intention is to create a TreeView, using the MVVM design pattern in WPF.
I have a data model which contains two classes: Scene and Character. Each Scene contains many Characters.
I have created a CharacterViewModel, which is fairly simple (and works fine). Naturally this wraps around the existing Character class.
The Scene class is where I'm getting confused. As I understand it, the SceneViewModel should wrap around the Scene class, just as the CharacterViewModel did for the Character class. But the difference is that Scene contains a list of Characters and thus adds exta complications.
The two options seem to be as follows:
Option 1: Scene contains List of Character and so SceneViewModel also will have that as part of it.
Option 2: Scene contains List of CharacterViewModel and so SceneViewModel will also have that as part of it.
I'm not sure which one to go for to be honest. I suspect it's the second (and this tutorial seems to agree (example 6 is the heading for the section I'm referring to). The first option seems like it would make things really weird (and also why created the CharacterViewModel at all?) but the second seems strange because it seems to muddy the waters regarding what should be in the model part of the program and what should be in the view model part of the program.
I hope I've explained my problem and I also hope someone can offer some help.
Thanks.
Let me first address this statement:
...the SceneViewModel should wrap around the Scene class, just as the CharacterViewModel did for the Character class.
This isn't exactly true. View model should be created for each view. There may be a one-to-one with your model classes, but that isn't a strict part of the MVVM idea. One view may need to present data from multiple "root" model elements (model elements that don't have an explicit relationship like the parent-child relationship in your application), or you may need to have multiple views for a single model element. And to elaborate further, each view model should ideally be isolated from the view technology as much as possible (i.e. a single view model is sufficient to create a WinForms view or a WPF view or an HTML view, etc).
For example, you may have a view that displays data from your Scene class. That view may also display some data for each Character in your Scene. The user may be able to click on a Character and open a view just for that Character (e.g. a popup). In this case, there may be separate view models to represent the Character in the root view and the popup. I tend to name my view model classes according to the root of the view. For an application like yours, I would have something like SceneViewModel and SceneCharacterViewModel (or SceneViewModel_Character, or CharacterInSceneViewModel -- any of these names conveys that the class is for representing a Character in a view for a Scene). This would differentiate that view model from the popup view (which would be Character-centric and would be named something like CharacterViewModel (or even CharacterDialogViewModel or CharacterPopupViewModel or CharacterEditorViewModel).
Keeping collections in sync between the model and view model is annoying but often necessary. Not always necessary, mind you -- there will be cases in which you'll find there are no additional view-model features that you need to add to a model, so it's perfectly acceptable for the view to reference the model directly in this case.
An example of keeping a model collection and view model collection in sync: Suppose your root SceneView has a button for each Character. That button will display a popup for the Character. Suppose further that the Character popup doesn't have a similar button because then it would allow the popup to open another popup (etc). You may want to use an ICommand implementation so that you can just bind the button to the command. It's definitely not appropriate for the ICommand instance to be in the model (even though the command may call a public method on the model). The appropriate place for this would be in the view model for the Character in the Scene view (not the view model for the Character in the popup). For every Character in the model, you would need to create a view model that references the Character and stores additional view-model stuff (the ICommand object).
This means that, as Characters are added/removed from the Scene, you need to create view models specifically for those Characters within the Scene view model. I would typically do this:
At construction time (or whatever time the view model initially receives the model), create a view model for each child object. Put those view models into a public property with a type of something like ReadOnlyCollection<SceneCharacterViewModel>. Your view will bind to that collection.
As child objects are added to the model (either internally or through a public method on the model), the model should notify the view model in an appropriate way. Since the model shouldn't have a direct reference to the view model (not even through an interface -- a model should be completely functional even in a non-UI context, in which there is no view model), the most appropriate way is to use events. You can do this a couple of ways:
Expose events from your model like CharacterAdded, CharacterRemoved or even CharactersUpdated (the last of these would be able to communicate either an add or a remove using a single event)
ObservableCollections (or ReadOnlyObservableCollections), which are most commonly used in view models, can also be used in models, in which case all the events are already available to you. The downside to this is that processing the events off of these collection types isn't the easiest thing.
A third option that is totally different: If your view model or command instance is directly invoking a method like sceneModel.AddCharacter(newCharacterModel), then you can just update your view model immediately after this line without needing any events. I often find myself starting this way because it's simple, but I almost always end up using one of the previous two techniques instead, as those techniques allow the model to notify the view model even in cases where the update is happening internally (e.g., in response to a timed event or asynchronous operation that is controlled by the model).
All of that being said, here's what a "pure" MVVM architecture would look like for your application. Purity can come at the expense of simplicity, so sometimes it's better to take some shortcuts here and there. One common shortcut: In WPF, it's often easier just to put all of your child widget content in the ItemTemplate of the ItemsControl that is being used to diplay your children, rather than creating a separate UserControl for the children.
I guess from your explanation Scene is the Model and SceneViewModel would wrap additional view related functionality to your model in the view model. Same applies for CharacterViewModel.
Whatever your view needs to display you would have a SceneViewModel with a list of CharacterViewodel or vice versa. Or like mentioned your could build up a tree structure with your ViewModels.
My personal view of things is, it is important to stay in the ViewModel universe. So when your construct a view model you would inject your model via a service and build up your ViewModel and only have lists with view models. You would need to do some mapping but there are useful frameworks like automapper, etc already available. But remember there are no hard rules with MVVM.
I didn't understand your choices, However, I think you just need one View Model and it should contain an ObservableCollection of the Scenes. I name it SceneViewModel:
public class SceneViewModel
{
public SceneViewModel()
{
Scene m1 = new Scene() { Name = "Scene1", Characters = new ObservableCollection<Character>() { new Character() { Name="C1" }, new Character() { Name = "C2" } } };
Scene m2 = new Scene() { Name = "Scene2", Characters = new ObservableCollection<Character>() { new Character() { Name = "D1" }, new Character() { Name = "D2" } } };
Scene m3 = new Scene() { Name = "Scene3", Characters = new ObservableCollection<Character>() { new Character() { Name = "R1" }, new Character() { Name = "R2" } } };
_scenes = new ObservableCollection<Scene>() { m1, m2, m3 };
}
ObservableCollection<Scene> _scenes;
public ObservableCollection<Scene> Scenes { get { return _scenes; } set { _scenes = value; } }
}
Scene will have an ObservableCollection of Characters
public class Scene : INotifyPropertyChanged
{
ObservableCollection<Character> _characters;
public ObservableCollection<Character> Characters { get { return _characters; } set { _characters = value; RaisePropertyChanged("Characters"); } }
string _name;
public string Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } }
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propname)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
}
}
and at last, Character:
public class Character : INotifyPropertyChanged
{
string _name;
public string Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } }
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propname)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
}
}
View
<TreeView DataContext="{Binding}" ItemsSource="{Binding Scenes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Characters}">
<TextBlock Text="{Binding Path=Name}"></TextBlock>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"></TextBlock>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
public MainWindow()
{
InitializeComponent();
DataContext = new SceneViewModel();
}

What constitutes a viewmodel?

I'm still not totally sure what constitutes a view model. I have a class that I use to wrap my model and alter the data slightly, but I am not sure whether it constitutes a view model. What is necessary to be considered a view model? Is it merely not supposed to have direct dependencies on the view, so that the viewmodel does not know how the view uses its properties and the view does not know what is in the viewmodel? and when the view wants to update anything it just gives some abstract command that the viewmodel takes and uses to update the model?
As I understand it in MVVM, I'm supposed to use properties on the view that bind to properties on the viewmodel that bind to properties on the model.
and in the reverse direction, I'm supposed to use commands from the view to the viewmodel, which then can either uses Icommand to command the model, or can just call public functions in the model to make changes to it.
One confusing thing is that in the example of MVVM that I saw made it seem like in MVVM the view should have no code behind other than perhaps creating commands, but I don't see how I could do that in my current project. I'm making a custom control using lots of controls that are interacting on events.
how would I make one treeview expand on another treeview's expand without using events?
Often, View Models end up being very similar to your domain models. One of the main goals of having View Models is to separate the GUI development from the business logic. For example, let's say you have a "User" domain model that has an IsAdmin property which you don't want exposed to the View. You create a View Model called "UserViewModel" that still has the ID, Username, and Password (see example code below), but doesn't have an IsAdmin property. Another approach is to use the domain model inside your view model, see the "AlternateUserViewModel" class below. There are pros and cons to any View Model solution. Creating the UserViewModel class with properties means you are essentially duplicating the objects you created for the domain model, since often times your domain models will be very similar to your view models. With the AlternateUserViewModel approach, there's not clear separation between your business logic layer and your GUI layer because the view model still needs to "know" about the domain model. What approach you decide on really depends on the environment you're working in. For personal projects, I like using the 2nd approach because separating the business logic from the design layer isn't such a major concern that I wouldn't want to let the view model layer "see" the domain model layer, but for a large corporation where you have separate teams working on the design layer and the back-end, the first approach may be preferred.
public class User
{
public int ID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool IsAdmin { get; set; }
}
public class UserViewModel
{
public int ID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
public class AlternateUserViewModel
{
public User User { get; set; }
public User ToDomainModel()
{
if (User == null)
return null;
// if this is an existing user, retrieve it from the database so you're not overwriting the IsAdmin property
if (User.ID != default(int))
{
User existingUser = UserService.GetUserByID(User.ID);
existingUser.Username = User.Username;
existingUser.Password = User.Password;
// IsAdmin is not set because you don't want that property exposed in the View Model
return existingUser;
}
else
{
return new User
{
Username = User.Username,
Password = User.Password,
IsAdmin = false
};
}
}
}
You have a number of questions here (consider breaking it into multiple posts). I'll try to answer some.
I think of ViewModel as THE app, in other words, this is where most of the app's logic happens.
In other words, ViewModel receives an input of:
Commands from the View
Changes in bound properties from the View
Events from a background service (e.g. when data is received from the Web)
Other events from the system or from domain models
and generates an output of:
changing properties that the View would bind to (e.g. IsBusy that could cause the View to display the waiting indicator)
showing/hiding stuff in the View (indirectly, of course, for example using various bool Properties)
causing navigation to other Views (also indirectly, since it doesn't have direct access to NavigatonService available to the View).
Another way to think about the ViewModel is like so: the ViewModel is the complete user-facing state of the system. In other words, this state and nothing else would be used by the View to show/present this state in some user-understandable way.
About Commands vs. Events:
Unfortunately, not everything in WPF is exposed as a Command. Buttons generate Commands, but not all controls do.
Luckily, you can use Behaviors to translate Events to Commands and some frameworks provide the implementation. Here's an example of how MVVM Light does this. Blend also provides this functionality.
Also, why do you need to generate Commands in the code-behind? Frameworks like MVVMLight provide an implementation of a RelayCommand (or DelegateCommand) that removes the need to create different ICommand implementations. You can just as easily implement it yourself.

MVP: Is it the View or the Presenter that should know of the Model?

Relatively new to patterns, let me straight away show an example in the context of WinForms.
I have a basic MVP Passive View structure, which one should I go ahead with:
public partial class UserView : Form, IUserView
{
public event EventHandler Save;
public UserView()
{
InitializeComponent();
new UserPresenter(new UserModel(), this);
}
}
public class UserPresenter
{
public UserPresenter(IUser model, IUserView view)
{
view.Save += (sender, e) => model.Save();
}
}
or
public partial class UserView : Form, IUserView
{
public event EventHandler Save;
public UserView()
{
InitializeComponent();
new UserPresenter(this);
}
}
public class UserPresenter
{
public UserPresenter(IUserView view)
{
var model = new UserModel();
//assuming I have the logic to bind property values from View to Model
view.Save += (sender, e) => model.Save();
}
}
My questions are:
1) Who should know of the concrete instance of model User, View or Presenter?
2) What will be the benefit in that case?
3) Suppose my Model is never dependent on the View. In that case what's wrong if View knows Model? After all UserView is made to present UserModel isn't it?
4) If Presenter should interact with only interfaces of Model and View, then to call model.Save in Save eventhandler, where do I get the concrete instance of Model from?
There are two duplicate questions here and here, but they aren't exactly dealing with my scenario I guess..
Strictly speaking, you should have the following rules:
Model does not know the View or the Presenter.
View does not know the Model or the Presenter.
Presenter knows both Models and Views, but only through their interfaces.
The Presenter coordinates all communication between the Model and the View, typically by handling events that are raised by the View. So to answer your questions:
1) Who should know of the concrete instance of model User, View or Presenter?
Ideally, neither. The Presenter should be communicating with UserModel through an IUserModel interface. The concrete instance is injected into the Presenter (e.g. through its constructor).
2) What will be the benefit in that case?
The primary benefit is for automated unit testing. You can inject mock Models or Views to test units in isolation.
3) Suppose my Model is never dependent on the View. In that case what's wrong if View knows Model? After all UserView is made to present UserModel isn't it?
There's nothing inherently wrong with it. There are variations of MVP that support direct communication from the View to the Model, typically to take advantage of data binding. You lose some testability in exchange for not having to write the binding code from scratch.
4) If Presenter should interact with only interfaces of Model and View, then to call model.Save in Save eventhandler, where do I get the concrete instance of Model from?
Depedency injection, such as the simplified example shown below.
public class SamplePresenter
{
public SamplePresenter(ISampleModel model, ISampleView view)
{
view.Saved += (sender, e) => model.Save();
}
}
public interface ISampleModel
{
void Save();
}
public interface ISampleView
{
void Show();
event EventHandler Saved;
}
public class Program
{
[STAThread]
static void Main()
{
ISampleModel model = new SampleModel();
ISampleView view = new SampleView();
SamplePresenter presenter = new SamplePresenter(model, view);
view.Show();
}
}
What's wrong if view knows model? After all UserView is made
specifically for UserModel isnt it?
Nothing. It's accepted practice in the Supervising Controller variant of the MVP pattern. The view interacts directly with the model for simple operations while more complex operations are marshalled throught the presenter. While in Passive View, everything goes through the presenter.
Additionally, see Jeremy Miller's Build your own CAB series to get a better idea on the differences between the two approaches: Supervising Controller and Passive View.
The Presenter should know about the Model, the View should not. A presententation layer is a good idea in many user interface applications. A presentation layer is simply an adapter. It presents an interface that's easy for a user interface layer to use (i.e., it presents lots of events, bindable properties, and so on) while obscuring the underlying data layer. This makes the data layer easier to re-use.
EDIT
So why can't the view just talk to the model directly? It certainly can. The problem is that there is usually an impedence mismatch between the model and the view. In other words, the programming interface that's natural for the view to use does not match the interface that's natural for the model to expose. If you adapt the model to suit the view's needs, then you end up creating a strong coupling between the model and the particular type of interface you're using.
For example, your app might be a GUI app today, but what if tomorrow you're asked to produce a version for the cloud? The events and bindable properties that are helpful for Winforms will just get in the way when you try to switch to WCF Rest. If you use a presentation layer, then adapting your code to the new environment will be much easier.
If it's not too much for your introduction to presentation patterns, I'd urge you to take a look at the Presenter-first variant of MVP.
In this variant, and providing an answer to your question, the presenter knows both the model and view but only via interfaces. Neither the view, nor the model know of each other. The presenter co-ordinates each via events and methods.
http://atomicobject.com/pages/presenter+first
http://spin.atomicobject.com/2008/01/30/presenter-first-get-your-triads-talking/
Example:
Class Presenter {
private IModel model;
private IView view;
void Presenter(IModel model, IView view) {
_model = model;
_view = view;
}
void Initialise() {
// Attach handler to event view will raise on save
_view.OnSave += HandleViewSave();
}
void HandleViewSave(){
_model.Save(_view.GetStuffToSave());
}
}
Very basic example but illustrates the point. The presenter is merely a conduit for communication between the view and model.
Creating the presenter can be done with Poor Man's DI or a proper container:
Presenter p = new Presenter(new CustomerModel(), new CustomerForm());
Note that AtomicObject recommend no reference to presenter, so it actually looks like this:
new Presenter(existingCustomerModel, existingCustomerForm);
existingCustomerModel.Initialise();
The fact that the model and view have scope means the presenter also stays in scope via its references... clever.

Update observable collection by requerying or adding to collection?

I have a observable collection exposed as a property within a view model. The observable collection is loaded with objects from a data access layer (linq2sql).
When a new item is added to the database through another view model what is the best way to update the observable collection? Should I repopulate the observable collection with a query to the database or directly insert the new object into the collection?
Also I am still trying to work out how to get one view model to communicate with another one, but I've only been using mvvm for 3 days.
You can use a whole new class to manage notifications from one class to another. For the question regarding whether to load all entities or just add newly added entity, it really depends on the number of possible entities to load each time. If they are going to be very few, you can reload them each time, otherwise just add the newly added object to the collection.
Example:
class ViewModel1
{
ObservableCollection<Object> entities;
public ViewModel1()
{
EventsManager.ObjectAddedEvent += new EventHandler<ObjectAddedEventArgs>(EventsManager_ObjectAddedEvent);
entities = new ObservableCollection<Object>();
}
void EventsManager_ObjectAddedEvent(object sender, ObjectAddedEventArgs e)
{
entities.Add(e.ObjectAdded);
}
}
class EventsManager
{
public static event EventHandler<ObjectAddedEventArgs> ObjectAddedEvent;
public static void RaiseObjectAddedEvent(Object objectAdded)
{
EventHandler<ObjectAddedEventArgs> temp = ObjectAddedEvent;
if (temp != null)
{
temp(null, new ObjectAddedEventArgs(objectAdded));
}
}
}
class ObjectAddedEventArgs : EventArgs
{
public Object ObjectAdded { get; protected set; }
public ObjectAddedEventArgs(Object objectAdded)
{
ObjectAdded = objectAdded;
}
}
class ViewModel2
{
public void AddObject(Object o)
{
EventsManager.RaiseObjectAddedEvent(o);
}
}
Whenever a model object is saved into the database, send a message to the viewmodels including the saved model object. This could be achieved using the Messenger helper class in MVVM Light Toolkit
As for the second part (how to teach view models talk to each other) I prefer to keep view models as decoupled as possible. Thus Event Aggregation or some kind of Message Broker seems to be natural choice.
The first part of the question is bit trickier, and I don't know correct answer. If Observable collection contains thousands of items I would try to choose an approach that doesn't involve complete reconstruction. Otherwise try the simplest and easiest solution you can come up with.
I use libraries I created that effectively allow one DataContext to save changes back to a parent DataContext and for a parent DataContext to notify its children that it just received changes.
With this functionality, I create a single master DataContext for my whole application, then for any modal windows with Ok and Cancel buttons or other parts of the UI that temporarily need their own "view of reality" I create child DataContexts. When the child DataContext writes back to the parent this causes all controls bound to objects in the parent to update and for the parent to broadcast the changes to all children so they can update too (or not, if they are in snapshot mode).
This solution took a while to code but works beautifully. I also use exactly the same mechanism to send changes to a parent DataContext on the server which is shared by other clients, so everyone has up-to-date data and giving me great caching performance. I even use it for communicating with my back-end data store.

Resources