Customize the Application UI and Behavior
- 5 minutes to read
In XAF, the data model defines the database structure and UI. Changes to your persistent classes affect the UI. For example, if you add a new property to a business class, a new editor is added to the list and detail forms.
You can use the auto-generated UI or customize it according to your business requirements and scenarios. This topic describes how to customize your application’s appearance and behavior.
Customize the Application UI Metadata
Use Attributes in Code
Built-in attributes allow you to edit the Application Model, create controls, and customize the application’s appearance and behavior (validation, fields’ visibility and formatting, etc.) in the Business Model‘s code. With this declarative approach, you can add only one line of code without using the model editor or creating Controllers.
Apply the SizeAttribute to the Testimonial‘s Quote property and pass Unlimited as the attribute’s parameter to replace a single-line editor with a multi-line editor.
public class Testimonial
{
// ...
string quote;
[Size(FieldSizeAttribute.Unlimited)]
public string Quote {
get { return quote; }
set { SetProperty(ref quote, value); }
}
// ...
}
Run the Blazor application and open the Testimonial Detail View. The following image illustrates the standard and customized UI:
Note that this approach adds a dependency from XAF assemblies to your data access layer (DAL).
Use the Model Editor
Data model settings are exported to the application’s metadata (Application Model). If you do not want to define the application’s UI structure and behavior in your data model code, edit the application metadata in the Model Editor. Each project stores metadata settings as XML markup in *.xafml files. These files form the Application Model’s layered structure.
Follow the steps below to change the Customer business object’s image and enable images in the navigation control via the Model Editor:
- In the Solution Explorer, right-click the SimpleProjectManager.Module project and select Open Model Editor in the context menu or double-click the file with the XAFML extension.
In the Model Editor, navigate to the BOModel | Customer node in the tree and set the ObjectCaptionFormat property to {0:FullName}.
The image below illustrates the result. The Customer Detail View displays the FullName property value in the caption.
Define Custom Logic and UI Elements
The Model Editor and built-in attributes allow you to change the options of the UI element and control. Other changes can be implemented only in code. For example, you can use the Controllers and Actions mechanism to replace the application’s default UI parts or implement custom business logic.
A Controller is a component that you can use to change the application flow, customize UI elements, and implement custom user interaction. Controllers can also include Actions. Actions are displayed in the UI as interactive elements (buttons, menu items, etc.) and execute custom business logic.
Follow the steps below to implement a SimpleAction that allows a user to mark the selected Project Tasks as completed and sets the EndDate property to the current date and time:
- In the Solution Explorer, right-click the SimpleProjectManager.Module\Controllers folder and select Add | Class… in the context menu. Set the class name to ProjectTaskController.
Replace the created class code with the following:
using System; using DevExpress.Data.Filtering; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Actions; using SimpleProjectManager.Module.BusinessObjects.Planning; namespace SimpleProjectManager.Module.Controllers { public class ProjectTaskController : ViewController { public ProjectTaskController() { TargetObjectType = typeof(ProjectTask); TargetViewType = ViewType.Any; SimpleAction markCompletedAction = new SimpleAction( this, "MarkCompleted", DevExpress.Persistent.Base.PredefinedCategory.RecordEdit){ TargetObjectsCriteria = (CriteriaOperator.Parse("Status != ?",ProjectTaskStatus.Completed)).ToString(), ConfirmationMessage = "Are you sure you want to mark the selected task(s) as 'Completed'?", ImageName = "State_Task_Completed" }; markCompletedAction.SelectionDependencyType = SelectionDependencyType.RequireMultipleObjects; markCompletedAction.Execute += (s, e) => { foreach(ProjectTask task in e.SelectedObjects) { task.EndDate = DateTime.Now; task.Status = ProjectTaskStatus.Completed; View.ObjectSpace.SetModified(task); } View.ObjectSpace.CommitChanges(); View.ObjectSpace.Refresh(); }; } } }
Property | Value | Description |
---|---|---|
ProjectTask | The Controller is activated when the application displays an object of the specified type or a list of these objects. | |
Any | The Controller is activated when the application displays a list or detail data form. | |
Status is not Completed | The Controller is activated when an object focused on a list form or displayed in a detail meets the condition. | |
The Action is active when a user selects more than one object in a list form. |
In the code above, the Object Space‘s IObjectSpace.CommitChanges method commits changes to the database. An Object Space entity is an ORM-independent implementation of the Repository and Unit Of Work design patterns. Object Space allows you to query or modify data in the transaction. Refer to the Create, Read, Update and Delete Data article for information about other Object Space methods.
The image below shows the MarkCompleted Action in the Blazor application.
The MarkCompleted Action iterates the selected objects, modifies their properties, commits changes to the database, and refreshes the screen.
Alternatively, you can …
- implement the generic ObjectViewController<ViewType, ObjectType> instead of the ViewController. For the ObjectViewController, you can specify the View’s and object’s type this Controller should be activated for in the generic ViewType and ObjectType parameters: Define the Scope of Controllers and Actions.
- use the ActionAttribute to create an action directly from a business class method. Refer to the Add a Simple Action using an Attribute topic for more information.
Next topic: Reuse Implemented Functionality