0

I'm creating a simple network application that communicates with one or more services, so I planned to use some queues (for outgoing messages and incoming ones), a table, a list containing the status for each active connection, etc.: in other words, these are the data structures needed to ensure the functioning of the application itself.

This application must also be equipped with a graphical interface that shows part of the internal functioning of the application itself: for example, the filling status of queues, the status (detected speed, etc.) of the connections, etc.. According to the Model-View-ViewModel pattern, the model consists of the data to be displayed in the GUI: in this application, the aforementioned data structures represent the model. In other words, the Model implements the business logic of the application.

The ViewModel should implement INotifyPropertyChanged interface in order to notify the View that a change is occurred, but how does the Model to communicate with the ViewModel? After reading this article, I realize that the INotifyPropertyChanged interface is implemented by the model. This answer explains a little more, but it confuses me a bit:

INotifyPropertyChanged - Should go into ViewModel and Model (if needed)

Why, if needed? When should I implement this interface? When should I not implement it?

Moreover, the Dictionary does not implement the INotifyPropertyChanged interface: if I use it, should I wrap it with a class which implements this interface?

Finally, the model should be read-only, meaning that the user does not be able to change the contents of internal data structures using the GUI. How to accomplish this?

Community
  • 1
  • 1
enzom83
  • 8,080
  • 10
  • 68
  • 114

3 Answers3

2

how does the Model to communicate with the ViewModel

Any way you want it to. In most of the apps we write, the view model makes calls to the business logic layer (the model). However, if you have a need for the view model to be notified immediately (events) of changes to the model, you could implement INotifyPropertyChanged on your model. Or you could simply have the view model subscribe to events on the model.

Moreover, the Dictionary does not implement the INotifyPropertyChanged interface: if I use it, should I wrap it with a class which implements this interface?

You only need to have the view model implement INotifyPropertyChanged. Properties within the view model (dictionary) will simply invoke NotifyPropertyChanged (or whatever your implementation looks like).

Finally, the model should be read-only, meaning that the user does not be able to change the contents of internal data structures using the GUI. How to accomplish this?

Don't provide the user the functionality to let them change the data. Make the binding one way, or simply don't provide them an API for making changes.

Bob Horn
  • 33,387
  • 34
  • 113
  • 219
1
  1. INotifyPropertyChanged is primarily implemented by the ViewModel classes. This is to facilitate the data-binding so that the UI controls in the view that are bound to the ViewModel property will be updated when the property is modified.
    In the MVVM design pattern, the relationships are very simple and in a single direction. The View knows it's ViewModel and a ViewModel knows about the Model. If the Model is updated, the ViewModel needs to know somehow so that it can reflect the update and propogate it to the View. One way is to also have the Model implement INotifyPropertyChanged and have the ViewModel implement the corresponding event handler. If all the changes are driven from the UI and being pushed back to the Model, then this is probably not necessary.

  2. You can't really bind to a Dictionary. Using an ObservableCollection would be ideal if that works in your case. Or, you can take a look at implementing an Observable Dictionary along the lines of this: http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

  3. MVVM has provided separation of the Model from the View, so there should be no direct relationship from the View to the Model. The implementation of the ViewModel controls what, if anything would ever get written back to your Model.

Gambit
  • 2,455
  • 18
  • 20
  • This post shows binding to a dictionary: http://stackoverflow.com/questions/3334128/binding-a-dictionarys-key-and-value-in-a-listbox-with-wpf – Bob Horn Aug 16 '12 at 23:53
  • @Bob Horn - Yes, in that case the values of the dictionary are probably being pulled into the control via databinding, but how is it updated when the values in the dictionary changes? I do not believe that it does given that there is no notification provided. – Gambit Aug 16 '12 at 23:59
  • Good point. Whatever updates the dictionary would have to invoke OnPropertyChanged, and that's not ideal. – Bob Horn Aug 17 '12 at 00:20
  • 1
    No no. The `INotifyCollectionChanged` is meant to inform on collection changes. INotifyPropertyXXXXX are for notifying on object/property change, and INotifyCollectionChanged informs that the object/collection is the same, and that just the list of items was updated. Sadly, the Dictionary/IDictionary lacks that. But you can work this around: Binding presented in that article binds to the Dictionary, but **does not use that** - no [key] is used. Actually, it binds to `IEnumerable>`, so instead of exposing a Dictionary, it could be wrapped into a refreshable collection view, etc. – quetzalcoatl Aug 17 '12 at 07:22
