MVVM concept for collections and parent/child relationships - wpf

In the model of my application I have a list of "parents" each referecing a list of "children" (e.g. a list of footballteams each containing a list of players).
I visualize this list in a tree view. I created a viewmodel-class for the tree and a viewmodel-class for a footballteam (let's call it "footballteamViewModel"). The class for the tree holds an ObservableCollection with footballteamViewModel-items. The items-source for the tree is this ObservableCollection. During initialization, I create for every footballteam in the model a corresponding footballteamViewModel object and add it to the ObservableCollection.
The thing is, that the list of footballteams in my model can be changed from outside of the tree and I want the tree to be updated. So if someone removes a footballteam from my list in the model, I would have to remove the corresponding item in my ObservableCollection of footballteamViewModel-items.
I cannot bind the list of footballteams from the model directly to the view. So I have to update my ObservableCollection in the ViewModel somehow, every time the collection in the model is changed.
My way to handle this is to use an ObservableCollection in the model and register to the collectionChanged-event in the ViewModel, so that I update my ViewModel (the Observable Collection of footballteamViewModel objects) whenever the model-collection is changed. But this does not feel "right". Is there a better way?
While typing this I found another post which describes exactly the same problem: WPF/MVVM: Delegating a domain Model collection to a ViewModel. The answers there encourage me that the way I'm solving this problem is not totally wrong but still I wonder if there is another method.
EDIT: From the first answers that you provided I assume that there is no definite answer to my question. They were all helpful, so it's worth reading them all. I only mark the answer with the reference to the Bindable Linq/Continous Linq/Optics frameworks, because I think it will help other who stumble over my question most.

This is one of the more nasty spots of MVVM.
One thing I have done a while ago is create a ViewModelCollection<T> which inherits ObservableCollection<T> and has modificator methods (Add, Remove), that perform operations on both collections,like so:
public interface IViewModel<T>
{
T WrappedModel { get; }
}
public class ViewModelCollection<T,M> : ObservableCollection<T,M> where T : IViewModel<M>
{
private IList<M> _baseCollection;
public ViewModelCollection(IList<T> baseCollection)
{
_baseCollection = baseCollection;
}
public override void Add(T objectToAdd)
{
IViewModel<M> vm = objectToAdd as IViewModel<M>;
if (vm != null)
{
this.Add(objectToAdd);
_baseCollection.Add(vm.WrappedModel);
}
}
public override void Remove(T objectToRemove)
{
IViewModel<M> vm = objectToRemoveas IViewModel<M>;
if (vm != null)
{
this.Remove(objectToRemove);
_baseCollection.Remove(vm.WrappedModel);
}
}
}
By now I don't do this at all, I just work with Castle Proxies that add the INotifyPropertyChanged functionality to my models - saves a lot of boilerplate code!
Please note, I haven't tested the code, just typed it down from memory.

You said that you cannot bind the model collection directly to the view (which means that the viewmodel needs to make its own ObservableCollection with a copy of what the model collection contains), and additionally that the view needs to be updated live when the model collection changes (which means that the model needs to inform the viewmodel of such changes, and the viewmodel needs to update its internal copy).
All of this doesn't leave much wiggle room really. One variation that might be interesting is making the model's collection a read/write IEnumerable, in which case consumers of the model would be forced to swap it with a new instance whenever they need to modify the collection. In return, the viewmodel's "stay in sync" code can be simplified and sync can be triggered through INotifyPropertyChanged on the collection property.

Your solution is not wrong at all, but there are some libraries that could help you implement it easier, like BindableLinq, ContinuousLinq or Obtics. You have a discusion about them here. Sadly, none of them seem to be under further development.
My personal experience with Clinq is excellent and i still use it, should work for your case.

Late, but may helps other ppl...
read this excellent 3 Part blog post series about this topic.
Part 3 is about collections and shows some solutions - helps me a lot
MVVM: To Wrap or Not to Wrap? How much should the ViewModel wrap the Model?

Related

How should I expose a list from a ViewModel using reactive UI?

how should I expose a list from a ViewModel using reactive UI?
I want a grid in the view to bind to the list.
Should I use ObservableCollection or something in the reactiveUI framework?
public class BooksViewModel : ReactiveObject
{
ObservableCollection<Book> Books{ get; set; }
}
Thanks
You should use the ReactiveList class, which is everything ObservableCollection is, plus a lot of other cool stuff. If your list of books will never change once you create the initial list, you can use a simple IEnumerable<T>
Depends on your requirements.
Do you really need ReactiveObject to listen to events that you only care about?
If no, the use cases I can think of for you to listen is for simple Add, Edit, Delete, which ObservableCollection already provides by default. So just use ObservableCollection
But if you don't care in the built in changes that ObservableCollection provides and you only care about Subscribing to certain events that you want then I'll use ReactiveObject. Also, if I need other objects to do A when B is published.
Don't complicate your ViewModel too much in the beginning. Bring ReactiveUI when you see a use case where you really need it.

How do I structure MVVM with Collections?

I'm having trouble understanding how to apply the MVVM pattern when Lists/Collections are involved.
Say the MainModel has a few properties and methods, as well as a list that contains other DetailModel objects. The DetailModel objects can be added, removed, or re-ordered.
The MainView will show a few controls related the the root model, and have a ListBox populated from the list. Each item will have it's own sub-view via a DetailModelView UserControl.
Finally, there is a MainViewModel. This has properties backed by the MainModel's properties and methods, bound to the Main View, with change notification keeping everything in sync. (Up to this point, I am comfortable with the pattern - more stating this in case there is something fundamental I am missing...)
When it comes to handling the list, I get confused. I have come across several examples where the MainViewModel simply exposes the list of DetailModels to the view, and the DetailModelViews are bound directly to the models. This functions, but is problematic. It does not consistently following the pattern (no DetailViewModel exists), and it drives me to include some UI-related code in my detail models. It seems clear to me that the MainViewModel should expose a list of DetailViewModels for the UI to bind, but I am stuck on how to implement such a thing!
How should manage the two lists (DetailModels and DetailViewModels)? I am really confused as where I initially populate the DetailViewModel list, and how I should handle adding, removing, or changing the order of the items to keep them synchronized!
Usually Models are nothing more than data objects. They shouldn't contain any code to do things like add/remove items from a list. This is the ViewModel's job.
In your case, I would create a MainViewModel that has the following properties:
ObservableCollection<DetailViewModel> Details
ICommand AddDetailCommand
ICommand RemoveDetailCommand
If your MainModel class is a data object, you can either expose it, or it's properties from the MainViewModel as well. Exposing it's Properties is the "MVVM purist" approach, while exposing the entire Model is sometimes more practical.
Your MainViewModel is in charge of creating the initial list of DetailViewModels, and it is in charge of Adding/Removing these items as well. For example, in the PropertyChanged event for the MainViewModel.MainModel property, it might rebuild the MainViewModel.Details collection, and the CollectionChanged event for the MainViewModel.Details property would update MainViewModel.MainModel.Details
You are right to have a separate DetailModels list and DetailViewModels list. The DetailViewModels list should be a property of type ObservableCollection<DetailViewModel>. You can populate the observable list when you set the Model (or at construction time, if you pass the model into the constructor of your ViewModel.)
private ObservableCollection<DetailViewModel> m_details;
public IEnumerable<DetailViewModel> Details
{
get { return m_details; }
}
You can the subscribe to m_details.CollectionChanged. This is where you can handle re-ordering the contents of the list in the Model.
I hope this helps.
In my experience, the only time you get away with exposing model objects to the view is if you're doing simple read-only presentation, e.g. displaying a string property in a ComboBox. If there's any kind of actual UI involving the object (especially one involving two-way data binding), a view model is needed.
Typically, a master VM's constructor will look like this:
public MasterViewModel(MasterModel m)
{
_Model = m;
_Detail = new ObservableCollection<DetailViewModel>(m.Detail);
}
where MasterModel.Detail is a collection of DetailModel objects, and _Detail is a backing field for a Detail property that's exposed to the view.
As far as adding, removing, and reordering items in this list is concerned, in the UI at least this will be done through commands on the MasterViewModel, which must manipulate both MasterModel.Detail and MasterViewModel.Detail. That's a bit of a pain, but unless you want to repopulate MasterViewModel.Detail after every change to MasterModel.Detail, it's really unavoidable.
On the other hand, if you've been wondering "why would I ever need to write unit tests for view models?", now you know.
Here is an answer that I think addresses this issue very nicely using an ObservableViewModelCollection<TViewModel, TModel>
It's nice and lazy. It takes an ObservableCollection and a ViewModelFactory in the ctor. I like it because it keeps state at the model layer where it belongs. User operations on the GUI can invoke commands at the VM which manipulate the M via public methods on the M. Any resulting changes at the M layer will be automatically handled by the class in this link.
https://stackoverflow.com/q/2177659/456490
Note my comment regarding SL vs. WPF

MVVM and multi threading

Right, sticking with the MVVM focus for the minute, there are a small number of scenarios where threading may occur:
As usual, for simplicity we have a Model class, ViewModel class and View class.
The Model has a Collection and a string property.
1) User triggers long running background task. View triggers ViewModel. Can easily be managed by ViewModel using, for example, BackgroundWorker
2) Thread updates Model, ViewModel notified by Model of changes.
Previously we've discussed using INotifyChanged to notify changes from Model to ViewModel. The DependencyProperty system appears to marshal these to the correct thread for you.
For ObservableCollections this does not work. Therefore should my model's public face be single threaded (Don't like, why should the Model know about threads) or would I replicate some parts of the Model (For example the Collection above) in the ViewModel to ensure that amendments are made on the correct thread?
I think I've sort of answered my own question. Perhaps not. My Model does know about threads, so perhaps it's only polite to markshal them back using the IMarshalInvoker idea mooted earlier by Colin?
Some of my problem here is that I consider MVVM to be yet another MVC variant, and historically I've been happy to use terms like MVP, MP, MVC pretty much interchangeably because I knew what worked with the GUI technology (usually winforms) on the V end. When I say MVVM I'm specifically looking for practical advice on what works for WPF and WPF specific foibles. I hope that explains the nature of my questions and why I'm asking them.
I don't think it's a very good idea to go all-out and implement collections in your Model as ObservableCollection, as this is "polluting" your Model in a way that's only useful to WPF.
INotifyPropertyChanged is OK because:
There are many scenarios where having the ability to "listen in" is useful.
It can be utilized from pretty much any .NET code, not just WPF.
It doesn't give you any trouble if you want to serialize your Model.
So, I suggest to not have your model know about threads. Make your ViewModel know about threads, like this:
class Model {
List<Widget> Widgets { get; private set; }
}
class ModelViewModel {
ObservableCollection<Widget> Widgets { get; private set; }
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
}
}
If Widget is a reference type and implements INotifyPropertyChanged (which would be about 100% of the time), this gets you most of the way:
Changes to any widget will be made to model itself and will reflect upon bindings immediately
Updates to the collection will reflect upon bindings immediately
There's still the problem that updates to the collection (adding and removing items) will not be made to model directly. But that can be arranged:
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
this.Widgets.CollectionChanged += this.PropagateChangesToModel;
}
void PropagateChangesToModel(object sender, NotifyCollectionChangedEventArgs e) {
// do what the name says :)
}
Finally, you need to make ObservableCollection play well with being updated from a worker thread. This is a really common issue with WPF, and I refer you to the answer to this question for a solution: ObservableCollection and threading.

