Example E1679
Visible to All Users

XAF - How to implement a custom attribute to customize the Application Model

This example demonstrates how to create a custom attribute and remove a property from the Application Model's DetailView.Items and ListView.Columns nodes.
In this case, the properties marked with this attribute are removed from views.

Implementation Details

To implement this functionality, the IModelMember interface is extended with the IRemovedFromViewInfo interface that contains the IsRemovedFromViewInfo property. The value of this property is calculated based on the value of the custom attribute we created (RemoveFromViewInfoAttribute) and applied to the persistent class via the domain logic (RemovedFromViewInfoLogic). The IRemovedFromViewInfo.IsRemovedFromViewInfo property is used by the model node generator updater (ViewsNodesGeneratorUpdater) to remove certain view items and columns from detail and list views.

This example demonstrates three techniques: how to extend the application model with additional properties, define default model values via domain logic, and modify the default model via the model node generator updater.

Files to Review

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

CustomAttributeSolution/CustomAttributeSolution.Module/BusinessObjects/Contact.cs
C#
using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl.EF; using DXExample.Module; using System.Collections.ObjectModel; namespace dxTestSolution.Module.BusinessObjects; [DefaultClassOptions] public class Contact : BaseObject { public virtual string FirstName { get; set; } [RemoveFromViewModel] public virtual string LastName { get; set; } public virtual int Age { get; set; } public virtual DateTime BirthDate { get; set; } public virtual ObservableCollection<MyTask> MyTasks { get; set; } = new ObservableCollection<MyTask>(); } // public DbSet<MyTask> MyTasks { get; set; } // public DbSet<Contact> Contacts { get; set; }
CustomAttributeSolution/CustomAttributeSolution.Module/Module.cs
C#
using System.ComponentModel; using DevExpress.ExpressApp; using DevExpress.ExpressApp.DC; using DevExpress.Persistent.Base; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp.Actions; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Updating; using DevExpress.ExpressApp.Model.Core; using DevExpress.ExpressApp.Model.DomainLogics; using DevExpress.ExpressApp.Model.NodeGenerators; using dxTestSolution.Module.DatabaseUpdate; using DXExample.Module; using System.Collections; namespace CustomAttributeSolution.Module; // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. public sealed class CustomAttributeSolutionModule : ModuleBase { public CustomAttributeSolutionModule() { // // CustomAttributeSolutionModule // RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); } public override IEnumerable<ModuleUpdater> GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); return new ModuleUpdater[] { updater, new MyUpdater(objectSpace, versionFromDB) }; } public override void Setup(XafApplication application) { base.Setup(application); // Manage various aspects of the application UI and behavior at the module level. } public override void ExtendModelInterfaces(DevExpress.ExpressApp.Model.ModelInterfaceExtenders extenders) { base.ExtendModelInterfaces(extenders); extenders.Add<IModelMember, IRemovedFromViewModel>(); } public override void AddGeneratorUpdaters(ModelNodesGeneratorUpdaters updaters) { base.AddGeneratorUpdaters(updaters); updaters.Add(new ViewsNodesGeneratorUpdater()); } public override void CustomizeLogics(CustomLogics customLogics) { base.CustomizeLogics(customLogics); customLogics.RegisterLogic(typeof(IRemovedFromViewModel), typeof(RemovedFromViewInfoLogic)); } } [DomainLogic(typeof(RemovedFromViewInfoLogic))] public interface IRemovedFromViewModel { bool IsRemovedFromViewModel { get; } } public class RemovedFromViewInfoLogic { public static bool Get_IsRemovedFromViewModel(IRemovedFromViewModel instance) { RemoveFromViewModelAttribute attr = ((IModelMember)instance).MemberInfo.FindAttribute<RemoveFromViewModelAttribute>(); if (attr != null) { return attr.IsPropertyRemoved; } else { return false; } } } public class ViewsNodesGeneratorUpdater : ModelNodesGeneratorUpdater<ModelViewsNodesGenerator> { public override void UpdateNode(ModelNode node) { foreach (IModelView view in (IModelViews)node) { ArrayList itemsToRemove = new ArrayList(); if (view is IModelDetailView) { foreach (IModelViewItem item in ((IModelDetailView)view).Items) { if (item is IModelMemberViewItem) { IRemovedFromViewModel member = ((IModelMemberViewItem)item).ModelMember as IRemovedFromViewModel; if (member != null && member.IsRemovedFromViewModel) { itemsToRemove.Add(item); } } } } if (view is IModelListView) { foreach (IModelColumn column in ((IModelListView)view).Columns) { IRemovedFromViewModel member = column.ModelMember as IRemovedFromViewModel; if (member != null && member.IsRemovedFromViewModel) { itemsToRemove.Add(column); } } } foreach (IModelNode item in itemsToRemove) { item.Remove(); } if (view is IModelDetailView && itemsToRemove.Count > 0) { IModelViewLayout layoutModel = ((IModelDetailView)view).Layout; layoutModel[0].Remove(); new ModelDetailViewLayoutNodesGenerator().GenerateNodes((ModelNode)layoutModel); } } } }
CustomAttributeSolution/CustomAttributeSolution.Module/RemoveFromViewInfoAttribute.cs
C#
using System; using System.Collections.Generic; using System.Text; namespace DXExample.Module { [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class RemoveFromViewModelAttribute : Attribute { private bool _IsPropertyRemoved; public RemoveFromViewModelAttribute(bool value) { _IsPropertyRemoved = value; } public RemoveFromViewModelAttribute() { _IsPropertyRemoved = true; } public bool IsPropertyRemoved { get { return _IsPropertyRemoved; } } } }

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.