Anywhere transition to a new view after returning from a different view - maximo-anywhere

We have a weird customization in Work Execution where we need 3 levels of one to many from work order (Hierarchy is Work Order->Custom Checklist Object (they review before starting work on a work order)->Custom Hazard Object->Custom Precaution Object). Each of these objects have three views (a list, a detail view, and a creation view).
Right now, when a user creates a hazard it returns to the checklist object. We want to open the detail view of the hazard so someone can easily modify the precautions that were added or add new ones (instead of having to go from the new checklist object->hazard list->hazard detail). Having the precautions editable directly on the add hazard screen causes a bunch of other issues so it's best to force the user to create a hazard before allowing them to add precautions.
On the create button in the New Hazard view we can add a click event and use eventContext.ui.show("ViewName") and display our hazard detail view (which works). The problem is when they save the hazard detail view, the this.ui.hideCurrentView() closes the Hazard Detail View and returns back to the Add New Hazard view since that was the last view displayed. We've also learned that if someone uses the back button in the hazard detail view it causes the hazard to be deleted (instead of just discarding the changes they made in the hazard detail view).
What we really want is when the user clicks the create hazard button, that it returns to the new checklist object view and then based on a flag that we've set on the object (to determine that a new hazard was added) open the hazard detail view. We've tried render & show event handler events on the new checklist view and on buttons and textboxes in the view and our code fires but it seems like because it's in the process of transitioning from the add hazard view to the add checklist view that it won't allow new UI transitions.
Is there a way for us to essentially inject that the hazard detail view should be what we return to from the add hazard view? Perhaps by modifying the viewHistory in the UserInterface?

You can probably dynamically modify the view stack, to remove the Add New Hazard view from the stack. If you look at some of our platform code you can see how to do that. A little bit of sample code..
var viewHistory = eventContext.ui.viewHistory;
var previousView = viewHistory[viewHistory.length-2];
Lemme know if this usecase comes up more often, we maybe should formalize this API for you.
UPDATE: in 7.6 we do have this method for you, UserInterface.returnToView(viewId)

Related

Avoiding duplicate data & calculations in view-models

I'm working on a Flex application that uses MVVM. I understand that it's recommended to have a 1-to-1 mapping between views and view-models. How then do I avoid performing the same calculations and storing the same data multiple times if it is needed in multiple views?
For example, imagine I have a program that can load project files consisting of a list of items. The main tab of my application has an export button that should only be enabled if the project is valid so I create an isExportEnabled property on the view-model for the main tab. The calculation for this involves validating the project by iterating though every item in the project and verifying some attribute on each. I have another tab which has a "Print Project Summary" button so the view-model for this tab has isPrintEnabled. The value for this flag is based on the same criteria, whether or not the project is valid.
I could put the logic for determining these values in their respective view-models, but then I end up calculating the same value twice when a project is loaded.
I could move isValid to the domain model but then the model becomes denormalized. What if a saved project is edited without updating the "isValid" flag?
I could make a global "Project View-Model" for the entire project which calculates whether the project is valid and then have isExportEnabled and isPrintEnabled delegate to that. However, then I end up with a hierarchy of view-models which this article recommends avoiding: Applying the Presentation Model in Flex
It feels like there is no correct way to do this.
So you are saying you have two user gestures, "Export" and "Print Project Summary" which are based on the same validation function ? If I read your post right then you can calculate it once and have two getters
private var _isValid:Boolean;
public function validate():Boolean
{
_isValid = //result of calculation
dispatchEvent( new Event("isValidChange") )
}
[Bindable(Event="isValidChange")]
public function get canExport():Boolean
{
return _isValid;
}
[Bindable(Event="isValidChange")]
public function get canPrint():Boolean
{
return _isValid;
}
Now some may say that since they are returning the same value that we should get rid of the getters and return a simple [Bindable] public value. But since this seems like the first implementation of this feature, having two separate functions allows you some robustness in the face of changing UI and validation requirements.
Personally, if the validation logic got too heavy, I would keep that value on my model "public var isValidProject" since the model should know if it is valid or not. Then the presentation layer would use that value to determine how to represent to the user that this is an invalid project (popups,alerts,error strings ).
In other cases, I would make a setter on the presenter of those buttons "set selectedProject" and run my validation and/or change my buttons enablement state there.
I would really be interested to hear others thoughts on this.

Flex, filter tree using ITreeDataDescriptor without reload and close all nodes

working with flex 4 and implementing filtering using ITreeDataDescriptor.
Filtering worked as expected like the following code snippet
however, i am trying to create a on-demand type of filter where user would type in the search clause in a TextInput, and as the user types, the tree nodes would be filtered on the fly.
my implementation now is have user click on the search button and then reapply the dataDescriptor then reload the data. A big problem is that the whole tree collapses after setting the dataProvider again.
any suggestion on how the on-demand filter can be achieved?
var dataFilter:ServicePricingFilter = new MyFilter();
dataFilter.searchString = this.txtSearchKeyword.text;
this.treeService.dataDescriptor = new MyDataDescriptor(dataFilter);
this.treeService.dataProvider = getTreeData();
I think you shouldn't set the dataprovider every time but use insted the filterFunction property available for ListCollectionView classes (ArrayCollection, XMLListCollection,...)
looked at the post Florian mentioned.
on-demand filtering is done by using ITreeDataDescriptor and a filterFunction.
on keyup event of the search TextInput, call invalidateList() function on the tree.
see the source code provided for the following post
http://www.davidarno.org/2009/04/01/how-to-filter-all-nodes-of-a-flex-tree-component/