0

INotifyPropertyChanged (INPC) should never be in the model unless the model is also the ViewModel (i.e. you don't have a "model"). INPC should only ever be in the view model.

The model should know nothing about the view model, and thus can never communicate with it. Only the view model can communicate with the model.

From the UI point of view, only the view model does anything with data; so, if you want the model to be "read only", then just don't implement that in the view model.

Binding would be done with the view model, in which case don't use Dictionary (unless you want to write the code to wrap that in order to bind it). If the Dictionary is in the model, then you should be "wrapping" that in the view model--it's fairly trivial to write an observable wrapper around a collection. In all likelihood your view model isn't going to deal with key/value pairs--it should be dealing with something flat that the UI can handle (and be bound to).

UPDATE:
INPC was introduced for data binding. It decouples a view from a particular concrete class so that it only needs to know about INPC (notice the direction of decoupling). In terms of MVVM this decouples the view from the view model, in the case of PM, this could decouple the view from the presenter, in the case of MVC this could decouple the view from the controller, in the case of MVP this decouples the view from the presenter.

Data binding is a technique of binding data to UI elements. It binds a data source to a target so that the target may request data how ever it sees fit or the source can push data however it sees fit (depending on the type of binding--it could be one-way or static, restricting how often get/push can occur).

Sometimes the necessary nature of the decoupled relationship between the data source and the target lead people to believe data binding isn't a UI concern and data binding can apply anywhere. i.e. a data binding implementation is completely decoupled from a UI. This is generally a mistake. Data binding decouples the view from the specific knowledge of specific classes (this is basic layering and avoidance of cycles, that I won't get into here). But, it doesn't completely decouple the view from the data source. Binding can't happen without the data source--there is still a level of coupling there, it's just the compile-time coupling that has been alleviated (aids in testing, flexibility, robustness, etc. but must be present at runtime in production. i.e. the fact that the INPC implementation can be tested without being bound at runtime to UI elements doesn't mean it's not dependant on a UI framework). The fact that the view is still loosely coupled to the data source isn't the only coupling in this relationship. The data source is loosely (if not less loosely) coupled to the view by way of its UI framework.

