How to handle bindable application wide variables in a WPF MVVM application? - wpf

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.

Related

ViewModel communication pattern

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.

ObservableCollection and Repository pattern in MVVM - How to relate them, and a case for the "Update" method

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.

Should I dependency inject? How do I do it?

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.

ViewModel-first approach to Silverlight navigation

I am looking for a truly decoupled way of supporting navigation in a Silverlight application using MVVM. I am trying to accomplish more of a "purist" implementation of the pattern where the UI is completely separated from the ViewModels so that the application can actually run entirely without a UI. To do this, I need to support navigation without UI concerns.
I have several ideas how to accomplish this (with Messaging, etc) but haven't come up with a good way of "mapping" the View to the ViewModel so that the UI can show the appropriate View when the ViewModel is "displayed". I recall coming across an article some time ago that described a solution to this very problem but can't seem to locate it online anymore.
Does anyone know how to find this article or have any experience solving this problem?
So here's my somewhat long-winded description what we ended up doing:
First, we decided to use the built-in Page Navigation framework. We had multiple reasons but since it is built-in and is also the navigation framework du jour in Windows 8, we opted to try this approach.
I should also mention that we use MVVM Light and MEF in our applications. (This comes into play below.)
To make this work, we created an application Shell (UserControl) that contains the Frame control. The Shell's DataContext is set to an instance of the ShellViewModel which exposes a single CurrentPage property (of type String). We then bind the Frame's Source property to CurrentPage. This approach is similar to Rachel's app-level ViewModel.
The ShellViewModel registers with the Messenger to receive CurrentPageChanged messages. When the message is received, the CurrentPage property is updated, the PropertyChanged event raised and the UI updated. The message originates from the NavigationService (which implements INavigationService and is injected/imported using MEF).
The NavigationService exposes a NavigateTo method which accepts the string name of the ViewModel representing the destination. This name matches the contract name applied to the ViewModel when exported (using MEF) and used to lookup the instance using our ViewModelLocator.
In the NavigateTo method, we use the ViewModelLocator to retrieve the ViewModel instance, call Deactivate on the current ViewModel (if one), call Activate on the new ViewModel then send the CurrentPageChanged message with the name of the new view as a parameter. Activate/Deactivate are helper methods on the ViewModels that allow us to perform any necessary tasks when the ViewModel is navigated to or from.
This appears to be working well and gives us a very MVVM-ish implementation with all navigation isolated from our ViewModels via the INavigationService and messaging.
The only down-side right now is that while we are using string constants in code to represent the ViewModel names, we are still hard-coding the strings in the Views to set the DataContext. I will be looking into a way to set the DataContext automatically as part of the navigation 'tooling'.
I should mention that this approach was parsed together from a number of sources, including (but not limited to) Rachel and the following links:
http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/01/25/adapting-silverlight-navigation-to-mvvm.aspx
http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx
http://www.geoffhudik.com/tech/2010/10/10/another-wp7-navigation-approach-with-mvvm.html
Usually I have a ViewModel for the entire app, and it contains the CurrentPage and all navigation event handling.
On the View side, I use a ContentControl with it's Content bound to CurrentPage, and use a DataTemplateSelector to determine which View to display for which ViewModel
There's an example here if you're interested, although it uses DataTemplates instead of a DataTemplateSelector.

Custom property dependant on other properties

Advance apologies for the event-style explanation; there's a lot of factors that I feel all play a role of their own. WPF is not my native framework of choice, and it probably shows. :)
Old situation: I had a window with several controls. Depending on their selections, I used multibindings and a converter to determine whether certain controls needed to be shown that inform the user about the implications of their changes before they'd eventually confirm them by OK (or simply dismissed by using Cancel). This worked perfectly.
Problem: Too many controls as time went by, too much clutter.
Solution: Put stuff in different Pages so it becomes easier to browse for the user. In order to have changes-to-be persist as a user arbitrarily browses between the pages, I create these dynamically and put them in a cache (Dictionary<string, BasePage>, see below), from which they will be pulled as the user chooses them.
Consequence: I need to decouple the bindings to the notification controls as the different options are now on different pages.
Solution? I put a BasePage class in that exposes certain abstract read-only properties that define the various aspects that the window needs to know about in order to do its notifications. For example, a bool requiresReboot property defines whether the current state of things on that page requires a reboot to take (full) effect. A specific page implements the property based on its controls.
Problem: I do not know how to keep create a proper binding that properly gets updated as the pages are changed. I tried giving my notification controls a binding to the Dictionary<string, BasePage> with a converter that checks all pages and the relevant property.
Questions:
1) How do I create a proper property for this purpose? I presume I need a DependancyProperty as I did a fair bit of reading on MSDN, but I can't figure out how this fits together.
2) How do I make a link between my custom property so that it allows (multiple) control(s) on a page to change that property? Do I use INotifyPropertyChanged somehow? My old example bound against several CheckBox.IsChecked properties in XAML. I am trying to avoid putting tons of events (OnChange, etc) on the controls as the original code did not need it and I have been told it makes for a messy solution for as far WPF is concerned.
3) Finally, I suspect I may need to change my Dictionary<string, BasePage> class to a custom implementation that implements some sort of INotifyPropertyChanged but for Collections? Observable Collection is the term I am looking for, I believe.
I hope someone is able to bridge the gap in my understanding of WPF (property) internals; I would very much appreciate it. A basic sample would be even better, but if it is too complicated, just a nudge in the right direction will do. Thank you. :)
It's been a while since I solved this, and while I cannot remember the exact cause of the problems, there were a few different issues that made up the bulk of the trouble I ran into.
I ended up making the Property in question a non-abstract DependencyProperty in the base class; it was the only way in which I could properly delegate the change notifications to the interface. Derived classes simply ended up binding it to their controls (with a proper Converter in the case extra logic was necessitated).
As Dictionary<string, BasePage> does not support any sort of change notification, I made an extra collection of ObservableCollection<BasePage> which I used for binding purposes.
However, such a collection does not propagate a change event when items inside of it has a property changed. Since this situation required that, and I was binding to the collection itself in the context of a property that does not have a Master<->Detail relationship like a DataGrid (which basically add their own OnPropertyChanged handlers to the binded object), I ended up subclassing a VeryObservableCollecton<>. This one listens to its own items, and throws a proper change event (I think it was an OnPropertyChanged from the INotifyPropertyChanged interface) so that the binding (or in this case a multi-binding) would refresh properly and allow my interface to update.
It is hardly the prettiest code, and it feels over-engineered, but at least it allows me to properly bind the UI to the data in this manner.

Resources