Kendo UI Mobile MVVM - How to handle two list views that navigate to a single detail view? - mvvm

I have two ListViews (in separate views). These views are bound to separate view-models but the ListViews contain the same entity type. Both views allow the user to select an item and navigate to it's detail/edit view.
What do I need to do to share this detail view between the two list views?
Here is what I have tried:
Assign the selected item to a property in the detail view's view-model
This initially appeared to work but actually breaks Kendo MVVM. Since the item is in the list view's view-model, assigning it to a property in another view-model causes problems.
Refresh data in each view's show event
While this almost works, it has a couple problems. 1) Getting fresh data all the time can be slow. 2) When saving changes in the detail view and navigating back to the list view, the save is async, so there is no guarantee that those changes will have been persisted before the call for ListView data. This also negates one of the benefits of MVVM and observables.
Share the view-model across views
The examples I have seen that have a list and detail view, have both views sharing a view-model with a selectedItem property. This is not possible in my particular case because I have two list views that navigate to the same detail view - not to mention that I prefer to have a separate view-model for each view so that the view-models don't become a huge mess. Am I supposed to have all views share a single view-model?
What am I missing?

Maybe you could extract the observable model to a plain object model with the toJSON() method, and then create a new observable model from it by wrapping it again. This should clear the existing bindings and avoids the conflicts you've found in your first approach.
var model = kendo.observable( otherModel.toJSON() );

Related

Reference master controller from detail controller

In the top of my detailcontroller I have a button to show a list of selected items from various options on the detail controller.
I want to initialize and keep the model, the popover and the list objects in the mastercontroller. How can I get a reference to my mastercontroller to reuse these objects?
Sharing data between views is easiest using a model tied to the component. If you make sure that everything that's selected in the master model is contained in that model, you will be able to use the data from the model in the detail view again.
Pulling data directly from another controller would go against the MVC paradigm and is not recommended (although not impossible, using e.g. the sap.ui.getCore().byId() method). I would not go there unless you have a clear view of the consequences.

Sharing a core data database between two instances of a table view controller

I'm making a shopping cart. In one tab, I have a table view controller with all the items. I have another tab, I have a shopping cart that has an 'add item to cart' button which segues to another table view controller whose class I set the same as the table view controller of the items in the other tab.
But the problem is, the one from the segue does not load the rows anymore, so I get a blank cells. How do I fix this?
Does my question have anything to do with passing NSManagedObjects among objects?
You have to be very careful passing ManagedObjects between threads. dispatch call is likely to do so. Instead, contain the processing to one thread per ManagedObjectContext. I prefer using a specific worker thread that main calls which then dispatches the messages asynchronously to private methods.
This may or may not be the cause of your particular problem, but I've had significant issues with Core Data working across threads that are likely to at the very least pop up later for you.

Clarification of MVVM - interactions between views

I'm using WPF and trying to program the MVVM way.
I understand how every view has its own view model and this works quite well. I am struggling to manage the interaction between views though.
Say I have two views, View1 and View2, each with its own ViewModel, ViewModel1 and ViewModel2. If I have a combobox on View1 and a button, what is the correct way to close the first view, notify the second view of the selection and show the second view once the button is pressed? It doesn't seem like it should go in the model because it's a UI thing. The ViewModel shouldn't know how to open and close WPF forms (or should it?) And the views shouldn't know about any other ViewModels (or should they?)
So how are these problems solved? In a nutshell:
1) How is data passed between views?
2) What manages the lifetime/visibility of views?
It will depend on whether you are doing view model or view first, and the exact implementation details will depend on if you are using an MVVM framework. If you aren't using a framework, then I would strongly recommend you start using one.
In your example, when the button is pressed, a method on ViewModel1 will be invoked. If doing view model first (which I would recommend), you would instantiate an instance of ViewModel2, and at this point you could pass in the combobox selection to the constructor of ViewModel2.
Depending on your framework, there will be different ways of then displaying the view associated with ViewModel2.
For 1) you can sychronize data through the DataModel. Provided each view shares the same instance of the DataModel and it implements INotifyPropertyChanged multiple views can be updated simulateneously.
Your sesond question is a matter of design, as #devdigital states it can depend on whether it is View first or ViewModel first. I would consider the introduction of a Controller class in much as the same way ASP.Net MVC works which controls which view is displayed. You can expose a ViewClosed event on the ViewModel which the controller can listen to and based on your workflow open another view.
You might consider introducing Controllers which are responsible for the lifetime management of the ViewModels. Furthermore, they mediate between the ViewModels.
The sample applications of the WPF Application Framework (WAF) show how these Controllers can be implemented.

