Hi guys.
I use CSLA 3.7 version
I have a Editable Root named Root1 and 2 EditableChilds: Child1 and Child2
Child1 and Child2 are sharing the same string property( named Shared_Child_Property)
I want to validate if exist at least one value not nullorempty for Shared_Child_Property (it is the same if exist in Child1.SharedProperty or Child2.SharedProperty)
in root 1 i declared:
Private Shared Child1Property As PropertyInfo(Of Child1) = _
RegisterProperty(New PropertyInfo(Of Child1)("Child"))
Public ReadOnly Property Child1() As Child1
Get
If Not FieldManager.FieldExists(Child1) Then
LoadProperty(Child1Property, Child1.NewChild())
End If
Return GetProperty(Child1Property)
End Get
End Property
....
The same property declaration i did for Child2
My problem is the follow:
In Child_Create method of Child1, i call ValidationRules(the same ocurrs for child2)...
And ValidationRules in Child 1 call this function :
Private Function ValidateAtLeastOneSharedProperty(Of T As Root1)( _
ByVal target As T, ByVal e As RuleArgs) As Boolean
dim parent as Root1 = target.GetParent
dim IsValidSharedPropChild1 as boolean = not string.IsnullorEmpty(target.Shared_Child_Property)
dim IsValidSharedPropChild2 as boolean = not string.IsnullorEmpty(parent.Child2.Shared_Child_Property)
if not IsValidSharedPropChild1 andAlso not IsValidSharedPropChild2 then
e.Description = "You must enter at least one valid string for Shared_Child_Property"
return false
else
return true
end if
End Function
I don´t know why target.GetParent return 'nothing' in the first call( when -i call from Child_Create), but if i write any string on child1.Shared_Child_Property and then delete the error provider worksfine, because return a correct parent (root1) instead of return 'nothing'.
Any Ideas. Thanks Jose Luis
The Parent property isn't set until the child object is actually added as a child of the parent.
Creating the child object occurs first. Then the child is added as a child of the parent.
The DataPortal_Create() method is what is creating the child. This occurs before the object is assigned to its parent.
Thanks Rocky.
I read your book and I would need to catch FieldDataDeserialized() method in root1 to call validationrules.checkrules.
But I solved this problem calling ValidationRules.CheckRules from DataPortal_OnDataPortalInvokeComplete, in this method I check
If ApplicationContext.ExecutionLocation = _
ApplicationContext.ExecutionLocations.Client AndAlso _
e.Operation = (DataPortalOperations.Create) Then
'''''''''''''''EnforceValidationRulesOn Child1 and Child2 Shared_Property'''''''''''
Child1.EnforceValidationManually
Child2.EnforceValidationManually
end if
Because this 2 rules are dependants, but theirs locations are in distincts childproperties,
I had to add this lines in Set Block of each Shared_Property.
For Shared_Property in child1 I do:
Set(ByVal value As String)
SetProperty(Of String)( Shared_Property, value.Trim)
Dim parent As Object = TryCast(Me.Parent, root1)
If parent IsNot Nothing Then
CType(parent, root).Child2.EnforceValidationManually
End If
End Set
This line call the ValidationRule for child2.SharedProperty, but NOT REMOVE the broken rule because Property_Changed has not been fired.
Is there any way easier to do this?
If I have 2 dependant properties to validate in 2 diferents editablechild properties, how do i to create a ruleDependant?
Thanks
I typically put this kind of rule in the parent object, not in the child. The parent object knows when the child object is created, and when it changes, so it is a simple location to put this type of rule.
Hi Rocky, thanks for your answer
I have a Root: ---> CustomerA
And 2 Childs -----> HomePhone
------------------> These childs props are sharing PhoneNumerProperty(String)
------->WorkPhone
I choose this implementation because i don't want to save null values in my database.
I put the rule in the parent like you suggest me, in this way:
This is my code:
<Serializable()> _
Public Class CustomerA
Inherits BusinessBase(Of CustomerA)
.........
''''''' this is Child1
Private Shared HomePhoneProperty As PropertyInfo(Of HomePhone) = RegisterProperty(New PropertyInfo(Of HomePhone)("HomePhone", "HomePhone"))
''' <Summary>
''' Gets the HomePhone value.
''' </Summary>
Public ReadOnly Property HomePhone() As HomePhone
Get
If Not FieldManager.FieldExists(HomePhoneProperty) Then
LoadProperty(Of HomePhone)(HomePhoneProperty, HomePhone.NewHomePhone)
End If
Return GetProperty(HomePhoneProperty)
End Get
End Property
''''''' this is Child2
Private Shared WorkPhoneProperty As PropertyInfo(Of WorkPhone) = RegisterProperty(New PropertyInfo(Of WorkPhone)("WorkPhone", "WorkPhone"))
''' <Summary>
''' Gets the WorkPhone value.
''' </Summary>
Public ReadOnly Property WorkPhone() As WorkPhone
Get
If Not FieldManager.FieldExists(WorkPhoneProperty) Then
LoadProperty(Of WorkPhone)(WorkPhoneProperty, WorkPhone.NewWorkPhone)
End If
Return GetProperty(WorkPhoneProperty)
End Get
End Property
........
Protected Overrides Sub AddBusinessRules()
ValidationRules.AddRule(Of CustomerA)(AddressOf ValidateAtLeat1Phone(Of CustomerA), HomePhoneProperty, 3)
ValidationRules.AddRule(Of CustomerA)(AddressOf ValidateAtLeat1Phone(Of CustomerA),WorkPhoneProperty, 3)
ValidationRules.AddDependentProperty(HomePhoneProperty, WorkPhoneProperty, True)
End Sub
Private Shared Function ValidateAtLeat1Phone(Of T As CustomerA)( _
ByVal target As T, _
ByVal e As Validation.RuleArgs) As Boolean
dim hasHomePhone as boolean= not String.IsNullOrEmpty(target.HomePhone.PhoneNumer)
dim hasWorkPhone as boolean= not String.IsNullOrEmpty(target.WorkPhone.PhoneNumer)
dim IsValidRule as boolean = not hasHomePhone AndAlso hasWorkPhone)
if not IsValidRule then
e.Description= "You must enter 1 phone number"
end if
Return IsValidRule
End Function
End Class
When I create the root, the ValidateAtLeat1Phone is called but the errorprovider no catch it , so the description of broken rule is not shown, and also the function is not fired when I change PhoneNumerProperty in a child.
What is my mistake?
How do i to fire this ruleMethod?
THANKS YOU VERY MUCH
Rocky, my first question when I design this Validation Rule was the following:
What is the OBJECT that handles the rule behavior?
My answer was: The object is the shared property(PhoneNumber) located in child property, so it is a good place to put the validation rule. The parent object(root object) has no responsability to handle this shared property, so to put the validation rule in this class is no sense.
In my UI i have 3 errorprovider controls, 1 for root and the others 2 for childs and also each error provider handles your own datasource (child class) so the root error provider has no responsability to manage the child property, because of this the rule broken is not shown. I could catch the root error provider in Property child events of root object in the UI and set error in the root error provider, but this idea violates encapsulation and normalization of behavior.
Copyright (c) Marimer LLC