Skip to main content
.NET 6.0+

Display Properties of a Referenced Object in the Master Object's View

  • 4 minutes to read

By default, properties of the current object type are displayed in a View. However, you may want to add editors for properties that are exposed by a related object, declared using a reference property. This topic describes the different approaches you can use to display properties of such an associated object.

The following Project and Task business classes are used in this topic.

using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
using System.ComponentModel;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
// ...
[DefaultClassOptions]
public class Project : BaseObject {
    public virtual string ProjectName { get; set; }
    public virtual DateTime? Deadline { get; set; }
    public virtual IList<Task> Tasks { get; set; }= new ObservableCollection<Task>();
}
[DefaultClassOptions]
public class Task : BaseObject {
    public virtual string Subject { get; set; }
    public virtual string Description { get; set; }
    public virtual Project Project { get; set; }
}

// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.

Although these classes are Entity Framework Core Code-First entities, you can use the same approaches with XPO persistent classes.

Apply the ExpandObjectMembers Attribute

When you apply the ExpandObjectMembersAttribute to a reference property, all properties of the related object are added to the model of the List and Detail Views of the current object type.

using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
// ...
public class Task : BaseObject {
    // ...
    [ExpandObjectMembers(ExpandObjectMembers.Always)]
    public virtual Project Project { get; set; }
}

As a result, all visible properties of the Project class will be added to Task Views (to the Views | <ListView> | Columns and Views | <DetailView> | Items nodes in the Application Model). New columns and View Items are highlighted in red in the image below.

WaysToDisplayRef_ExpandObjectMembers

Unnecessary columns/items can be removed in the Model Editor.

You can pass other values of the ExpandObjectMembers enumeration to add Project properties only to *Task* List Views, or only to Task Detail Views. You can also pass the memberName parameter to add a single specific property instead of all visible properties. For details, refer to the ExpandObjectMembersAttribute class description.

Add an Editor or Column in the Model Editor

You can add a column/item to a List or Detail View in the Model Editor, using the context menu of Views | <ListView> | Columns and Views | <DetailView> | Items nodes. Use the ReferencePropertyName.PropertyName notation when specifying the IModelMemberViewItem.PropertyName value. The image below demonstrates how to add the Project.Deadline column to the Task List View in the Model Editor.

WaysToDisplayRef_ME

You can add a PropertyEditor node to the Views | <DetailView> | Items in a similar manner, but note that you should also add a corresponding layout item to the Views | <DetailView> | Layout node. An example is provided in the Add an Editor to a Detail View tutorial.

Use the DetailPropertyEditor in a Detail View

You can use the DetailPropertyEditor Property Editor to display a reference property as an embedded Detail View in WinForms and ASP.NET Web Forms applications. For this purpose, you can apply the EditorAlias attribute to the reference property.

using DevExpress.ExpressApp.Editors;
// ...
public class Task : BaseObject {
    // ...
    [EditorAlias(EditorAliases.DetailPropertyEditor)]
    public virtual Project Project { get; set; }
}

Alternatively, you can run the Model Editor for the platform-specific project (WinForms or ASP.NET Web Forms) and set the IModelCommonMemberViewItem.PropertyEditorType property of the BOModel | <Class> | OwnMembers | <Member> node to DetailPropertyEditor.

WaysToDisplayRef_DetailPropertyEditor_ME

The image below demonstrates the Project property displayed using the DetailPropertyEditor.

WaysToDisplayRef_DetailPropertyEditor

Add a Calculated Property

You can declare a property whose value is calculated as follows.

public class Task : BaseObject {
    // ...
    public DateTime? Deadline {
        get { return Project != null ? Project.Deadline : null; }
    }
}

You can also add a custom calculated field in the Model Editor and refer to the required property using IModelMember.Expression.

WaysToDisplayRef_CustomField

In both these cases, the Deadline property will be readonly in Task Views. If you need to edit it, implement the INotifyPropertyChanged interface and declare Deadline as follows.

using System.ComponentModel.DataAnnotations.Schema;
// ...
public class Task : BaseObject, INotifyPropertyChanged {
    // ...
    private void OnChanged(String propertyName) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    [NotMapped]
    public DateTime? Deadline {
        get { return Project != null ? Project.Deadline : null; }
        set {
            if (Project != null) {
                Project.Deadline = value;
                OnChanged(nameof(Project));
            }
        }
    }
}

In XPO, you do not need to implement INotifyPropertyChanged; the OnChanged protected method is available in the base XPBaseObject class. Additionally, the NonPersistentAttribute is used instead of NotMappedAttribute in XPO.

See Also