Search This Blog

Tuesday, March 14, 2017

New ways to customize the New Action's items list in XAF v16.2.5 - YOUR FEEDBACK IS NEEDED!!!

Changing the way how the New Action's items list is populated is quite an often task. The default behavior when the current types and all its descendants are added may be inappropriate in large XAF applications with a complex business objects inheritance hierarchy.



That is why we have decided to provide more built-in modes of populating this list. The available modes are listed in the DevExpress.ExpressApp.SystemModule.NewObjectActionItemListMode enumeration.

ValueDescription
DefaultThe current type and all of its descendant types are added.
ExcludeBaseTypeAll descendants of the current type are added. The current type itself is excluded.
LastDescendantsOnlyOnly the last types in the inheritance hierarchy of the current type are added.


You can change the mode globally using the NewObjectViewController.DefaultNewObjectActionItemListMode static field, or individually for each View using the NewObjectViewController.NewObjectActionItemListMode property.

using DevExpress.ExpressApp; using DevExpress.ExpressApp.SystemModule; using DevExpress.Persistent.BaseImpl;
// ...
public class CustomizeNewActionItemsListController : ObjectViewController<ObjectView, Task> {
    protected override void OnActivated() {
        base.OnActivated();
        NewObjectViewController controller = Frame.GetController<NewObjectViewController>();
        controller.NewObjectActionItemListMode = NewObjectActionItemListMode.LastDescendantsOnly;
    }
}

The NewObjectActionItemListMode value is ignored in case when there are no descendants of the current business object type. In the ExcludeBaseType and LastDescendantsOnly modes, the New Action may become inactive if it is impossible to instantiate any of the descendants (e.g., due to the Security System restrictions).

If none of the default modes meets your requirements, handle the NewObjectViewController.CollectDescendantTypes and NewObjectViewController.CollectCreatableItemTypes events and populate the list manually.

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.SystemModule;
using DevExpress.Persistent.BaseImpl;
// ...
public class CustomizeNewActionItemsListController : ObjectViewController<ObjectView, Task> {
    protected override void OnActivated() {
        base.OnActivated();
        NewObjectViewController controller = Frame.GetController<NewObjectViewController>();
        controller.CollectCreatableItemTypes += HideHCategoryViewController_CollectCreatableItemTypes;
        controller.CollectDescendantTypes += HideHCategoryViewController_CollectDescendantTypes;
        controller.UpdateNewObjectAction();
    }
    private void HideHCategoryViewController_CollectDescendantTypes(object sender, CollectTypesEventArgs e) {
        CustomizeList(e.Types);
    }
    private void HideHCategoryViewController_CollectCreatableItemTypes(object sender, CollectTypesEventArgs e) {
        CustomizeList(e.Types);
    }
    private void CustomizeList(ICollection<Type> types) {
        List<Type> unusableTypes = new List<Type>();
        foreach (Type item in types) {
            if (item == typeof(Task)) {
                unusableTypes.Add(item);
            }
        }
        foreach (Type item in unusableTypes) {
            types.Remove(item);
        }
    }
}

To try the demonstrated functionality, update to XAF version 16.2.5. Also, we will be happy to receive your feedback in comments to this post. Possibly, we have missed a certain popular scenario which can be added to the list of built-in modes.

8 comments:

  1. Hi Dennis, I've uploaded a screenshot to FB. From a recent customisation which I did, it'd be handy to be able to group as part of the population of items - perhaps even some mechanism for group captions. This would probably require wrapper classes to the types on the method signatures above though i.e. CollectTypesEventArgs.

    ReplyDelete
    Replies
    1. Thanks, Chris. Let's think about it. I am reposting a screenshot link here for everyone to see: https://www.facebook.com/photo.php?fbid=10154224461131813&set=p.10154224461131813&type=3&theater

      Delete
    2. Obviously, something like grouping/categorisation could also be introduced via class attributes / within the model. So, maybe injecting this at event level might not be the best design/solution. My example is also not a common usage I expect.

      Delete
    3. Chris, thank you for the feedback. We will certainly investigate the possibility of grouping the New Action items.

      Delete
  2. Chris, am I correct that you can currently achieve custom grouping you need using manual customizations of the NewObjectAction (e.g., using the ChoiceActionItem > BeginGroup option)?

    ReplyDelete
  3. Possibly Dennis, currently my controller is simply hooking CollectDescendantTypes and sorting the types by group, then alphabetically. The group is retrieved from an attribute on the class type. This is a low use form, so I didn't bother setting the BeginGroup values (I'm using a WindowController rather than sub-classing NewObjectViewController BTW).

    There could be that there's a better way to achieve this ...

    Having some control of grouping and sorting might be useful (model driven perhaps) e.g. group new items by module, and sort by e.g. order of class type in workflow.. SalesQuotation, SalesOrder, SalesInvoice, CreditNote etc

    My need in this respect is low, so take these simply as ideas, rather than requirements.

    ReplyDelete
    Replies
    1. Your solutions looks fine, though deriving the Controller would be more universal (to cover nested frames as well, e.g., in DashboardView - https://www.devexpress.com/Support/Center/Question/Details/T492042).
       
      Yes, I understand the priorities.

      Delete
    2. If by deriving you mean descending, then this is something we avoid doing (descending DX controllers). You only get one chance to descend a controller whereas you have multiple opportunities to subscribe to events.

      Delete