Description:
Scenario
There is a base persistent class MyBaseObject and several sub-classes inherited from it: MyFirstInheritedClass and MySecondInheritedClass.
There is also an unrelated MyAnotherClass defined in the data model.
Also consider that application end-users do not manipulate base class instances directly but instead, work with its descendants.
With that, it is often required to hide this base class from the New Action's list and leave only options for creating inherited items.
Answer:
There are several different solutions to accomplish this task and you can choose the most appropriate one for you or combine the approaches:
1. At the data model/business class level
1.1. Mark the base class as abstract (MustInherit in VB). Since an abstract class cannot be instantiated, XAF will not generate a New action item for it:
C#public abstract class MyBaseObject
Visual BasicPublic MustInherit Class MyBaseObject
1.2. Make your base class' constructor with the Session parameter non-public (e.g., protected or private):
C#protected MyBaseObject(Session session) : base(session) { }
Visual BasicProtected Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
Take special note that this approach is not available for Domain Components (DC), because interfaces do not provide constructors. Instead, for DC use the approaches from point #2.
2. At the Controller level
2.1. In your platform-agnostic XAF module project (e.g., YourSolutionName.Module), create a custom Controller and specify the mode for populating the New Action items list using the NewObjectViewController.NewObjectActionItemListMode property (you can set it to the LastDescendantsOnly or ExcludeBaseType values). You can change the mode globally using the NewObjectViewController.DefaultNewObjectActionItemListMode static field.
2.2. In your platform-agnostic XAF module project (e.g., YourSolutionName.Module), create a custom Controller and handle the CollectDescendantTypes and CollectCreatableItemTypes events of the NewObjectViewController class (responsible for managing the New Action). Ensure that you are calling the NewObjectViewController.UpdateNewObjectAction method after subscribing to these events as shown in the How to: Customize the New Action's Items List help article. You may find code examples in the T472989 article helpful for customizing the New Action inside a nested ListView.
2.3. In your platform-agnostic XAF module project (e.g., YourSolutionName.Module), create a custom Controller inherited from the ViewController class and manage its View.AllowNew property as required.
To learn more about these approaches, review the Customize Controllers and Actions help article.
3. At the Application Model level by modifying the CreatableItems node (this approach is suitable for limited scenarios only)
3.1. You can set the Application Model's IModelView.AllowNew property for the required Views | <ListView> or <DetailView> node to false.
3.2.* The IModelCreatableItems collection can be modified using the Model Editor or by setting CreatableItemAttribute for necessary business classes in code. Here is the first approach:
*Take special note that with this approach, however, it is not possible to disable the top-most item in the New Action menu. So, the solutions above are preferred in most cases.
See the the screenshot and description below for more details:
If the MyBaseObject's ListView is selected in the navigation control, the MyBaseObject item is visible in the New Action's items List (red ellipsis). However, if another item is selected in the navigation control, the base entity item is hidden in the bottom section of the New Action with the help of our CreatableItems node settings.
Search keywords: remove, hide, disable, exclude, base, super, parent, common, default, class, creation, create, New Action, NewObjectViewController, NewObjectAction, inherit, descendant, inheritance, inherited, user, role
What are the ways to hide MyFirstInheritedClass only?
Hello Evgeniy,
You can either remove public constructors (use protected ones) from your class (1.2) or create a WindowController class and handle the CollectDescendantTypes and CollectCreatableItemTypes events (2) to accomplish this task.
How it is possible with DC
Hello,
You can create a WindowController class and handle the CollectDescendantTypes and CollectCreatableItemTypes events (2) to accomplish this task.
Starting with version 16.2.5, there are several predefined modes for populating the New Action items list. These modes are listed in the DevExpress.ExpressApp.SystemModule.NewObjectActionItemListMode enumeration.
Default - the current type and all of its descendant types are added.
ExcludeBaseType - all descendants of the current type are added. The current type itself is excluded.
LastDescendantsOnly - only 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>(); if(controller != null) { controller.NewObjectActionItemListMode = NewObjectActionItemListMode.LastDescendantsOnly; } } }
See the New ways to customize the New Action's items list in XAF v16.2.5 blog post to learn more.
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>(); if(controller != null) { controller.NewObjectActionItemListMode = NewObjectActionItemListMode.LastDescendantsOnly; } } }
I tried to implement this in DC. But I am getting 'System.NullReferenceException: 'Object reference not set to an instance of an object.' '.What am I doing wrong? Thanks
Hello Mali,
I've created a separate ticket on your behalf (T653060: NewObjectActionItemListMode.LastDescendantsOnly causes NullReferenceException with DC). It has been placed in our processing queue and will be answered shortly.
"You can change the mode globally using the NewObjectViewController.DefaultNewObjectActionItemListMode static field"
Can you provide an example of how/where to do this?
Hi Jeff,
I generally set that kind of static settings in the
DevExpress.ExpressApp.Win.WinApplication.InitializeDefaultSettings
. In your XafApplication descendant, override InitializeDefaultSettings with something like this:protected override void InitializeDefaultSettings() { base.InitializeDefaultSettings(); NewObjectViewController.DefaultNewObjectActionItemListMode = NewObjectActionItemListMode.Default; }
Additionally if for whatever reason the static setting must be set earlier, I put those settings in the XafApplication descendant static constructor. Something like this:
public sealed class MyWinApplication : WinApplication { static MyWinApplication() { NewObjectViewController.DefaultNewObjectActionItemListMode = NewObjectActionItemListMode.Default; } }
HTH,
Alex