I'm using MVVM for a WPF client that represents a model and allows users to interact with it. I've always shied away from using the ObservableCollection class in the actual model (opting for generic collections like IList inside that model instead, and then converting that IList to the actual data-bound ObservableCollection on the ViewModel when the underlying collection changes). Reason being that MSDN presents the class as WPF and UI-centric:
You can enumerate over any collection that implements the IEnumerable
interface. However, to set up dynamic bindings so that insertions or
deletions in the collection update the UI automatically, the
collection must implement the INotifyCollectionChanged interface. This
interface exposes the CollectionChanged event, an event that should be
raised whenever the underlying collection changes. WPF provides the
ObservableCollection class, which is a built-in implementation of a
data collection that implements the INotifyCollectionChanged
interface.
Question: Is my distinction actually necessary? It's extra work and extra code. I understand that this topic might be too vague and subjective for SO, but maybe there are clear, universally agreed-upon conventions everybody follows.
Yes I think you are doing it right. Observable collections belong at the presentation layer. Add them to your view model, not your domain model.
This question may be of some help
but maybe there are clear, universally agreed-upon conventions everybody follows.
Please let me know when you find them, thx.
Is my distinction actually necessary?
It depends on what a model really is in this case, or rather how you define a model.
If it is some kind of domain business object that is defined in an assembly that is referenced by your business or service layer and may be used across your entire domain, it shouldn't implement any kind of client-specific interfaces such as INotifyCollectionChanged.
Then you should prefer to use a generic type such as IList and then create a wrapper class in the client application that you bind to the view element to.
But if the model is a class that is used only inside your client application and not in any other tiers of your application, then you might as well define the collection property as an ObservableCollection and bind to this one directly.
The point is that a domain business object should not have any knowledge of WPF or the fact that a client application may bind to it. That's why it seldom makes sense to bind directly to such objects in a WPF application without wrapping them in WPF-aware view model classes first.
This does add some extra work and an additional class but at the same time it helps maintain separation of concerns which is usually good for maintenance.
In an enterprise scenario it is also pretty common that the business object may contain business logic that you don't want to expose to the client and it also may contain additional properties that it makes no sense to expose to the view. So then you still need to wrap it in another class even if the collection property should actually return an ObservableCollection.
So if your question is "should I use ObservableCollections in the business objects" the answer is no.
Related
I am developing a C# MVVM WPF app and have problems to decide whether I should use the message mediator pattern or simple INotifyPropertyChanged for my UI 'live' Model change notifications. The problem in particular is that my model represents a graph with lots of 'live' objects that all have properties where different viewmodels will be interested in the changes at some point. I have about 3-5 viewmodels active that need notification of model changes. Some changes might be nested deep inside the models 'grandchildren'.
I tried to compare both messaging techniques, mediator pattern and INotifyPropertyChanged, and think that the mediator is better suited for change notifications between different modules/systems. My viewmodels definitely need the initial values of the model upon initialization and then change notifications afterwards. INotifyPropertyChanged seems to be the optimal choice in my case, but I am a bit skeptic, because I think lots of nameof(e.PropertyName) switch cases are not very elegant. Are there better alternatives for this problem?
As is typical for such cases, you could have both ways. You will obviously not be able to avoid using INotifyPropertyChanged because this is the WPF way of handling MVVM-based Data Binding, so all your view-models will be at least basic implementations of this interface.
I suspect that you might simply need both. I would not suggest using the INotifyPropertyChanged-based pattern inside your model. The reason this interface was created was to base the observer pattern on actual property names as strings. This was pretty much a "one-way street", as XAML, the typical "design" language supporting WPF, is parsed in a "stringly" manner, leaving few efficient alternatives. In my humble opinion, there is almost no reason that you would want to force notifications throughout your model to be as weakly-typed (stringly-typed, in fact) as this scenario, so I would suggest avoiding INotifyPropertyChanged if you have a relatively voluminous Domain Model.
Messaging would probably be the way to go, maintaining strong-typing with message type registrations and whatnot, unless you would like to consider other alternatives, such as simple C# events, or even combine both. While at it, try to stick and adhere to hierarchy and encapsulation as strongly as possible but also as weakly as practical*.
(*I mean, if some of your Domain objects reach multiple nesting levels, then, occasionally, it may be more practical to bypass hierarchy and let, for example, grand-grandchildren send messages of their own, instead of notifying their parents' parents through events, and letting these parents' parents then send the corresponding notification messages. In typical OOP programming, compromises are constantly weighted against practicality and time availability).
I have (many more than, but restricting focus to) two class libraries for the model, and another library for view models.
One of the libraries is named Condenser, and has a class called WaterCooledCondenser, which inherits from the HeatExchanger class in the Subcomponents project. The condenser is business logic, but it was designed for the view model to interact with (it is part of the Model). When I create a new Condenser in the view model it says that HeatExchanger is not referenced, and to add a reference to Subcomponents... I don't think the view model has any business knowing anything about the classes in that library, they are only meant to provide structure to the Model.
Would adding a reference to the class library violate MVVM? Is there another way around having the view model know anything about the structure of the model?
If these are third party libraries, you may be out of luck. But in general, I would say that your ViewModel should only know how to interact with Interfaces of another library. This way if the library changes implementation it should not beak if the interfaces are the same.
This being said, knowing the basic structure of the model is allowed in MVVM. However keeping the Business Logic and Models completely separate becomes harder when you know the specifics of your class. In order to prevent this interfaces are great tools in future proofing your code.
I would take what I say with a grain of salt; this is completely based on my experience in working within this design pattern.
I'm working on a WPF project using the MVVM pattern and I was wondering if I can improve the internal structure of my ViewModel by abstracting its exposed properties into separate classes.
It's common practice for VMs to contain lots of properties laying around in the same class: Some are used to retrieved user inputs, some are used to expose commands, others to expose the models, and probably some other properties for the view model's own business logic. Not to mention that these properties often have set and get bodies that adds some bulk to the package. This can quickly become messy inside a VM class and finding one's way there can become challenging.
As a way to solve this issue, I am exploring with my team the idea of grouping properties inside my VM into different categories. As a first approach, I chose to group them this way:
ViewData, UserInputs and Commands, each one represented by its own class. Then I referenced them as properties inside my VM class.
My intention is that these classes will only act as placeholders to free up the bloat in my VM and keep it clean and focused only on interaction logic for handling user events.
It's a simple refactoring, but I get the following pros:
Cleaner and readable VM.
Easier binding from the XAML because you know what the entry point is/should be.
Let me elaborate on the latter one: If I want to bind a text box to a property of my VM, I know the binding expression should start with Userinput.MyVMProperty. If I need to show a value from my VM, I know my binding's entry point is going to be ViewData.MyOtherVMProperty. Binding intellisense will also become better because when you know your entry point, the
suggestion list would be smaller and more focused. This also works the other way around: when reading through your XAML controls, any binding that starts with UserInput necessarily means it's a a control that should send data back to the VM.
The only cons I can find is that this will require creating extra classes for each VM, but I believe it's a fair price to pay for the benefits you get.
Take note that the grouping I suggested may not be the best, but I don't mind any other grouping as long as it solves the problem with bulky VMs.
So, has any one ever tried a similar pattern? Do you think this is a good idea/practice? What other good practices I can use to improve my VMs?
Bonus question: One developer in my team who seemed to agree with this idea, suggested to go the extra mile and consider the grouped classes as VM dependencies and that they need to be injected inside the VM. What do you think about this?
So for every ViewModel you need to create own inner classes for every group. You cannot use Interfaces because ViewModels have different properties and commands
Then did you considered that every "groupclass" must to "know" about other groups for ViewModel will work properly.
In my opinion Class should be solid logical structure with minimal outside dependency.
Based on the pros you trying to achieve I can suggest another approach without changing structure of the ViewModel classes
Readability can be achieved partly by #regions.
Or use Partial class for separating different groups in the different files,
while keeping them inside one logical structure
Intellisense can be improved by naming conveniences - using prefix based on group property belong to. For example UserInputMyName, ViewDataFullName or CommandDelete
I've never used INotifyPropertyChanged, and I'm considering using it widely throughout a new application.
My question is, is it 'proper' to use INotifyPropertyChanged interface in order to provide event notifications for things other than databound controls?
It seems from a bunch of examples online that this interface is widely used for notifying grids and such for when data is changed. I have various scenario's where I need other classes to be notified of data changes in other classes, and I was wondering if you think it's cleaner to implement this interface, and perform the changed call on setters, or rather just create regular events.
When making a choice like this, I lean towards using language features over other constructs.
A severe downside to INotifyPropertyChanged is that it only provides the property name as a string on update, and your consuming classes have to parse that string and decide how to act on it.
With events you can provide any kind of delegate signature that the event requires and the consuming classes can act on that change directly.
If you peek under the hood, you'll find that INotifyPropertyChanged is an event anyway, so why not use events directly?
I think you can use this Interface for those scenarios but you have to really think hard about if you want this thight coupeling between your classes.
If this makes sense to you - sure, why reinvent the wheel?
I think you should go ahead an implement the INotifyPropertyChanged interface, just because it's there for that purpose and its what the UI uses to pickup changes, there's no need to create custom events yourself.
WPF and Silverlight both use INotifyPropertyChanged extensively in the data binding system. If your are going to databind to your objects, you should definetely use INotifyPropertyChanged. |
Otherwise, as far as I know, it does not influence .NET Framework technologies.
INotifyPropertyChanged is not the cleanest way of notifying when your property changes, depending on how you look at it, since there is one event and a string with the propertyname, you will have to make a switch statement. It sure is easier to implement comparing to events per property though
I would not use INotifyPropertyChanged for anything except databinding. This interface is probably the only option for databinding because controls which will act on PropertyChanged event do not know sender's type in advance. Because of that databinding has to use such a generic interface.
For my own types and scenarios I would use regular events (one event per each property which can change its value). INotifyPropertyChanged in such scenarios is kind of stringly typed code. You can see that even WPF itself is still full of oldscool events (FrameworkElement for example with a lot of ***Changed events).
Dont use is in other scenarios, if you need to notify other domain classes use domain events instead, which would be more business oriented and descriptive and strongly typed
I am not a fan of INPC outside of the UI realms as it hides the fact that significant events are being generated by instances of the object. Also, if I use your class implementing INPC, I will expect all properties to broadcast notifications, if only some of them do, that's a bug at runtime that can go unnoticed.
In C#:
I have a data class that is shared amongst several gui classes. I would like all of the gui classes that use it to be notified when some of the properties change, so they can keep the GUI up to date.
In a couple of the properties I have added delegates that the GUI classes can listen to for updates. This seems to work ok.
The problem I have is that more and more of the properties will require GUI notification. When that happens I will have to add more delegates. It also seems that this is adding an extra responsibility to the data class that it has to manage.
Is there some common pattern that I can use to monitor this class to extract this notification responsibility from the data class?
The common way of doing this is for the data class to implement INotifyPropertyChanged.
EDIT: If you have a lot of properties, this can lead to very repetitive code in the data class, and if you are binding to a UI, it might be best to use an AOP approach and intercept calls to the properties that you want to notify on. Most IoC containers have support for this sort of thing.
The pattern is called Observer. In .Net, events are one implementation of that pattern.
For the specific case of observing individual properties, the INotifyPropertyChanged interface should be used (as #Lee describes).
You don't say what GUI framework (WinForms, WPF) you are using, but there is the INotifyPropertyChanged interface. There is an How to guide on MSDN too.
You can just use the built-in System.EventHandler. That is a pretty standard pattern. You still need to define an event for each property that you want to monitor, but you don't need a separate delegate.
In Windows Forms there are several ways to notify GUI when some properties are chaged using Data Binding.
There are several types of Data binding in Windows Forms.
For simple data binding (data source with one object boud to one control) you can use INotifyPropertyChanged, or you can add events in this format: PropertyNameChanged for every property that you want update in GUI. And you should set Binding.ControlUpdateMode property to OnPropertyChanged.
For complex data binding (data source with many objects bound to control that can display many objects) you should use all from (1) and you should use BindingSource or BindingList or manually implement IBindingList;
For more information you should see this great books:
Windows Forms 2.0 Programming by Chris Sells
Data Binding with Windows Forms 2.0: Programming Smart Client Data Applications with .NET by Brian Noyes