Something that continues to confuse me about MVVM - if I use the view-first approach to constructing my objects (this appears to be the most common approach, at least after much reading and searching), how do I get contextual information into the viewmodel?
I've seen many answers to similar questions say "use the DI container to inject your model," but that doesn't help me here, so I'm going to provide a small example.
Let's say my application is a PeopleEditor. It's made to load and edit People objects, which are complex. When you load the application, you get a home screen that loads a bunch of People into memory - let's say that those are all made accessible via a collection that I can get to from my container. By clicking on a Person, you are taken to the editor screen. The editor is complex, so this is not a trivial master-detail view implemented in one screen.
So, on the home screen, when I click a person, the application needs to create a new view and viewmodel and show the view. If I create the viewmodel first, via the container or not, I can initialize it with the appropriate person object. This seems very natural to me, so I'm having a hard time figuring out why view-first seems to be the predominant pattern. How would I do this using the view-first approach? The view would create the viewmodel, which can get to the collection of People but doesn't know which person its editing. EDIT for clarity: Multiple People editors could exist at one time, each editing a different person.
The Prism 4.0 alpha's MVVM reference implementation uses a "state handler", which is basically a service that the app uses to store a constructor parameter in the container. It saves the state and calls ShowView, and the viewmodel that ultimately gets created imports a state object. This seems clunky to me - it's like it's trying to pretend it's loosely coupled when it's really not. Does anyone else have any other guidance?
To instantiate such basic viewmodel, create a ViewModelProvider with current activity/fragment reference and invoke get method with ViewModel's class.
You should call startActivity from activity, not from viewmodel. If you want to open it from viewmodel, you need to create livedata in viewmodel with some navigation parameter and observe on livedata inside the activity.
nlawalker,
I'm not expert but what i learn about View-First and Model-First is:
Don't mean to say Model-First approach is bad but, I prefer View-First approach because viewmodel can sits in code behind, so when some process require non-binding friendly task (PasswordBox, DialogConfirmation, ClosingForm etc), i can write my logic in code behind.
Anyway, To solve the case I usually used combination of IOC and Event Aggregator. Here it is:
Registering instance of viewmodel is not really necessary. it is only to make sure that viewmodel is ready when event dispatched by the previous viewmodel.
UPDATE
but then to populate it with any kind of local context I need to use a global facility to send it an event?
In your case, contextual object isn't local it is rather a message passed between object invocation. Obviously in your model-first approach you do:
//selectedPeople is contextual object
myPeopleDetailVM.LoadData(selectedPeople)
it will pretty much the same when you pass selectedPeople
to the argument of the event bus.
If you considering performance, than you can compare it with the WPF Routed Event System in this case Routing strategy is more complex than Event Bus and I think if you confident enough using WPF routed event than you should with Event Aggregator.
The only problem i see if you use built-in framework event aggregator (prism, mvvmlight), your viewmodel is polluted with event bus, if you complaining about this then i agree with you.
Hope that help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With