This post may be outdated. For the latest Domain Components concepts and examples refer to the current online documentation.
In the UI of XAF any object can be represented by a string, called its display name, and you can easily specify any property as being the display name via DefaultProperty attribute.
Whilst building the XCRM application, we came across a nice “gotcha” namely, how do you display two or more objects, in a list, if those objects have different default properties? Specifically we ran across this problem whilst implementing Customers.
First off, we introduced the ICustomer interface with the “contract” that Customers must fulfil:
[DomainComponent]
[XafDefaultProperty("Name")]
public interface ICustomer {
[PersistentDc]
string Name { get; }
As you can see, this interface specifies the “Name” property as being the display name, which seems completely sensible and intuitive. All is okay so far. However, we also have the IPerson and IAccount interfaces. There is also the IContact interface, which inherits from IPerson, ICustomer and IAccount, and it has FullName as its display name:
[DomainComponent]
[ImageName("BO_Contact")]
[XafDefaultProperty("FullName")]
[VisibleInReports]
[XafDisplayName("Contact")]
public interface IContact : IPerson, ICustomer {
IAccount Account { get; set; }
}
And not forgetting IAccount, which inherits from ICustomer, and that uses AccountName as it’s display name:
[XafDisplayName("Account")]
public interface IAccount : ICustomer {
[RuleRequiredField(AccountValidationRules.AccountNameIsRequired, DefaultContexts.Save)]
string AccountName { get; set; }
As I’ve said, both of these interfaces inherit from ICustomer, which means we have to work with display names of ICustomer.Name, IContact.FullName and IAccount.AccountName.
If you are thinking that this is pretty complicated, just wait, it gets worse. There are certain requirements placed on default properties, for example filtering by these properties should be done on the database server and not on the client. Also these properties are likely to be used in criteria and filtering operations, which should be “fast enough” and also not dump half the database onto the client. 
To ensure these performance requirements were met, we added the [Persistent] attribute and removed the setter from the Name member on ICustomer:
[DomainComponent]
[XafDefaultProperty("Name")]
public interface ICustomer {
[PersistentDc]
string Name { get; }
This change made the Name member a calculated property and we need to provide some form of domain logic that will return a meaningful value for it. We don’t provide this logic explicitly for ICustomer, because we don’t know what it will look like. We do know what it should look like in the IAccount subclass however:
[XafDisplayName("Account")]
public interface IAccount : ICustomer {
[RuleRequiredField(AccountValidationRules.AccountNameIsRequired, DefaultContexts.Save)]
string AccountName { get; set; }
So in this case, the domain logic for the Name member on ICustomer should return AccountName:
[DomainLogic(typeof(IAccount))]
public class AccountLogic {
public static string Get_Name(IAccount account) {
return string.Format("{0}", account.AccountName);
}
}
Following this simple pattern, we now know that the domain logic for IContact should return FullName:
[DomainLogic(typeof(IContact))]
public class ContactLogic {
public static string Get_Name(IContact contact) {
return string.Format("{0}", contact.FullName);
}
}
As you can see from this screen shot, using the pattern defined above, it is easy to have objects with different display names in a single list. Here you can see the “FullName” from the Contact and the “AccountName” (labelled Account) from the Account.

Well that about wraps it up for this post, if you have any questions or comments please leave them below – until next time, happy XAF’ing! 