Monday, June 08, 2009

XAF Custom Rule for Conditionally Required Properties

 

For those of you using DevExpress XAF (eXpressApp) you may have come across the need for making a Domain Object property conditionally required.  For Example, lets say you have a Domain Object with 3 properties (FirstName, LastName, and Phone) and you want Phone to be required only if FirstName and LastName are not null. How do you do it in XAF? Well I have a solution for you.  Simply download the source and apply the RuleConditionalIsRequiredAttribute to your properties like so:

[DefaultClassOptions]
public class TestRule : BaseObject
{
public TestRule(Session session) : base(session) { }

...

private string phone;
[RuleConditionalIsRequired("Phone is Required", DefaultContexts.Save, "!String.IsNullOrEmpty(FirstName) && !String.IsNullOrEmpty(LastName)", "Phone is required when First Name and Last Name are added.")]
public string Phone
{
get
{
return phone;
}
set
{
SetPropertyValue("Phone", ref phone, value);
}
}
}




As you can see you are writing C# code as the condition, I haven't tested in VB but since its using lambda expressions to compile this condition I'm sure it will work (I hope at least for VB coders).  It works great in my C# applications.  Your condition has to return bool and can only be used for properties.  The method CheckCondition will build a lambda expression and execute it against your class instance.  If the condition returns true then this property is required, otherwise it is not required.  The lambda expression class was developed by Microsoft and distributed with Visual Studio 2008 as a Sample application on using LAMDBA Expressions.



Now when we run this we get the following error: ValidationError



The Full Source is attached.



I hope this helps someone.



Happy Coding!!! Download Source Here

11 comments:

Paul Elliott said...

Am I mising something but cant this be accomplish with the following

[RuleRequiredField("Phone number is required", DefaultContexts.Save, "Phone number is required",TargetCriteria="LastName !='' && FirstName != ''")]
public string Phone
{.....
}

this is what TargetCriteria is for


Paul Elliott

Gary Cox said...

Thanks Paul, yes this can be done in the same manner. This is just another way you can perform this type of requirement.

Alain Bismark said...

Nice!!!!

Gary, one detail, the Parser module, have any help?, you use this Parser in other software?

Nice, nice...

Gary Cox said...

Thanks Alain, unfortunately I don't have any help on the Parser. That was written by Microsoft and I got it out a Sample that comes with VS2008. It's a very simple class though, if you need help with it just let me know and I can help you out.

Alain Bismark said...

Thanks Gary.

Two basic questions if you have time:

1. Where I can find the sample of Microsoft (to understand the context where this parser is used), I search my installation of VS 2008, but I didnt find this module.


2. You used this Parser, to compute for example, mathematical expressions, or to make scripting over NET objects?

Thanks a lot!

Alain

Alain Bismark said...

Forget it.

I found it.

Just one question, if possible to put method (boolean function) in your rules?, I tested, but failed.

Thanks.

Gary Cox said...

Alain,
This only works on properties and must return a boolean value.

Lorian said...

Hi,

Thanks for this example it has helped me a lot with my own project. The only difference is rather than using RuleConditionalIsRequired I am using RuleCriteria. For example

[RuleCriteria("AccountingPeriod Conditions", DefaultContexts.Save, "RecurrencePeriodId.RecurrencePeriodName == 'Accounting' && (DayOfPeriod > 0 && DayOfPeriod <=35)", "")]

This all works fine however I am trying to make a RuleCriteria where if a field has the value of Yearly then a certain field can not be empty.

This is what I thought it would be

[RuleCriteria("YearlyPeriodIsSelected", DefaultContexts.Save, "RecurrencePeriodId.RecurrencePeriodName == 'Yearly' && !Int.IsNullOrEmpty(MonthOfPeriod), "If the value for Recurrence Period is Yearly then the value for Month Of Period can not be empty")]

This is not working and any recommendation will be of great help.

Kind Regards

Lorian

Lorian said...

Sorry, there should be a " after (MonthOfPeriod)

Gary Cox said...

Lorain,
My implementation is different from that of DevExpress. The condition you are passing is how you would do this using my attribute, however since you are using the DevExpress attribute you need to follow their format. This information can be found in the help or you can submit a support question in the Support Center.

Gary Cox said...

One thing I noticed on your code Lorain is your passing Int.IsNullOrEmpty, if MonthOfPeriod is a generic int type (int?) then you should checking using MonthOfPeriod.HasValue().

 
Creative Commons License
Blogged Information and Code is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.