KB Article Q332740
Visible to All Users

NewObjectViewController - How to hide the New Action from the main menu, but still have it available inline as the New Item Row feature of ListEditor

Blazor

To accomplish this task, use the following controller:

C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.Blazor.SystemModule; using DevExpress.ExpressApp.SystemModule; using dxTestSolution.Module.BusinessObjects; namespace dxTestSolution.Blazor.Server.Controllers; public class CustomBlazorController2 :ObjectViewController<ListView, MyTask> { BlazorNewObjectViewController _BlazorNewObjectViewController; NewItemRowListViewController _NewItemRowListViewController; protected override void OnActivated() { base.OnActivated(); _BlazorNewObjectViewController = Frame.GetController<BlazorNewObjectViewController>(); _NewItemRowListViewController = Frame.GetController<NewItemRowListViewController>(); if(_BlazorNewObjectViewController != null) { _BlazorNewObjectViewController.NewObjectAction.Active["test"] = false; } if(_NewItemRowListViewController != null) { _NewItemRowListViewController.CustomCalculateNewItemRowPosition += Cnt2_CustomCalculateNewItemRowPosition; } } private void Cnt2_CustomCalculateNewItemRowPosition(object sender, CustomCalculateNewItemRowPositionEventArgs e) { e.NewItemRowPosition = NewItemRowPosition.Top; } protected override void OnDeactivated() { base.OnDeactivated(); if(_BlazorNewObjectViewController != null) { _BlazorNewObjectViewController.NewObjectAction.Active.RemoveItem("test"); } if(_NewItemRowListViewController != null) { _NewItemRowListViewController.CustomCalculateNewItemRowPosition -= Cnt2_CustomCalculateNewItemRowPosition; } } }

ASP.NET WebForms

By default, when the New action is deactivated or disabled, the New Item Row feature is disabled as well. This is logical, because the New Action may be deactivated due to security reasons as well.
To prevent the default behavior or keep the capability to create new records directly in XAF List Editors without the New Action in the main menu, consider one of the two totally different strategies.

1. Deactivating the New Action and overriding the dependent ListEditor behavior.
1.1.  Deactivate required Actions in the main menu:

C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.SystemModule; using DevExpress.ExpressApp.Web.SystemModule; using MainDemo.Module.BusinessObjects; namespace MainDemo.Module.Web.Controllers { public class MyViewController : ObjectViewController<ListView, Contact> { private const string UnavailableForContactActiveKey = "UnavailableForContact"; private NewObjectViewController newController = null; private ListViewController webListViewController = null; protected override void OnActivated() { base.OnActivated(); newController = Frame.GetController<NewObjectViewController>(); if(newController != null) { newController.NewObjectAction.Active.SetItemValue(UnavailableForContactActiveKey, false); } webListViewController = Frame.GetController<ListViewController>(); if(webListViewController != null) { webListViewController.EditAction.Active.SetItemValue(UnavailableForContactActiveKey, false); } } protected override void OnDeactivated() { base.OnDeactivated(); if(newController != null) { newController.NewObjectAction.Active.RemoveItem(UnavailableForContactActiveKey); } if(webListViewController != null) { webListViewController.EditAction.Active.RemoveItem(UnavailableForContactActiveKey); } } } }

Refer to the Task-Based Help > How to: Deactivate (Hide) an Action in Code  article for more details.

1.2.  Subscribe to the NewItemRowListViewController.CustomCalculateNewItemRowPosition event or override the NewItemRowListViewController.CalculateNewItemRowPosition method to control the New Item Row feature availability manually:

C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.SystemModule; namespace MainDemo.Module.Controllers { public class MyNewItemRowListViewController : NewItemRowListViewController { protected override NewItemRowPosition CalculateNewItemRowPosition() { NewItemRowPosition result = NewItemRowPosition.None; if(View.Model != null && View.AllowEdit && View.AllowNew) { result = ((IModelListViewNewItemRow)View.Model).NewItemRowPosition; } return result; } } }

