Blogs

Gary's Blog

XAF – Domain Components How-to: Implement a Default Property for a Business Entity Derived from Multiple Components

     

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. Smile

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.

Contact List

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! Smile

Published Feb 24 2011, 11:00 AM by Gary Short (DevExpress)
Filed under: , ,
Technorati tags: XAF, DC, Domain Components
Bookmark and Share

Comments

 

M. Brekhof said:

Hi Gary,

You start with

[DomainComponent]

[XafDefaultProperty("Name")]

public interface ICustomer {

   [PersistentDc]

   string Name { get; }

the halfway the page you say:

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; }

Somehow I would have expected the two to be different (the first one should be different).

And am I right that Fullname of Contact is a inherited property of IPerson (which is a base class or how-do-you-call-it?)?

regards,

Martin

February 24, 2011 5:14 PM
 

Dan (DevExpress) said:

First of all, sorry for a long delay.

> FullName

Yes, this property is declared in the IPerson interface and the IContact interface is inherited from the IPerson. You can find more details about these interfaces in the XCRM demo application that is installed among other demos with all the source code.

>the two to be different

In this post series we are not going to show the development process in every detail because it will take hundreds of screens to read. Instead, we have developed a XCRM demo application and now we pay attention to significant parts of this demo development. We will comment our code and explain why there is one attribute or another, we will tell how we create it in a brief form. So, there will be such duplicated code snippets. However, we will try to avoid them and we are hoping that such things will not trouble our readers.

March 10, 2011 7:45 AM
More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.