Skip to main content
All docs
V24.1
.NET 6.0+

Implement a Property Editor Based on a Custom Component (Blazor)

  • 5 minutes to read

This topic describes how to implement a Property Editor for ASP.NET Core Blazor applications. For this, implement the following entities in the application project (MySolution.Blazor.Server):

Component Model
An object representation of the component that is required to change the component’s state.
Property Editor
A class that integrates the component into your XAF application.

Note

When you use Razor markup (*.razor) to create a custom component, ensure that the component’s logic is separated from property editors. Use Parameters and the @inject directive to supply necessary data to the component. Avoid mixing the component’s logic with the component model or property editor.

The process of component creation in XAF is similar to non-XAF applications. The Component Model contains information about component parameters and component type, and is responsible for linking the component with the property editor.

For more information about the XAF Component Model, refer to the following topic: Underlying Controls and Components Behind UI Elements (ASP.NET Core Blazor).

The example below demonstrates a custom String Property Editor that displays the InputText component.

Component Model

  1. Create a ComponentModelBase descendant and name it InputTextModel. In this class, declare properties that you will set in the underlying InputText component. The properties must have the same type and name as their counterparts in the component. In this example, use Value, ValueChanged, and ValueExpression properties.
  2. Override the ComponentType method and return the type of the component. XAF automatically creates a RenderFragment to render InputText based on properties and component type specified in the Component Model.

File: MySolution.Blazor.Server\Editors\InputTextModel.cs

using System.Linq.Expressions;
using DevExpress.ExpressApp.Blazor.Components.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;  

namespace YourSolutionName.Blazor.Server.Editors;

public class InputTextModel : ComponentModelBase {
    public string  Value {
        get => GetPropertyValue<string>();
        set => SetPropertyValue(value);
    }
    public EventCallback<string> ValueChanged {
        get => GetPropertyValue<EventCallback<string>>();
        set => SetPropertyValue(value);
    }
    public Expression<Func<string>> ValueExpression {
        get => GetPropertyValue<Expression<Func<string>>>();
        set => SetPropertyValue(value);
    }
    public override Type ComponentType => typeof(InputText);
}

Property Editor

  1. Create a BlazorPropertyEditorBase descendant and name it CustomStringPropertyEditor. Apply a PropertyEditorAttribute to it and set its parameters to string and false. These values specify that you can choose this Property Editor in the Model Editor for any string property, and this editor is not marked as default.
  2. Override the CreateComponentModel method, create the InputTextModel instance, and set it up.
  3. Override the ReadValueCore and GetControlValueCore methods to set and retrieve the value of the underlying component.
  4. Override the ApplyReadOnly method to manage the read-only state.

File: MySolution.Blazor.Server\Editors\CustomStringPropertyEditor.cs

using DevExpress.ExpressApp.Blazor.Components.Models;
using DevExpress.ExpressApp.Blazor.Editors;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Model;
using Microsoft.AspNetCore.Components;  

namespace YourSolutionName.Blazor.Server.Editors;  

[PropertyEditor(typeof(string), false)]
public class CustomStringPropertyEditor : BlazorPropertyEditorBase {
    public CustomStringPropertyEditor(Type objectType, IModelMemberViewItem model) : base(objectType, model) { }
    public override InputTextModel ComponentModel => (InputTextModel)base.ComponentModel;
    protected override IComponentModel CreateComponentModel() {
        var model = new  InputTextModel();
        model.ValueExpression = () => model.Value;
        model.ValueChanged = EventCallback.Factory.Create<string>(this, value => {
            model.Value = value;
            OnControlValueChanged();
            WriteValue();
        });
        return model;
    }
    protected override void ReadValueCore() {
        base.ReadValueCore();
        ComponentModel.Value = (string)PropertyValue;
    }
    protected override object GetControlValueCore() => ComponentModel.Value;
    protected override void ApplyReadOnly() {
        base.ApplyReadOnly();
        ComponentModel?.SetAttribute("readonly", !AllowEdit);
    }
}

Rebuild your solution and invoke the Model Editor for the ASP.NET Core Blazor application project (MySolution.Blazor.Server). Navigate to the required BOModel | <Class> | OwnMembers | <Member> node and set the node’s PropertyEditorType property to CustomStringPropertyEditor.

You can also set this Property Editor for a particular View only. To do this, specify the PropertyEditorType property of the Views | <DetailView> | Items | <PropertyEditor> node.

Note

If your project uses .NET 6 or earlier, an error may occur. For more information, refer to the following pull request in the ASP.NET Core open-source repository: Blazor input component support when EditContext is not supplied.

Note

The built-in Component Model handles the Component’s ValueChanged event (TextChanged, DateChanged, TimeChanged, and so on) and automatically reads and writes the Component’s Value (Text, Date, Time, and so on). For example, an implementation of a property editor based on DxTextBoxModel may look like this:

using DevExpress.ExpressApp.Blazor.Components.Models;
using DevExpress.ExpressApp.Blazor.Editors;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Model;

[PropertyEditor(typeof(string), false)]
public class CustomStringPropertyEditor : BlazorPropertyEditorBase {
    public CustomStringPropertyEditor(Type objectType, IModelMemberViewItem model) : base(objectType, model) { }
    public override DxTextBoxModel ComponentModel => (DxTextBoxModel)base.ComponentModel;
    protected override IComponentModel CreateComponentModel() => new DxTextBoxModel();
}

Access XafApplication and ObjectSpace to Query and Manipulate Data (Perform CRUD Operations)

A custom Property Editor may require access to the application or the View ObjectSpace object. If so, implement the IComplexViewItem interface as shown in the following topic: IComplexViewItem.

Use the IComplexViewItem.Setup method to get the XafApplication and IObjectSpace objects. The IObjectSpace object contains methods to access the application database.

Display a Custom Component in a List View

The InputText component from the above example will be rendered in Detail Views and in List Views during inline editing. To specify a component that your custom Property Editor should render in regular List View cells, override the BlazorPropertyEditorBase.CreateViewComponentCore method.

File: MySolution.Blazor.Server\CustomStringPropertyEditor.cs

using DevExpress.ExpressApp.Blazor.Components.Models;
using DevExpress.ExpressApp.Blazor.Editors;
using DevExpress.ExpressApp.Editors;
using Microsoft.AspNetCore.Components;

namespace YourSolutionName.Blazor.Server.Editors;

[PropertyEditor(typeof(string), false)]
public class CustomStringPropertyEditor : BlazorPropertyEditorBase {
    // ...
    protected override RenderFragment CreateViewComponentCore(object dataContext) {
        InputTextModel componentModel = new InputTextModel();
        componentModel.Value = (string)this.GetPropertyValue(dataContext);
        componentModel.ValueExpression = () => componentModel.Value;
        componentModel.SetAttribute("readonly", true);
        return  componentModel.GetComponentContent();
    }
}

The image below demonstrates the result.

XAF ASP.NET Core Blazor Custom Component-Based String Property Editor in a List View, DevExpress

See Also