What Changed
We changed the way XAF determines the default property and implemented the helper static property: DevExpress.ExpressApp.DC.TypeInfo.DefaultPropertyNames. This property contains the following string values: Name, Title, Subject, Caption, Description, Benennung, Nombre, Nome
.
The following table demonstrates how XAF determines the TypeInfo.DefaultMember property value in 21.1 and earlier versions:
Step | v21.1 and later | v20.2 and earlier |
---|---|---|
1 | The property specified by the class's DefaultPropertyAttribute or XafDefaultPropertyAttribute, TypeInfo.DefaultMember. | Same. |
2 | A property whose name matches or contains one of the DevExpress.ExpressApp.DC.TypeInfo.DefaultPropertyNames values. These values are arranged in priority order. For example, if a business class has both ObjectName and Description properties, TypeInfo.DefaultMember returns ObjectName. | The property “Name” or a property that contains “Name” in its identifier. |
3 | The property specified by the class's FriendlyKeyPropertyAttribute. | Same. |
4 | The property specified by the class's KeyAttribute. | Skip. |
Reasons for Change
These changes help to determine the TypeInfo.DefaultMember value in more cases and allow addressing the following issues:
- Blazor DxDataGrid does not support reference properties that don't have TypeInfo.DefaultMember;
- Blazor DxDataGrid does not support reference properties whose descriptors contain an exclamation mark ("!");
- List Editors in DataView and InstantFeedback data access modes don't show the values of reference properties if they don't have TypeInfo.DefaultMember.
Impact on Existing Apps
This change affects your business class if you overrode its ToString method to specify the display value and did not apply DefaultPropertyAttribute or XafDefaultPropertyAttribute to the class. For example, now, the display value of the following business class is Oid's value, not ToString's returned value.
C#using System;
using DevExpress.Persistent.Base;
using DevExpress.Xpo;
namespace YourSolutionName.Module.BusinessObjects {
[DefaultClassOptions]
public class MyTestObject : XPLiteObject {
public MyTestObject(Session session) : base(session) { }
private Guid oid = Guid.Empty;
[Key(true)]
public Guid Oid {
get { return oid; }
set { oid = value; }
}
private string firstPart;
public string FirstPart {
get => firstPart;
set => SetPropertyValue(nameof(FirstPart), ref firstPart, value);
}
private string secondPart;
public string SecondPart {
get => secondPart;
set => SetPropertyValue(nameof(SecondPart), ref secondPart, value);
}
public override string ToString() => FirstPart + " " + SecondPart;
}
}
In v21.1 and later versions, create a new getter-only property to return the display value and apply DefaultPropertyAttribute or XafDefaultPropertyAttribute to the business class, as shown below:
C#using System;
using System.Reflection;
using DevExpress.Persistent.Base;
using DevExpress.Xpo;
namespace YourSolutionName.Module.BusinessObjects {
[DefaultClassOptions]
[DefaultProperty(nameof(MyTestObject.CalculatedProperty))]
public class MyTestObject : XPLiteObject {
//
public string CalculatedProperty => FirstPart + " " + SecondPart;
}
}
NOTE: You can apply PersistentAliasAttribute (XPO) or CalculatedAttribute (EF or Non-Persistent Objects) for this display property as described in s170565, if required
How to Revert to Previous Behavior
Ignore DefaultPropertyNames Values Other than "Name"
To revert the previous behavior or customize DefaultPropertyNames, add the static constructor to your application module and modify this list. The example below shows how to revert the previous behavior:
C#using DevExpress.ExpressApp;
public sealed partial class YourSolutionNameModule : ModuleBase {
// ...
static YourSolutionNameModule() {
DevExpress.ExpressApp.DC.TypeInfo.DefaultPropertyNames.Clear();
DevExpress.ExpressApp.DC.TypeInfo.DefaultPropertyNames.Add("Name");
}
}
Note: The FrameworkSettings.DefaultSettingsCompatibilityMode option reverts the previous behavior in v20.2 and lower.
Ignore Properties Decorated with the Key Attribute
To revert to the previous behavior, add the static constructor to your application module and set the DevExpress.ExpressApp.DC.TypeInfo.IncludeKeyMemberIntoDefaultMemberCheck property to false.
C#using DevExpress.ExpressApp;
public sealed partial class YourSolutionNameModule : ModuleBase {
// ...
static YourSolutionNameModule() {
DevExpress.ExpressApp.DC.TypeInfo.IncludeKeyMemberIntoDefaultMemberCheck = false;
}
}
Note: The FrameworkSettings.DefaultSettingsCompatibilityMode option sets this property to true in v21.1 and newer.
Non-XAF Apps
You can either set the TypeInfo.IncludeKeyMemberIntoDefaultMemberCheck property to false or set the FrameworkSettings.DefaultSettingsCompatibilityMode property to v20.2 or lower. The Project Converter does not apply the latter setting automatically if your non-XAF projects do not reference the DevExpress.ExpressApp assembly.