ASP MVC multi-view form models

I am pretty new to this stuff but I am running into a concept-wall and I keep going back and forth with the best way to handle the problem.
I have a multi-view process to filling out a "New User Form". Each view has a small part of the entire form. In each view I have a model and the model has properties set to an instance of a LINQ to SQL class (for pre-populating) along with dropdown data (state, country). I also thought I should have a model (value object) that represents the entire form. This value object has properties for each LINQ class as well. So I made the view take the value object as a dependency injection. Then what? Just set a property to ViewData to send in multiple models? Seems like a bad idea since I would have to do that to every view. Should all view models come from a base class with the value object?
I might be way off already. Hopefully someone can help me get back on track. The ultimate goal is to have an object that represents the state/data of a form that spans multiple views and the form fields should populate if data is present.
Thanks for your patience!
Okay, so I am going to try to answer my own question but I am still not sure about things. I am going to use the info I got here: http://www.asp.net/Learn/mvc/tutorial-13-cs.aspx to create an instance of the value object that will be available to every view. Then I am sending the instance (or a property of) into the view model through it's constructor.
I am still working on how to keep the instance of the value object through all pages but I am assuming it will have to be done through a session variable of sorts.

DataGrid crash on CompositeCollection Edit

I have a DataGrid.
It's ItemsSource is bound to the ModelView's CompositeCollection through the ViewModel.
The CompositeCollection consists of 2 ObservableCollections.
The display on the grid is fine. I am able to see the collection.
However, when I try to edit one of the rows, I get a crash (NotSupportedException) of:
"'EditItem' is not allowed for this view"
How do I make the rows editable? I need to be able to edit the ModelViews representing each row in the Grid.
Here is the CompositeCollection Property code that I use to bind to the itemssource:
this isn't the exact code since I am not allowed to post the exact code but it is the same logic on how I make the collection
public CompositeCollection ModelViewsCollection
{
get
{
CollectionContainer modelViewContainer;
CompositeCollection modelViewCollection = new CompositeCollection();
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection;
modelViewCollection .Add(modelViewContainer);
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection2;
modelViewCollection .Add(modelViewContainer);
return modelViewCollection;
}
}
CompositeCollection does not implement IEditableCollectionView which is used by the datagrid to edit.
I have had the same issues, and ended up doing my own fake composite collection on the view model, similiar to what you have, if all you are putting in your collection is two observable collections, its not to hard to track the changes listening to collection changed on both of them. and make your viewmodels collection consist of both of them
You could even do the dirty hack that i did, of rebuilding the ObservableCollection that the grid binds to every time one of the collections change (not elegant i know, but ill go back and optimise when i get time.. i.e. never) With a linq query this stuff is really easy.
Otherwise maybe you could derive from CompositeCollection and try and add the IEditableCollectionView, if you get that working be sure to let me know.
here is the same question on the datagrid forum

XtraGrid doesn't display properly newly added line

I'm using XtraGrid of DevExpress 2.9.5 to display a blotter of dynamic set of lines. The blotter is integrated into another application, this is why it has to be based on UserControl class and also implement a couple of custom interfaces.
public partial class BlotterForm : UserControl, ISMMdiEmbeddable, ISMAssociatedMFCWindow
{
private BindingList<BlotterTrade> fDeals;
....
}
As the data is binded to control using BindedList, any change should be reflected in the form automatically. And if I try to add new line to fDeals like follows:
public void AddDeal()
{
fDeals.Add(new BlotterTrade(1,2,3));
}
... i can see the line, but it's content is rubbish.
I tried to do the same in a small test application. It works ok with only difference that the blotter in test application is based on DevExpress.XtraEditors.XtraForm. To me it looks now that the form of original blotter doesn't overload some method or miss some event. But I cannot find out what exactly is missed.
Can somebody tell me what I do wrong or don't do?
Thanks.
A couple of things:
BindingList doesn't always work too well with DevExpress, and it's suggested to use XPCollection instead.
Do you have any more info about how you setup your columns in the xtragrid? If you use incorrect field names in the column, then they won't show what you're looking for.
If the params you're using (1, 2, 3) are ids stored as fkeys to other objects (not sure if you're using xpo or not) then they won't show up correctly either (there'll likely be a '+' in the cell instead of any values).
[aside] be sure that blottertrade implements INotifyPropertyChanged for better interaction with the grid.
Thanks to everybody for the answers and comments. I think I sorted out the problem. It was actually related to interaction between native C++ and C# layers in my application. The object that was supposed to be displayed in XtraGrid was created in C++ layer, the grid was displayed asynchronously with object construction/deconstruction, that's why at the moment when the grid was ready to display it, the object itself didn't exist. Hence the rubbish. It's good the grid itself was not crashing or firing exceptions.

Resources