List View Column Generation

  • 8 minutes to read

The eXpressApp Framework automatically generates all List Views according to the Application Model's information. This topic describes the specific rules used to generate a default set of List View columns.


The column generation logic is declared in the ModelListViewColumnsNodesGenerator class, which is the Node Generator (see Extend and Customize the Application Model in Code).

Simple Property Columns Generation

In this section, simple property columns are generated for the following persistent class:

public class ObjectA : BaseObject {
    public ObjectA(Session session) : base(session) { }
    private string propertyA1;
    private string propertyA2;
    public string PropertyA1 {
        get { return propertyA1; }
        set { SetPropertyValue(nameof(PropertyA1), ref propertyA1, value); }
    public string PropertyA2 {
        get { return propertyA2; }
        set { SetPropertyValue(nameof(PropertyA2), ref propertyA2, value); }

The ListView's and LookupListView's Columns node contains child nodes generated for this class. In Mobile applications, the RowLayout node and its child nodes are generated in addition to Columns (Columns' nodes do not affect a List View layout- it is based on RowLayout nodes only). The following image illustrates these nodes in the Model Editor:


The column order specified using the IModelNode.Index properties corresponds to their declaration order. These columns are visible when their Index values are positive or zero.

The following attributes, applied in code, affect column visibility:

  • DefaultProperty and FriendlyKeyProperty Attributes

    If the class has a default or friendly key property (see DefaultPropertyAttribute and FriendlyKeyPropertyAttribute), its Lookup List View contains a single column corresponding to this property. In the general List View, the default property column has an index of zero and is displayed first. In Mobile applications, the ListView's and LookupListView's RowLayout node contains the single node corresponding to the default property. To display additional property values, add new Layout View Items to the RowLayout node. The code below demonstrates the DefaultProperty attribute in use, and the image illustrates the result.

    public class ObjectA : BaseObject {
        // ...


    The FriendlyKeyProperty attribute has the same effect.

    If the business class exposes a property containing the "Name" substring in its name (excluding inherited properties), then it is considered as the default property:

    public class ObjectA : BaseObject {
        // ...
        public string ObjectName {
            // ...


    The DefaultProperty attribute overrides this behavior.

  • Browsable Attribute

    The corresponding column is not generated if the property is decorated with the Browsable attribute and false is passed as the parameter (see BrowsableAttribute).

  • VisibleInListView Attribute

    The corresponding column is generated but remains invisible if the property is decorated with the VisibleInListViewAttribute attribute and false is passed as the parameter. The Columns node's IModelNode.Index property is set to -1. You can use the Column Chooser or Model Editor to unhide such a column (see Change Field Layout and Visibility in a List View).

  • VisibleInLookupListView Attribute

    When a class has a default property, XAF generates one column for this property in the Lookup List View. To add a column in code, decorate the required property with the VisibleInLookupListViewAttribute and pass true as the attribute parameter. When the class has no default property, all property columns are generated in the Lookup List View. To hide a column corresponding to a certain property, decorate the property with the VisibleInLookupListViewAttribute, and pass false as the attribute parameter.

Reference Property Columns Generation

To demonstrate how the reference property columns are generated, the persistent class demonstrated in the previous section, will be extended with the PropertyA3 reference property of the ObjectB type

public class ObjectA : BaseObject {
    // ...
    private ObjectB propertyA3;
    public ObjectB PropertyA3 {
        get { return propertyA3; }
        set { SetPropertyValue(nameof(propertyA3), ref propertyA3, value); }
public class ObjectB : BaseObject {
    public ObjectB(Session session) : base(session) { }
    private string propertyB1;
    public string PropertyB1 {
        get { return propertyB1; }
        set { SetPropertyValue(nameof(propertyB1), ref propertyB1, value); }
    private string propertyB2;
    public string PropertyB2 {
        get { return propertyB2; }
        set { SetPropertyValue(nameof(propertyB2), ref propertyB2, value); }

A column is generated to represent the PropertyA3 property by default. In Mobile applications, the ListView's and LookupListView's RowLayout node contains a single node corresponding to the first property:


In the UI, the PropertyA3 displays the PropertyB2's value, because the PropertyB2 is the ObjectB class' default property.


In Mobile applications, you need to add the new PropertyA3 Layout View Item to the RowLayout node to show the PropertyA3 property value in the List View.

If the PropertyA3 property is decorated by the ExpandObjectMembersAttribute with the ExpandObjectMembers.InListView parameter, then the columns for all ObjectB class' properties are generated in the ObjectA List View. The ExpandObjectMembersAttribute has no effect in Mobile List Views.

public class ObjectA : BaseObject {
    // ...
    public ObjectB PropertyA3 {
        // ...


Columns, Generated in Inherited Class' List Views

Consider the following ObjectC class, derived from the ObjectA class:

public class ObjectC : ObjectA {
    public ObjectC(Session session) : base(session) { }
    private string propertyC1;
    public string PropertyC1 {
         get { return propertyC1; }
        set { SetPropertyValue(nameof(propertyC1), ref propertyC1, value); }
    private string propertyC2;
    public string PropertyC2 {
        get { return propertyC2; }
        set { SetPropertyValue(nameof(propertyC2), ref propertyC2, value); }

Typically, the columns for this class properties are generated as usual (see the description of ObjectA List Views column generation above). The columns for derived properties are generated as hidden (with -1 indexes). Note the following specifics:

  • The intended behavior when the derived class has no default property, and its ancestor has a default property

    The ancestor class's default property is used as the default in a derived class' List View. In the general List View, this property's column gets the zero index and is shown first. In the Lookup List View, the default property ancestor class column is the only generated column. The following image illustrates the generated columns when the ProprertyA2 is the ObjectA class' default property:


  • The intended behavior, when the derived class has no public fields and properties

    In this case, columns generated for the derived class are the same as the ancestor class' columns, and they all are visible by default. The ancestor class's default property is used as the default in a derived class' List View.

Default Columns Width

Each column has an IModelColumn.Width property, specifying its width in a Windows Forms application. The following table demonstrates the default width values:

Type of Property Default Width Default Width in Lookups
The property is the class' default or friendly key property (see DefaultPropertyAttribute, FriendlyKeyPropertyAttribute). If a property contains "Name" in its name (excluding inherited properties), this property is also considered default. 400 340
A short value type property - int, float, double, decimal, char or bool. 50 50
Other properties (string, etc.) 70 50

Usually the default property contains the most details in the class, so a wide column is automatically generated for it. Short type values do not take much screen space, and their default columns are narrow.

In ASP.NET Web XAF applications, the web browser determines column widths based on the current theme and the displayed content's style - the Width property has no effect.

Columns Sorting Order

List Views are sorted by the default property values in ascending order (if the default property type is System.IComparable). The default column's IModelColumn.SortIndex is set to 0, and IModelColumn.SortOrder is set to ColumnSortOrder.Ascending. Other columns have the default SortIndex and SortOrder (-1 and ColumnSortOrder.None, respectively) values.

See Also