WPF/MVVM: Delegating a domain Model collection to a ViewModel

A domain model collection (normally a List or IEnumerable) is delegated to a ViewModel.
Thats means my CustomerViewModel has a order collection of type List or IEnumerable.
No change in the list is recognized by the bound control. But with ObservableCollection it is.
This is a problem in the MVVM design pattern.
How do you cope with it?
UPDATE: Sample of how I do it:
public class SchoolclassViewModel : ViewModelBase
{
private Schoolclass _schoolclass;
private ObservableCollection<PupilViewModel> _pupils = new ObservableCollection<PupilViewModel>();
public SchoolclassViewModel(Schoolclass schoolclass)
{
_schoolclass = schoolclass;
_schoolclass.Pupils = new List<Pupil>();
foreach (var p in schoolclass.Pupils)
Pupils.Add(new PupilViewModel(p));
}
public Schoolclass GetSchoolclass
{
get { return _schoolclass; }
}
public int ID { get; set; }
public string SchoolclassName
{
get { return _schoolclass.SchoolclassName;}
set
{
if(_schoolclass.SchoolclassName != value)
{
_schoolclass.SchoolclassName = value;
this.RaisePropertyChanged("SchoolclassName");
}
}
}
public ObservableCollection<PupilViewModel> Pupils
{
get{ return _pupils;}
set
{
_pupils = value;
this.RaisePropertyChanged("Pupils");
}
}
}
I deal with this by not doing it the way you describe.
If I need to present a Foo object and its related Bar objects in the view, the FooViewModel will generally implement a Bars property of type ObservableCollection<BarViewModel>.
Note that this is irrespective of whether or not the underlying Foo class has a Bars property of type IEnumerable<Bar>. The Foo class might not. The application might not even need to be able to iterate over all of the Bar objects for a Foo, except in the UI.
Edit
When my view is a simple representation of the application's object model, I pretty much do things as you do in your sample. The code in my constructor is generally a bit more compact:
_Bars = new ObservableCollection<BarViewModel>(
_Foo.Bars.Select(x => new BarViewModel(x)));
but it's essentially the same thing.
But this assumes that Foo actually exposes a Bars property. It might not. Or maybe only some Bar objects should appear in the view. Or maybe they should appear intermingled with other objects, and the FooViewModel should expose a CompositeCollection of some kind.
The point I'm making is that the view model is a model of the view. This doesn't necessarily have a direct correspondence to the underlying object model.
To pick a simple example: My program may give the user a way of putting items into five different categories by dragging and dropping them into five different ListBox controls. Ultimately, doing this sets a Category property on the Item object. My view model is going to have a collection of CategoryViewModel objects, each with a property of type ObservableCollection<ItemViewModel>, so that dragging items back and forth between collections is simple to implement.
The thing is, there may not even be a Category class in the application's object model, let alone a collection of Category objects. Item.Category might just be a property of type string. The CategoryViewModel isn't mirroring the application's object model. It only exists to support the view in the UI.
Ok, I'll go ahead and add my thoughts as an answer instead of in the comments. :)
I think the bottom line is that this is just the reality of the way WPF and databinding work. In order for two-way databinding to operate, collections need a means of notifying controls that are bound to them, and the standard lists and collections used in most domain objects don't/won't/shouldn't support this. As I mentioned in a comment, being required to implement INotifyPropertyChanged for non-collection properties is another requirement that may not be met by a standard domain object.
Domain objects are not intended to to be viewmodels, and for this reason you may find that you need to map back and forth between the two types of objects. This is not dissimilar to having to map back and forth between domain objects and data access objects. Each type of object has a different function in the system, and each should be specifically designed to support their own role in the system.
All that said, Agies's idea of using AOP to automatically generate proxy classes is very interesting, and something I intend to look into.
What I do is instead of using ObservableCollection in my domain model is use my own collection type that implements the INotifyCollectionChanged interface amongst other useful standard and custom interfaces. My way of thinking is that much like Rockford Lhotka suggests in his book that change notification is useful in to more than just a presentation layer since other business objects within the domain layer often need some sort of notification when state changes in another object.
With this methodology you could create your own collection type that still has the benefits of change notification and as well as what ever custom behaviors you need. The base class for your collection could be implemented as purely infrastructure code and then a subclass could be created that could contain business logic using the subtype layering techinque used in this book. So in the end you could have a collection that can wrap types of IEnumerable<> and provide the change notification stuff your looking for as well for both your domain model and presentation code.