Every UI framework has a restriction that access and modification of UI elements must be done on the main, or UI, thread. (at least on Windows; it likely happens on other platforms, I'm just not proficient in any others). With data binding, the source is indirectly bound to the control and any data change directly changes one or more UI elements (depending on the framework you can have intermediaries. Like value converters in WinRT, but their responsibility is to transform or convert data). This means that the data source needs to have intimate knowledge that it is bound to a UI and what type of UI framework it is binding to. This tight coupling to a UI framework clearly couples the data source (still loosely) to the UI.

This means any particular implementation of INPC is really bound to one and only one UI framework. That object can no longer be used anywhere (obviously anywhere is an ideal, it's often impossible to make anything work for every scenario--the point here is high cohesion in more than just one or two scenarios). e.g. if an implementation of INPC is used in a multi-threaded environment then it needs to "marshal" data back to the UI thread before sending out property notifications. In WinForms, that's Control.BeginInvoke, in WPF and Silverlight that's via System.Windows.Threading.Dispatcher. In WinRT, that's via Windows.UI.CoreDispatcher. In all cases the INPC implementation must take a direct coupling to one UI framework. In the case of Silverlight, that's a direct coupling to either the "desktop" Dispatcher or the Windows Phone Dispatcher.

Quality metrics include concepts like cohesion. Cohesion is a measure of how strongly related two units of code are. An implementation of INPC that is used by something other than the UI, due to the nature of all the infrastructure required to support that one particular UI framework, although potentially able to be used outside of the UI, will have low cohesion because all of the code relating to the UI framework will not be used. i.e. it's take on too much responsibility to be completely decoupled from the UI. Yes, you can use an object that implements INPC anywhere and never use the PropertyChanged event, but then you have low coehsion (considered bad).

If I implemented INPC in my model and I wanted to use that model with both my UI and my WCF or web service back end, I either couldn't or my backend would have to take a reference to some UI framework. If I wanted to use that model in another type of UI, I couldn't, because that INPC implemetnation depends on one particular UI framework. I'd have to write another "model"; at which point it's clearly a "view model".

INPC itself is not bound to a particular UI framework (nor should it be). This leads to the misconception that INPC can be used anywhere. Yes, its lack of coupling to high-level namespaces means it can, but the overwhelming usage of INPC is when the target is a UI. I'd challenge any other uses of INPC that don't involve a UI as true "binding". As with any other tool, you can misuse it to get useful results. INPC could be used for projecting data, it could be used for transforming data, etc.; but I believe those are misuses of INPC and really outside the focus of this question...

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • 1
    ***Never/ever***?! Even EntityFramework uses it. Are you saying that EntityF is a ViewModel? What you written in the opening on INPChanged usage is justcompletely wrong. INPC is ***older than the XAML, WPF or the MVVM itself***. So old, that good ol' WinForms used that. This is a general-purpose interface describing the premise of notificaation about property change. You may use it anywhere you like. That fact that WPF listens to that is a coincidence, or rather, a nice nod to the programmers from MS architects,as they used a good well known interface. You just need to know what you are doing. – quetzalcoatl Aug 17 '12 at 07:16
  • True, the Model should not know about the ViewModel, but why should that imply that it can't communicate with it? A speaker doesn't need to know everyone in the audience to give a lecture to them. – Gambit Aug 17 '12 at 07:53
  • @quetzalcoatl EF is a data model. You have great flexibility in what you can do with EDMs, but they still suffer from impedance mismatch. Using EF entities directly in your UI via data binding couples your UI directly to your data model. This is one of the reasons why the POCO abilities of EF have become so popular. Same coupling issues occur with EF, if I update data on a background thread, my Entity no needs to know how to marshal to the UI thread--you don't get that out of the box with EF. "WinForms", yeah nother **UI** framework. – Peter Ritchie Aug 17 '12 at 15:20
  • @Gambit See my update, I've detailed how INPC implementations are really coupled to the view. I'm not sure the speaker analogy makes sense; but the speaker must know what language everyone in the audience speaks in order to be useful. – Peter Ritchie Aug 17 '12 at 15:22
  • @PeterRitchie INPC aside, my main point is that the Model can and needs to have communication with the ViewModel and/or the Model. This communication is anonymous, as the Model doesn't have to know specifically the VM or View, but it will communicate some info to them. INPC is just one mechanism (and a very convenient one) that can facilitate this. If the Model is static, then the communication isn't necessary. But if it's not, how will the VM ever know when the Model has changed? – Gambit Aug 17 '12 at 16:35
  • @Gambit That's one of the responsibilities of the VM to know when the model is changed. If the change occurs through the UI, the VM is *told* about it. If it's from an external source the VM should detect that and re-query the model in a way that is proper for the UI requirements. Constant external updates of data has the potential make the UI unresponsive--not something you want to allow to happen. i.e. you'd batch updates to the UI--something a VM would be responsible for, not the model. – Peter Ritchie Aug 17 '12 at 16:44
  • 1
    @PeterRitchie I guess we have a different view of what the MVVM pattern is then. The VM is responsible for presentation logic and data to support the View. It has no knowledge of how the data in the Model is sourced or the triggers in the Model that may cause it to change. As for batching UI updates, the VM can easily handle that if the Model is notifying it of changes. The VM decides when to notify the View. The Model could care less. It's just saying "FYI, something's changed here". – Gambit Aug 17 '12 at 17:03
  • @Gambit I'm saying having to use the Dispatcher or Control.Invoke/BeginInvoke is presentation logic. Notification of data changes *is not business logic*--a "model" is only business logic in *any* definition of MVVM. – Peter Ritchie Aug 17 '12 at 17:17
  • @PeterRitchie Comments are getting too long and discussion doesn't seem productive. I am dropping out. We'll just have to implement MVVM in our own ways. – Gambit Aug 17 '12 at 17:29
  • @PeterRitchie - while you added a lot of accurate descriptions and I've almost retracted the -1, you are still mis-explaining one important point: the INPC has nothing to dispatchers and thread-safety. If at some point anyone publishes a UI framework that does not have a my-threads-only constraint, the INPC will still work. If your implementations of INPC are hard-bound to any UI Dispatchers - it is all your fault that this code is non-portable, not the INPC's!! If I need, then my implementations are flexible in terms of thread-synchronisations of event invocations. Saying that, I'm out too. – quetzalcoatl Aug 17 '12 at 19:42
  • @quetzalcoatl Well, I think I explain at the end about how INPC is decouple by nature. But INPC leads you down a path of coupling to the UI so that if you *do* introduce threads (usually when, not if) your model has to couple to a single UI framework. FWIW Windows has been trying to get away from a single-thread requirement literally for years. Other things to consider: distribution of your business layer (creating a tier), sharing your business layer across different platforms (web, WPF, WinForms, etc). – Peter Ritchie Aug 17 '12 at 20:40
  • @Gambit: _If the Model is static, then the communication isn't necessary._ Why? – enzom83 Aug 17 '12 at 21:35
  • @PeterRitchie: https://docs.google.com/open?id=0B1179asykTa5cU9NOW5mdkRoWnc Please review the samples. Models presented there are independent of UI and with a few tricks work nicely both on WPF and Forms. Sure, I've got to do some work, but that additional code is mostly reusable, and hey, there's non-UI threads, extra work is granted. Please note that sharing INPC posed no problems at all. Collection binding was a little worse, as Forms use IBL versus WPF's INCC. Models expose then as IList<> so the mismatch is naturally hidden, and impl selection is easy to solve with factories or IoC. – quetzalcoatl Aug 18 '12 at 01:14
  • If you want to see that, get the package soon from gdocs. The code will be removed in a few days. After that I'll probably post it at http://quetzalcoatl-pl.blogspot.com/, but I don't guarantee to remember about it later:) – quetzalcoatl Aug 18 '12 at 01:16
  • Maybe I understood how the ViewModel can detect changes in the Model (without the Model notifies the ViewModel): in practice it is sufficient that the Model is inside the ViewModel, that is, the object that represents the Model could be a private attribute of the viewModel, so the ViewModel acts as an intermediary both for writing and for reading the Model. – enzom83 Aug 18 '12 at 10:18
  • @enzom83 The Model can be an attribute of the ViewModel. However, this doesn't mean that the ViewModel will automatically know if something has changed in the Model unless the ViewModel is the one initiating the change. In those cases where the underlying Model is modified by something else, a mechanism is needed for it to let the ViewModel know (or the View if it is directly databound to the View). – Gambit Aug 18 '12 at 19:01
  • I admit I do ont remember the whole discussion, but I think the enzom83 walks all the time around the same problem: which side **knows** and how does it **notify** the others? At the core of it lies a tiny misunderstanding on the naming level. The View is the thing build with "controls", used to display other things. The ViewModel is the abstract model of the View, that describes what data View uses and what actions View can invoke. In this nomenclature, the last, the Model is "all the rest". Business, Data, Networking, Blargh, is in the Model. The describes only the "view" aspects. – quetzalcoatl Aug 19 '12 at 10:12
  • In this way, it is the "Model"'s responsibility to know everything and to drive/inform/notify to all the rest. The View+ViewModel sometimes invokes some actions, but they in the end lead to the Model that changes something and notifies back.. The ViewModel is only an intermediary contract, so you can exchange Views to other ones, designed in parallel by separate people. This is the core idea. Now, as we have three-level structure, there have been some movements to use it directly: use Model as DataModel, use ViewModel as logic, use View as View and navigator, etc – quetzalcoatl Aug 19 '12 at 10:15
  • 1
    but in the end, in later stages, they all seem to have problems with assigning resposibilities and communications.. This is where we should look back at the core. As MVVM was meant to simplify designing UI in separation from code, it does not care about Business. It cares only with Visual/View and Bindings aspect. From its point of view, the Model is "everything else". Thus, for us, the Model must be analyzed further. For instance, try logically splitting it into "controller", "business logic" and "datamodel". A to that "ViewModel" and "View". – quetzalcoatl Aug 19 '12 at 10:18
  • View + ViewModel <-> Controller <=> BusinessLogic <-> DataModel; and Controller <- DataModel; and ViewModel <- DataModel. It is bloated but you instantly "see" who knows what and how the communication passes. User invokes an action, it is fetched by Controller, which invokes some logic that does something on the DataModel. Then, controller inspects the changes and updates the ViewModel accordingly. During that, the Controller may pass DataObjects to the ViewModel directly, to display them somewhere. Everything clear now? – quetzalcoatl Aug 19 '12 at 10:23
  • Business logic never does touch the view/viewmodel and is abstract in terms of UI. Controller binds the actions and the business logic and thus also must know what is being changed and what should be presented next. Thus, business logic notifies noone about nothing, or just sometimes informs the controller about something. Controller notifies to noone - he **orders** everyone to do something or to present something. Then ViewModel notifies the View. DataModel should implement **simple** change notification(INPC?) on the purpose of just-displaying-it, but otherwise it is only plain data object. – quetzalcoatl Aug 19 '12 at 10:27
  • While it seem simple, it has some problems: first one is what PeterRitchie said abot threaing. If you pass DataModel "to simply view it", you must be very careful about which thread modifies the data inside. The same with ViewModel. But this is doable in a general as I've shown. Worse, having View-ViewModel-Controller-Logic-Model is a bloat. Many times you will just implements tons of forwarding code to pass the click to the Logic and back. – quetzalcoatl Aug 19 '12 at 10:31
  • This is why , **for small applications**, the Controller is split and its parts are put into XAML (Navigation,Actions) and ViewModel, and the BusinessLogic is merged into the ViewModel. And magically you are left with "View", "ViewModel" and (Data)Model, and you write shorter snips of code to get it working, but in fact, it's all mixed. You have to, i.e. to set in XAML some conditional bindings to invoke navigation or to disable some business logic, or process the data in a ViewModel and then you smell problems when other ViewModel(s) seem to duplicate it. Sometimes it is OK, sometimes not. – quetzalcoatl Aug 19 '12 at 10:35
  • For almost any simple app, it is OK, but as the app grows, you tend to see you simply need more layers, sometimes even more than I've just presented (i.e. split Controller between the 'StageController' and 'NavigationController') and that your VM are starting to be more "a useless boilerplate code", just like DataModels do when you use some ORM frameowrk. This is not true, they are not useless (as they separate the View!), but this is in fact how they should look like! – quetzalcoatl Aug 19 '12 at 10:42
  • @quetzalcoatl No, the Model has the strictest responsibility: only business logic. DataModel and Model are two different things. Notification is destination-specific, to move from WPF to WinForms would require a change to the model (if it implemented INPC and the model was used in a background thread). Having to change the model based on UI concerns is widely regarded as a really bad thing. e.g. Single Responsibility Principle. – Peter Ritchie Aug 19 '12 at 19:27
  • With code examples I have proven that even with use of INPC you do NOT HAVE TO change the VIEW MODEL implementation when moving from WPF to Forms, even if BG threads are working inside. Just apply the same approach to DataModel and you will not have to modify it either. You really dont see that? Have you seen the example I posted earlier, or are you still zeaosly repeating the same mumble with eyes closed? BTW. where did I say that Model and DataModel is the same, huh? I clearly pointed out that they are at different areas of abstractions. Try reading ALL what I wrote next time, ok? – quetzalcoatl Aug 19 '12 at 21:06
  • I've restored the link: https://docs.google.com/file/d/0B1179asykTa5cU9NOW5mdkRoWnc/edit it will stay for another few days. Please see the code regarding threads, Wpf, Forms, and Models with INPC and review your opinions on what an interface/notification forces you to do. The sample uses the same ViewModel classes for both WPF and Forms, and the Models evilishly create many non-UI threads that randomly modify them, and you can edit the models (2-way bindings) on the UI, too. XAML and Forms are bound directly to the models. Impossible? Not. It works. See for yourself. Not that complicated, too. – quetzalcoatl Aug 19 '12 at 21:12
  • @quetzalcoatl yep, still a password protected archive... Next time you want me to read something, provide access. *OK* – Peter Ritchie Aug 19 '12 at 22:05
  • Ouch. I'm sorry, I've got so irritated that I've forgot to write down the pass to zip: "threads" – quetzalcoatl Aug 20 '12 at 10:33
  • I actually spent the time trying figure out the structure of the code--everything has a Model name, in a ViewModel namespace. I'm assuming `SomeTopLevelModel` is the *view model* and `SomeItemModel` is the *model*. ArgumentOutOfRangeException in WinForms. 170+ lines of code to manage 4 properties? That doesn't concern you at all? The basic design has the power to overwhelm the UI. The UI is coupled to the fact that model is throttled. If the model went as fast as it could (and why wouldn't it) the UI would hang. – Peter Ritchie Aug 20 '12 at 16:00
  • You wouldn't want external sources to influence the UI that directly. But, you're not listening to what I'm saying, so I'm not interesting in continually repeating myself. If you want to fall back on "it works". Have fun with that. Patterns weren't created because of situations that did work, they were created for situations that did, but suffered from other problems. – Peter Ritchie Aug 20 '12 at 16:01