Nested Views

Topics: Feature requests
Jun 29, 2012 at 1:16 AM

Hi, we recently struck an interesting issue.

We had already had a model, vm & view (Purchase) for an app.

Then we neede to add a new concept (PurchaseOrder) which contained another new concept (PurchaseOrderItem). The PurchaseOrderItem model contained a Purchase model.

No problems (we thought), we just created vms & views for the new models. The PurchaseOrderItem view just included the Purchase view (binding it to the Purchase model within the PurchaseOrderItem).

The PurchaseOrder view included a list of PurchaseOrderItems & a 'detail area' displaying the selected item (in a PurchaseOrderItem view, which contained a PurchaseView).

This is when we noticed problems.

If we edited one item in the list & selected another item before saving the changes, the edited item 'magically' reverted back to its 'original' state. Similar result when adding new items. IE we had to save the PurchaseOrder before adding another item.

Note: our models are complex objects (CSLA BusinessBase) which handle db interaction & distributed execution (eg WCF) issues.

After debugging this for a while we realised that each View was firing begin & cancel directly on the relevant models when the selected item was changed. In simple models this had not caused us any noticable issues.

We hav now 'fixed' the issue by using a 'standard' (ie non catel) UserControl to hold the UI objects. The views (Catel) now just include the usercontrol. IE no view includes another view.

EG, in our case we now have:

  • Purchase user control containing the actual UI objects
  • Purchase view (Catel) which contains the Purchase user control
  • PurchaseOrderItem view (Catel) which includes the Purchase user control

Any opinions?

Jun 29, 2012 at 7:49 AM

By default, then an item changes or a view unloads, Catel cancels the view model (and thus model) if a view model is not explicitly saved.

You can:

  1. Pass false to supportIEditableObject in the ViewModelBase constructor, then it will not handle IEditableObject
  2. Use on of the options on the UserControl to control the save state. 
Jun 29, 2012 at 9:28 PM

Hi,

We actually are happy with the ‘IEditableObject ‘features of the Catel controls (view). It makes features like delete / undelete easy to implement

In this scenario we are binding the ‘outer’ model (PurchaseOrderItem) to the detail view. The view automatically creates the appropriate vm.

It in turn is binding, ‘inner’ model (Purchase) to the ‘inner’ view. This view also automatically creates a vm from this model.

We don’t attempt to convert a list of models into a list of vms (ie we are using lazy construction).

The issue is that when the selected item in the list changes the data binding notifications result in ‘cancel edit’ being called on both vms (outer & inner) separately by Catel.

We are able to intercept the cancel edit call to the outer vm, & deal with it (we have a generic list mgr handling the binding stuff), but we can’t intercept the cancel edit call to the inner vm.

Unfortunately the app needs to allow users direct access to Purchase objects. Therefore just preventing IEditableObject features on this vm is not acceptable.

Now that we better understand the issue we will look further into what will work best for us. For now, our ‘don’t nest views’ solution appears to be a low cost fix.

I was also interested to know if anyone else has faced this issue.

Jul 2, 2012 at 6:30 PM

We have implemented events on the DataObjectBase for BeginEdit which allows you to cancel the BeginEdit call. We might just do the same for the CancelEventArgs.

Jul 2, 2012 at 6:52 PM

Implemented and committed. You can build the source yourself or wait until we release a new nightly build.

Jul 17, 2012 at 4:56 AM

Hi,

apologies for the late reply. I have been 'distracted' working on a large legacy system.

From our perspective, for this specific issue, it would be far more usefel to know when the CancelEdit call happens because it is this event that causes the issues I described. We don't want to cancel the BeginEdit (after all the object is actually being edited).

We want to deal with the (from our perspective) 'incorrect' cancelEdit event when a user selects another item in the list before having saved the current item. IE we are happy to allow changes to any item in the list & allow the user to later save (or not) the changes to all the 'dirty' list items in one operation.

Jul 18, 2012 at 7:43 AM

I also implemented the Cancel option on the CancelEditEventArgs. You can subscribe to this event and decide whether it is allowed to happen or not.