WPF Collections and Databinding

I am new to WPF and trying to wrap my head around WPF's framework, what it does and does not do for you.
To clarify this, I would like to know what is the difference between this:
public List<MyCustomObject> MyCustomObjects
{
get { return (List<MyCustomObject>)GetValue(MyCustomObjectsProperty); }
set { SetValue(MyCustomObjectsProperty, value); }
}
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
and this:
public ObservableCollection<MyCustomObject> MyCustomObjects { get; set; }
public Main ()
{
MyCustomObjects = new ObservableCollection<<MyCustomObject>();
}
Ok, we must put some order into things, there's a few concepts mixed in together here.
First of all, you're asking what the difference is between a field-backed property and a dependency property. Google would be your best friend, however I recommend this blog post by WPF's vanguard Josh Smith: Overview of dependency properties in WPF
In short: dependency properties support the richness that is WPF: Styling, animation, binding, metadata, and more.
Secondly, you're asking what the difference is between a List and an ObservableCollection. Well the latter provides change notifications (in the forms of events) on any change to the collection (addition, removal, change of order, clearing, etc.), and the former does not. You can read more about that here: The ObservableCollection Class
In short: ObservableCollection provides change notifications which are required for the UI to automatically reflect changes in the view model.
In addition to Aviad and Reed's answers, I would like to point out a serious bug in your first code sample :
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
The new List<MyCustomObject>() used as the default value will be created only once, so by default all instances of your type will share the same List<MyCustomObject> instance, which is probably not what you want... The only sensible default value here is null
In the first case, you're setting up a Dependency Property containing a List<T> instance.
In the second, you're making a normal CLR property, but having it setup as an ObservableCollection<T>.
For WPF Data Binding, there are some differences here.
Typically, you want all of your properties in the DataContext (which is the object that, by default, things "bind" to) to either implement INotifyPropertyChanged or to be a Dependency Property. This lets the binding framework know when changes are made to that object. Normally, though, you'd only use a Dependency Property if your working with a custom control - it's usually a better idea to have your object to which your data bound be a separate class, assigned to the DataContext. (For details here, see Josh Smith on MVVM or my recent detailed post on MVVM...)
However, with a collection, you typically also want the binding system to know when the items within the collection change (ie: an item is added). ObservableCollection<T> handles this by implementing INotifyCollectionChanged.
By using the second approach (using an ObservableCollection<T>), your UI can tell when items were added or removed from the collection - not just when a new collection is assigned. This lets things work automatically, like a ListBox adding elements when a new item is added to your collection.
1:
You're using a dependency property to "tell" the framework when that property is changed. This will have the following consequences for your binding:
MyCustomObjects.Add(new MyCustomObject()); //Wont update the view through databinding
MyCustomObjects = new List<MyCustomObject>(); //Will update the view through databinding
You could gain the same databinding functionality by implementing INotifyPropertyChanged on which ever class exposes the property, but dependency properties a capable of much more than just notifying about changes. These are rather advanced features though, which you aren't likely to come across in your average joe app :)
2:
You're using an observable collection, which implements INotifyCollectionChanged for you, to tell the databinding whenever the content of the collection has changed. This will have the opposite consequences than #1:
MyCustomObjects.Add(new MyCustomObject()); //Will update the view through databinding
MyCustomObjects = new ObservableCollection<MyCustomObject>(); //Won't update the view through databinding

Resources