views:

65

answers:

3

I have a DataGrid. Right now it's binding to an ObservableCollection<Foo> in my model just great.

But now I want to implement a user-friendly way to add a new item to the datagrid. It seems like I'll need to modify Foo to inherit from IEditableObject and INotifyPropertyChanged, which is kind of icky from a MVVM perspective in my mind---those seem more like view-type implementation details. But whatever, not as big a deal.

(Edit: clarification; Foo is in my model, not viewmodel.)

But now I know I'm doing something wrong when I have to change my ObservableCollection<Foo> into a custom CollectionOfFoo with logic for adding blank Foo items to the end of the collection whenever the user commits a change, like in the referenced blog post. That stuff definitely doesn't belong in my model.

How can I implement such a nice UI for adding new items, while at the same time preserving my MVVM-ness? I was thinking maybe some kind of wrapper around my collection that implements this, but I'm not sure how to make that wrapper bind back to the model... :-S.

+2  A: 

That stuff definitely doesn't belong in my model.

But it definitely does belong in your viewmodel. And an observable collection of viewmodel classes is what your datagrid should be bound to.

It sounds to me like (if Foo is Model class) you need to write a FooViewModel class.

Another approach to this would be to add your "new" item in another control, maybe write a form and have it appear over the top of the datagrid whenever the user elects to create a new row?

Rob Fonseca-Ensor
I think this is what I was looking for. Right now my setup is View = XAML binds to ViewModel = code-behind property which returns Model = `ObservableCollection<Foo>`. Instead it sounds like I want to have ViewModel = code-behind property which returns a viewmodel field with all this logic, which is itself bound to Model = `List<Foo>` or `ObservableCollection<Foo>` (not sure yet... hints?)
Domenic
It's hard to answer this without seeing your actual situation/code, but let's say you've got a data layer / repository that has `IEnumerable<Foo> GetFoos()` and `void SaveFoos(IEnumerable<Foo> foos)`. In this case, you don't really need to put the Foos into a list, your viewmodel can just construct an ObservableCollection of FooViewModels when it's loading data, and then `Select(x=>x.Model)` the Models back out of the ViewModels when it comes time to save. But it really depends. Do whatever results in the least code - don't write pages of plumbing!
Rob Fonseca-Ensor
A: 

Doesn't it disturb you that ObservableCollection itself implements INotifyPropertyChanged?

Meaning - even if it were polluting ViewModel (which it isn't), it's too late to do anything about it.

ima
+1  A: 
  1. If you keep talking about how "icky" it is for your models to implement IPC, you're going to incur the wrath of the anemic model crowd.
  2. There's no reason why you can't have an ICommand in your VM to create a new Foo instance for editing.
Will
Of course, assuming you've shoe-horned ICommands into SL.
Will
Interesting link; indeed, I am never sure how much my model is supposed to be "portable" or not (i.e. should it be technology-agnostic, representing the abstract objects I'm modeling, or should it be tied to all this Silverlight stuff?) Maybe I should search SO for questions that might clarify this position.
Domenic
Do you really expect to be using your models in more than one type of application? I think we all sweat the little stuff way too much....
Will
I agree with will: be pragmatic. The one situation where I will stick to patterns resolutely is when they make unit testing easier / possible. Making your Model _too_ ignorant often means a lot of extra work for no actual gain.
Rob Fonseca-Ensor