If you are inheriting from a system Controller, do NOT specify the TargetViewId, TargetObjectType and TargetViewNesting properties, and check the View.Id, View.ObjectType, View.IsRoot and other suitable conditions in the CalculateNewItemRowPosition method.  Refer to the Customize Controllers and Actions topic to learn how to handle controllers' events and override their methods.
Since you are ignoring the NewObjectViewController.NewObjectAction.Active/Enabled state completely, you may want to additionally check for security permissions and other things manually (see the UpdateActionState method of the NewObjectViewController class from our sources for more details).

2. Hiding the New Action control in nested views without Action deactivation.

C#
using System.ComponentModel; using DevExpress.ExpressApp; using DevExpress.ExpressApp.SystemModule; using DevExpress.ExpressApp.Templates.ActionControls; namespace MainDemo.Module.Controllers { public class HideNewActionWithoutDeactivationViewController : ViewController { private ActionControlsSiteController actionControlsSiteController = null; private FillActionContainersController fillActionsController = null; public HideNewActionWithoutDeactivationViewController() { TargetViewId = "Contact_Tasks_ListView"; } protected override void OnActivated() { base.OnActivated(); actionControlsSiteController = Frame.GetController<ActionControlsSiteController>(); if(actionControlsSiteController != null) { actionControlsSiteController.CustomAddActionControlToContainer += ActionControlsSiteController_CustomAddActionControlToContainer; } fillActionsController = Frame.GetController<FillActionContainersController>(); if(fillActionsController != null) { fillActionsController.CustomRegisterActionInContainer += FillActionsController_CustomRegisterActionInContainer; } } private void DisableActionControlCreation(HandledEventArgs args, string actionId) { if(actionId == NewObjectViewController.NewActionId) { args.Handled = true; } } private void FillActionsController_CustomRegisterActionInContainer(object sender, CustomRegisterActionInContainerEventArgs e) { DisableActionControlCreation(e, e.Action.Id); } private void ActionControlsSiteController_CustomAddActionControlToContainer(object sender, CustomAddActionControlEventArgs e) { DisableActionControlCreation(e, e.Action.Id); } protected override void OnDeactivated() { if(actionControlsSiteController != null) { actionControlsSiteController.CustomAddActionControlToContainer -= ActionControlsSiteController_CustomAddActionControlToContainer; } if(fillActionsController != null) { fillActionsController.CustomRegisterActionInContainer -= FillActionsController_CustomRegisterActionInContainer; } base.OnDeactivated(); } } }

Events used in this approach are raised when the current Frame is initialized. If this Frame is a Window, the View that is about to be displayed is unknown. So, this approach cannot be used to hide the New action only in a particular root View. However, the View ID is available in nested Frames at this moment. So, this approach is suitable if you need to hide the New action in a nested ListView shown for an associated collection. For instance, in the code example, customization is applied to the Tasks ListView from the Contact DetailView (Contact_Tasks_ListView).

Finally, there is another, but yet more complicated strategy with deactivating the Action and overriding the ListEditor behavior in a more tricky way, where the custom Active key, e.g., "UnavailableForContact", is excluded from processing, but we would like to refrain from sharing this code due to its size and complexity.

Show previous comments (3)
Anatol (DevExpress) 6 years ago

    In the NewObjectViewController.UpdateActionState method from our sources, you can see how our internal DataManipulationRight.IsAddToCollectionAllowed and DataManipulationRight.CanEdit methods are used to evaluate security permissions. Alternatively, you can use a more documented SecuritySystem.IsGranted method, as shown in the Access the Security System in Code topic.

      Running into the same issue with XAF v24.1.5 in Blazor. The controller shown above removes both the 'New' button as well as the in-line '+' button.

      I wish there was an option to set a List View to ONLY edit in-line or only edit in a tab. If it's in-line, show the '+' button, if it's tab, show the 'New' button. Also, setting in-line editing would disable opening a tab when clicking on a row.

      It's not a good user experience to have a mixture of those two edit behaviors in one list view. I can see scenarios where the tab makes a lot of sense, but for example for the one below, the user only manipulates two fields (Last Updated On and Last Updated By are set by EF automatically) and showing a new tab for that makes no sense.

      Clipboard-File-1.png

      Andrey K (DevExpress Support) 5 months ago

        Hello,

        I created a separate ticket on your behalf: T1254296: How to hide the New Action from the main menu, but still have it available inline as the New Item Row feature. We placed it in our processing queue and will process it shortly.

        Thanks,
        Andrey

        Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

        Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.