Search This Blog

Wednesday, July 30, 2014

Checking if an object is new or not within a criterion string

Typical usage scenarios

I remember registering a corresponding feature request in order to make it easier for XAF developers to accomplish the following types of tasks:
a) Validating data fields for new records only; e.g., the scenario from Q440548
b) Implementing different data field appearance for new and saved records; e.g., the color or enabled state as in Q475272
c) Managing Action controls' state for new records via TargetObjectsCriteria

During these years these three scenarios stayed popular among our users (we had several dozens of trackers), so it was a natural decision for us, as framework creators, to make accomplishing this common and proven stuff easier for developers and probably end users.

Existing solutions

Before I introduce the usability improvement, I want to briefly outline a couple of good existing solutions that require writing some custom code to accomplish the tasks above.
In short, these are declaring a non-persistent property within your base persistent class that would return Session.IsNewObject(this) from the getter and then using this property in criteria, OR controlling required logic via Controllers and a similar IObjectSpace.IsNewObject method. You can find more technical details in this SC ticket. As I emphasized above, these are still good solutions and you can continue using them, but what would be great is to have something built-in that would allow developers not to write any code for these common scenarios.

Our new solution and its implementation details

Our solution, which is included in the standard delivery starting with v14.1.5 (so you can already access it), is a built-in IsNewObject criteria function, which can be used inside a criteria string; e.g., for the ConditionalAppearance and Validation modules.
This function is currently available for XPO users only, and it requires a persistent object instance as a parameter. The exact usage syntax is IsNewObject(This) or IsNewObject(ReferenceProperty),
where "This" is a service XPO keyword referring to the current object instance and "ReferenceProperty" is a reference property of the current object. Here are also some screenshots from the Model Editor depicting the real use by example of the appearance and validation rules:

The implementation of the custom criteria function is pretty straightforward, and I believe that some of you already have something similar in your code:

using System;
using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.SystemModule;

namespace DevExpress.ExpressApp.Xpo {
    public class IsNewObjectCriteriaOperator : ICustomFunctionOperator {
        public const string OperatorName = "IsNewObject";
        private static readonly IsNewObjectCriteriaOperator instance = new IsNewObjectCriteriaOperator();
        public static void Register() {
        #region ICustomFunctionOperator Members
        public object Evaluate(params object[] operands) {
            if(operands == null || operands.Length != 1) {
                throw new ArgumentException();
            object obj = operands[0];
            IObjectSpace objectSpace = XPObjectSpace.FindObjectSpaceByObject(obj);
            return objectSpace != null && objectSpace.IsNewObject(obj);
        public string Name {
            get { return OperatorName; }
        public System.Type ResultType(params System.Type[] operands) {
            return typeof(bool);

Take special note of the use of the XPObjectSpace.FindObjectSpaceByObject method here, which you may not be aware of yet. It helps to obtain an IObjectSpace object from an XPO object instance in some complex scenarios. Creating custom criteria functions should not be new to you, but, anyway, you can learn more on it from the XAF and XPO documentation (onetwothree). If you are curious, check out the implementation of the IsCurrentUserInRole, CurrentUserId and other built-in XAF criteria functions - it will surely open new horizons for you.

Finally, the documentation on the new function is currently in works and it will be published with the nearest online help files update. I hope you find this little gem helpful. Please let us know in comments if you liked it as well as whether you plan to use this new function in other scenarios. I will be more than happy to hear from you.


No comments:

Post a Comment