Cancelling edits: NSUndoManager or separate NSManagedObjectContext for editing?

I have a View Controller that manages a view which is always shown in editing mode. The view is essentially a table view similar to that of a contact's details in Apple's Contacts app. The model underneath my view is represented by a 2-level object graph comprised of a root entity - call it R - having a to-many relationship to a child entity C. Now, R is a large object (it has 20+ attributes, all editable but non-mandatory). By default, R has n children (n being a configurable value), but child objects can be added and removed to/from R's collection via my editing view and C's attributes can be edited as well. Note that C entities include attributes for image meta-data, so there may be images picked and associated with the model while editing.
Edits on R and its children are performed via the main table view form, as well as from "secondary" views to which I navigate (back and forth) in order to collect the required information, depending on the case.
My question is, how would you implement a "Cancel all edits" in this situation, i.e. how should I isolate all my edits to easily revert to the state prior to editing? Using a NSUndoManager with my main NSManagedObjectContext? Having a separate NSManagedObjectContext for editing? What would be the trade-offs for each?
I don't care for redo. I am looking for an idea/solution that would strike a balance between the amount of memory used while editing vs. the ability to save the user's data if the app is interrupted while editing.
Thank you for all your ideas.
I would advise against a design that has the same edit function in two different views. Each view should represent objects of an different entity/class of the data model and should therefore have different editors and undo management.
The contact app shows how this is done. You can delete an entire contact in the master tableview and individual contact attributes in detail view. The changes in each view are committed when the view disappears. Such a setup not only makes undo management much easier but makes it much easier for the user to understand exactly what changes they are making.
If you want to stick to your original design, I would suggest keeping the undo stack of the master tableview until the master unloads completely i.e. not when the detail view loads.
I concluded here that for NSUndoManager to work properly with Core Data, it must be done in a child context. Since a child context gives you "Cancel all edits" capability, you don't also need NSUndoManager. Therefore, every cancel-able View Controller should do its work in a child context This means, for example, controller A would use a child of the document's context, and if it segues to controller B, that would use a child of A's context (child of child of document context). If the users presses Save, the context is saved which automatically propagates the changes up to the parent. If the users presses Cancel, the context is discarded thereby ignoring the changes. The only complication is with an iPad app where A and B might both be visible and the user presses Save on A (but this is probably just bad design).

ViewController design question for complex layout

I'm building my second app, and I'm trying to learn from the places I stubbed my toes on the first one.
Just as in the last app, I have sections of my app that feature a view with buttons along the bottom (basically a custom tab bar) that trigger the switching of the contents of the main, big area of the screen. One is a map view, one is a table view, one is a grid view, looking at the same objects in three different ways.
In my last app, I had each of the content options be a separate view, managed by separate ViewControllers. That worked, but there were places it was awkward. Passing data among those VCs was a little tricky (especially passing back upstream), and I was totally confused by my nested view controllers not having access to self.navigationController, for instance. It could be argued that I now know how to work with that scheme (and I do), but I'm interested in a Better Way.
I'm now thinking, maybe that whole thing should be ONE view controller, and it should have separate top-level UIView objects that it swaps in and out when the tabs at the bottom are clicked.
Problem is, two of my nested views have tables on them. So I'd need to either write REALLY complex UITableViewDelegate methods to figure out which table I'm talking about, or create separate UITableViewController subclasses to manage my table data. Either way, this just eliminated most of the simplicity I was hoping to achieve by keeping it all in one View Controller.
The other thing is, having those content views be UIViews inside the same view controller has some ramifications. There's no load time to swap views, but I'm burning memory I don't need to, if the user never visits one or more of those view alternatives.
Thoughts?
Problem is, two of my nested views have tables on them. So I'd need to either write REALLY complex UITableViewDelegate methods to figure out which table I'm talking about, or create separate UITableViewController subclasses to manage my table data.
A table view datasource/delegate does not need to be a view controller, it can be any object. So you could write two custom classes that acts as datasource/delegate for the table views.
The other thing is, having those content views be UIViews inside the same view controller has some ramifications. There's no load time to swap views, but I'm burning memory I don't need to, if the user never visits one or more of those view alternatives.
You should load the views lazily in that case, i.e. do not load anything before is is needed. And release stuff that is not needed at the moment when you receive a memory warning.