Is there a way to allow for a property to be visible in the report designer but not browseable (cannot be added to a list view or detail view)
XAF - How to hide a property/field from the layout customization form (DetailView), grid's Column Chooser (ListView), and Object Model dialog tree
Answers approved by DevExpress Support
Hello,
XAF v24.2 includes a new HideInUI attribute for use within business classes. This is a simple declarative way to hide fields from ListView and DetailView, their customization forms and many other UI contexts such as the Field List of the Filter, Report and Dashboard Editor/Designer. You no longer need manual Controller-based solutions or multiple non-flexible VisibleInXXX and Browsable attributes.
We also unified ways to disable runtime layout customization completely - you can now use 2 CustomizationFormEnabled options (global and View-specific) instead of the former 4 options.
Refer to the following breaking change article for more information: EnableColumnChooser and CustomizationEnabled options are replaced by a common cross-plarform option CustomizationFormEnabled.
Best regards,
Herman
Other Answers
You can control a property's visibility as well as availability of data values in multiple ways. In certain cases, it may be easier to remove these runtime capabilities completely. Refer to the XAF - How to disable adding and removing fields in the layout customization form (DetailView) or grid's Column Chooser (ListView) article for more information.
1. Security System at the Data Store Level (Protect Sensitive Data Values First)
If your goal is to restrict access to certain values based on a user's role, we highly recommend you use our Security System's permission settings: Security (Access Control & Authentication). This is the only way to guarantee that users do not have access to certain data. This solution protects you at the data store level and can be combined with visual solutions at the UI level (#2).
For more information on why it is important to avoid "security by obscurity" in your apps (only visual protection), refer to Forced Browsing Protection.
NOTE: You can skip this security solution only if your hidden UI elements do not contain sensitive data (for instance, you want to implement dynamic UI interactions or other goals, which do not include data protection).
2. Visual Customization at the Application Level (Control Data Field Visibility in the UI)
None of the solutions from this group can be used without #1 due to security reasons. All these solutions target default XAF's list and detail forms only (powered by the default grid list editor and layout manager respectively). You must implement additional UI-level solutions (on your own) for reports, dashboards, charts, pivot grids, tree lists, and other UI controls and modules.
2. UI-level: Data Annotation Attributes in Code of Business Classes)
Generally, you can use our built-in attributes to control the property visibility.
2.1. "Soft" Hiding
These attributes can hide properties from the View, but it is still possible to see them in the Application Model and thus in the CustomizationForm and ColumnChooser windows and other places in the UI.
VisibleInDetailViewAttribute
VisibleInListViewAttribute
VisibleInLookupListViewAttribute
2.2. "Hard" Hiding
These attributes specify whether the target business class or member should be visible in the Application Model. Members hidden in this manner cannot be displayed in Views.
BrowsableAttribute
MemberDesignTimeVisibilityAttribute
3. UI-level: Static Application Model Customization in the Model Editor
This option is a variation of #2 with attributes, because these code attributes eventually affect the Application Model.
The Column Chooser and Layout Customization dialogs display members that exist in the ListView | Columns and DetailView | Items nodes. A model column is displayed in the Column Chooser when its Index property is set to -1. A model View Item is displayed in the Layout Customization dialog when it does not have the corresponding layout item in the DetailView | Layout node. You can remove such nodes as follows:
3.1. Manual Node Removal in the Model Editor
Open the Model Editor and delete the corresponding IModelColumn and IModelPropertyEditor nodes.
3.2. Semi-Automatic Removal in Code or Using a Custom Attribute in the Model Editor
Customize the Application Model in code or implement a custom data annotation attribute as shown in the following example: How to implement a custom attribute to customize the Application Model or T921103 (a customer solution).
NOTE: In an XAF WinForms and Blazor application, customization forms allow you to invoke the Object Model dialog. This dialog allows the user to add new IModelColumn and IModelPropertyEditor nodes. To prevent this, still use the solutions #1 with #4.1 - 4.3.
4. UI-level: Dynamic Control Customization in Code
4.1. Remove the Column Chooser and Customization Form Completely in Code
In certain cases, it may be easier to remove these runtime capabilities completely. Refer to the XAF - How to disable adding and removing fields in the layout customization form (DetailView) or grid's Column Chooser (ListView) article for more information.
4.2. Hide Fields in the Column Chooser and Customization Form in Code
If you want to hide a property in the ListView's Column Chooser or DetailView's Customization Form in code, you can use the following solutions:
ASP.NET Core Blazor
C#// SolutionName.Blazor
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor.Editors;
using DevExpress.ExpressApp.Model;
using System.ComponentModel;
public class HideFromCustomizationFormController : ViewController<ListView>, IModelExtender {
void IModelExtender.ExtendModelInterfaces(ModelInterfaceExtenders extenders) {
extenders.Add(typeof(IModelMember),
typeof(IModelMemberShowInCustomizationForm));
}
protected override void OnViewControlsCreated() {
base.OnViewControlsCreated();
DxGridListEditor dxGridListEditor = View.Editor as DxGridListEditor;
if(dxGridListEditor != null) {
foreach(IModelColumn columnModel in View.Model.Columns) {
var column = dxGridListEditor.GetGridAdapter().GridDataColumnModels.FirstOrDefault(c => c.FieldName == columnModel.FieldName);
if(column != null) {
column.ShowInColumnChooser = ((IModelMemberShowInCustomizationForm)columnModel.ModelMember).ShowInCustomizationForm;
}
}
}
}
}
public interface IModelMemberShowInCustomizationForm : IModelNode {
[DefaultValue(true)]
bool ShowInCustomizationForm { get; set; }
}
WinForms and ASP.NET WebForms
C#// SolutionName.Module
using System.ComponentModel;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Editors;
// ...
public class HideFromCustomizationFormController : ViewController<ListView>, IModelExtender {
void IModelExtender.ExtendModelInterfaces(ModelInterfaceExtenders extenders) {
extenders.Add(typeof(IModelMember),
typeof(IModelMemberShowInCustomizationForm));
}
protected override void OnViewControlsCreated() {
base.OnViewControlsCreated();
ColumnsListEditor listEditor = View.Editor as ColumnsListEditor;
if (listEditor != null) {
foreach (ColumnWrapper column in listEditor.Columns) {
IModelMemberShowInCustomizationForm modelMember =
(IModelMemberShowInCustomizationForm)View.Model.Columns[column.Id].ModelMember;
column.ShowInCustomizationForm = modelMember.ShowInCustomizationForm;
}
}
}
}
public interface IModelMemberShowInCustomizationForm : IModelNode {
[DefaultValue(true)]
bool ShowInCustomizationForm { get; set; }
}
This controller adds the ShowInCustomizationForm property to IModelMember nodes to extend the Application Model. You can set this property to false in the Model Editor, and the respective column will be hidden from the customization form.
4.3. Hide Object Model Dialog Fields in Code
To prevent adding a property from the Object Model dialog in XAF WinForms and Blazor, use the following solution.
ASP.NET Core Blazor
To specify properties that you want to display or hide in the Object Model dialog in both ListView and DetailView, override the ObjectModelController
controller. For example, the following code snippet demonstrates how to filter out all key properties:
Codeusing DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor.Components;
using DevExpress.ExpressApp.Blazor.SystemModule;
namespace YourApplicationName.Blazor.Server.Controllers;
public class CustomizeObjectDialogController : ViewController<DetailView> {
ObjectModelController objectModelController;
protected override void OnActivated() {
base.OnActivated();
objectModelController = Frame.GetController<ObjectModelController>();
objectModelController.CustomizePropertyVisibility += ObjectModelController_CustomizePropertyVisibility;
}
private void ObjectModelController_CustomizePropertyVisibility(object sender, CustomizePropertyVisibilityEventArgs e) {
if(e.MemberInfo.Owner.KeyMember == e.MemberInfo) {
e.Visible = false;
}
}
protected override void OnDeactivated() {
base.OnDeactivated();
if(objectModelController != null) {
objectModelController.CustomizePropertyVisibility -= ObjectModelController_CustomizePropertyVisibility;
objectModelController = null;
}
}
}
WinForms
To hide a column from the Column Chooser even after it was added from the Model Browser, subscribe to the ColumnsListEditor.ColumnAdded event and update columns.
C#using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Win.Editors;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Win.SystemModule;
public class CustomWinController : ObjectViewController<ListView,Contact> {
protected override void OnViewControlsCreated() {
base.OnViewControlsCreated();
GridListEditor listEditor = ((ListView)View).Editor as GridListEditor;
UpdateColumns(listEditor);
listEditor.ColumnAdded += ListEditor_ColumnAdded;
}
private void ListEditor_ColumnAdded(object sender, System.EventArgs e) {
GridListEditor listEditor = (GridListEditor)sender;
UpdateColumns(listEditor);
}
private void UpdateColumns(GridListEditor listEditor) {
foreach(var columnWrapper in listEditor.Columns) {
if(!IsVisibleColumn(columnWrapper.PropertyName)) {
columnWrapper.ShowInCustomizationForm = false;
}
}
}
public static bool IsVisibleColumn(string name) {
if(name.StartsWith("<SubContact>SubProperty") || name.StartsWith("Upcast_Subcontact")) {
return false;
}
return true;
}
}
To hide a member from the Model Browser invoked from the Column Chooser, create a controller derived from GridEditorColumnChooserController. In the overridden CreateColumnChooserExtenderCore method, subscribe to the extender's ModelBrowserCreated event. You can access the tree list and filter its nodes there as follows.
C#public class GridEditorColumnChooserControllerEx: GridEditorColumnChooserController {
protected override GridListEditorColumnChooserExtender CreateColumnChooserExtenderCore() {
var ext = base.CreateColumnChooserExtenderCore();
ext.ModelBrowserCreated += Ext_ModelBrowserCreated;
return ext;
}
private void Ext_ModelBrowserCreated(object sender, ModelBrowserCreatedEventArgs e) {
e.ModelBrowser.FieldsTreeList.CustomRowFilter += FieldsTreeList_CustomRowFilter;
}
private void FieldsTreeList_CustomRowFilter(object sender, DevExpress.XtraTreeList.CustomRowFilterEventArgs e) {
var memberInfo = e.Node.Tag as IMemberInfo;
if(memberInfo != null) {
if(!CustomWinController.IsVisibleColumn(memberInfo.Name)) {
e.Visible = false;
e.Handled = true;
}
}
}
}
4.4. Conditional Appearance Rules to Hide View Items in Code
If you want to show/hide a property conditionally and declaratively, you can use the Conditional Appearance Module and add the required appearance rule and also implement Hide the Protected Content Columns in a List View and Property Editors in a Detail View.
Mentioned solution works for me (also in Column chooser):
C#[Appearance("AlwaysHide", Visibility=ViewItemVisibility.Hide)]
public string MyProperty {
// ...
}
Dear Kostantin,
I'm working to hide a field from column chooser,so i added this same class HideFromCustomizationFormController
But i have this error:
Error 42 Default property access is ambiguous between the inherited interface members 'Public ReadOnly Default Property Item(id As String) As NodeType' of interface 'DevExpress.ExpressApp.Model.IModelList(Of DevExpress.ExpressApp.Model.IModelColumn)'
and
'Public Default Property Item(index As Integer) As T' of interface 'System.Collections.Generic.IList(Of DevExpress.ExpressApp.Model.IModelColumn)'.
Can you help me to resolve it?
Thank you
Hello Pauline,
I have noticed that you created a new ticket regarding this problem: hide field from column chooser. We will process your question in this new thread.
Hello Howard,
You can hide these properties via the VisibleInDetailView and VisibleInListView attributes. Does this solution meet your requirements?
Thanks,
Anatol
they still show in the column chooser. i want to eliminate their visibility except for reporting.
Hello, Howard.
In addition to VisibleInDetailView and VisibleInListView attributes, apply the Appearance attribute in the following manner:
using DevExpress.ExpressApp.ConditionalAppearance; using DevExpress.ExpressApp.Editors; // ... [Appearance("AlwaysHide", Visibility=ViewItemVisibility.Hide)] public string MyProperty { // ... }
Thanks,
Konstantin B
the appearnace attribute does not effect the column chooser -- the property still shows up there.