How can I clear broken rules?

How can I clear broken rules?

Old forum URL: forums.lhotka.net/forums/t/3109.aspx


JoeFallon1 posted on Wednesday, June 27, 2007

I have code like this:

myBO = DirectCast(myOtherBO.Clone, MyType)

'myBO still contains all the Broken Rules from myOtherBO which causes them to appear twice on screen.
'Need to clear it.
'JF 6/27/07 - this code does not work.
Dim ruleCollection As Csla2.Validation.BrokenRulesCollection = myBO.BrokenRulesCollection
Dim item As Csla2.Validation.BrokenRule = ValidationRules.GetBrokenRules.Item(index)

For i As Integer = ruleCollection.Count - 1 To 0 Step -1
  item = ValidationRules.GetBrokenRules.Item(i)
  ValidationRules.GetBrokenRules.Remove(item)
Next

'The code above ends up calling this in ReadOnlyBindingList:

Protected Overrides Sub RemoveItem(ByVal index As Integer)
If Not IsReadOnly Then
 
Dim oldValue As Boolean = AllowRemove
  AllowRemove =
True
 
MyBase.RemoveItem(index)
  AllowRemove = oldValue
Else
 
Throw New NotSupportedException(My.Resources.RemoveInvalidException)
End If
End Sub

The code fails because IsReadOnly is set to True and cannot be changed externally.

Even if it worked it would probably make a mess of things since this isn't how Rocky clears the broken rules after he calls CheckRules.

He uses an IRuleMethod and also modifies the counters.

Friend Overloads Sub Remove(ByVal rule As IRuleMethod)
' we loop through using a numeric counter because
' removing items in a foreach isn't reliable
IsReadOnly = False
For index As Integer = 0 To Count - 1
If Me(index).RuleName = rule.RuleName Then
DecrementCount(Me(index))
RemoveAt(index)
Exit For
End If
Next
IsReadOnly = True
End Sub

On a side note -  I normally loop backwards over a collection when removing items as this way you are not affected when the index changes on all the items above the one you just removed. Is that a non-issue in this code block for some reason?

Bottom line - I need a way to remove all the broken rules for the cloned BO. And I do not want ot modify Csla directly if I do not have to.

Any ideas?

Joe

RockfordLhotka replied on Wednesday, June 27, 2007

If the object is somehow valid (has no broken rules) after being cloned, you should be able to call CheckRules() to re-run the rules and all the broken rules will disappear from the list.

Otherwise the object is invalid, so it should have broken rules Smile [:)]

Remember that you can override the cloning method, which should allow you to call CheckRules() on the clone before returning it as a result.

JoeFallon1 replied on Thursday, June 28, 2007

Rocky,

I have a real need to be able to remove a broken rule other than by re-running that rule.

 

I have a BO that contains other BOs and can't be saved if any of them are invalid.

But in some cases if a child BO is invalid, I don't really care and want to save it anyway.

In order to do this I need the BO to be valid and the only way to do that is to remove the broken rules. If I pass in the rules collection to a method like this it fails because the rules collection is read only.

Private Sub ClearBrokenRules(ByVal ruleCollection As Csla2.Validation.BrokenRulesCollection)
 
For i As Integer = ruleCollection.Count - 1 To 0 Step -1
    ruleCollection.RemoveAt(i)
 
Next
End Sub

I want to avoid making framework changes. Is there anyway to do this? Or will there be some way in a future version? If so, how will it be done?

Thanks.

=======================================================

I went with this for now because I really need this functionality. Plus it is exactly how the normal method works only instead of using a ruleMethod as a parameter I use the broken rule itself.

   'need a Public way to clear broken rules other than by calling CheckRules.

    Public Overloads Sub Remove(ByVal rule As BrokenRule)

      ' we loop through using a numeric counter because removing items in a foreach isn't reliable
      IsReadOnly = False
      For index As Integer = 0 To Count - 1
        If Me(index).RuleName = rule.RuleName Then
          DecrementCount(Me(index))
          RemoveAt(index)
          Exit For
        End If
      Next
      IsReadOnly = True

    End Sub

Makes it easy to code a ClearBrokenRules method like this:

Public Shared Sub ClearBrokenRules(ByVal ruleCollection As Csla2.Validation.BrokenRulesCollection)
 
For i As Integer = ruleCollection.Count - 1 To 0 Step -1
   
Dim brokenRule As Csla2.Validation.BrokenRule = ruleCollection.Item(i)
    ruleCollection.Remove(brokenRule)
 
Next
End Sub

 

Joe

 

xal replied on Wednesday, July 04, 2007

Why not make the rules be warnings instead of errors?
Or if you want them to be errors, (this may sound silly, but esentially solves your problem) you could have a "SaveAnyWay" property, that you can set to true, so when you set it, you call ValidationRules.CheckRules().

All your rules should check the "SaveAnyWay" property like:

If target.SaveAnyWay Then
e.Severity=RuleSeverity.Warning
Else
e.Severity= RuleSeverity.Error
End If

Or even easier:
If target.SaveAnyWay Then
Return True
End If

Which makes the rule valid.

Again, this may sound silly, but it certainly gets the job done. This way, you can display those broken rules to the user, and before saving, you set SaveAnyWay to true for each BO.
If you want it to be even nicer, you should set those properties _after_ cloning the bo, so that the one still bound displays the error, and after performing the DataPortal_Insert / Update you set SaveAnyWay back to false, so that the returning object is in the same state as the original. Make sure you do that before calling MarkOld, of course.

Andrés

jbarrett replied on Thursday, June 06, 2013

I have a list. In that list there is a Boolean field and only one row in the list can have that Boolean turned on. I thought I wanted to have a rule to validate. But the problem is, every row in the list shows an error (red 'x') even when one row has a valid value. How to I cross-validate other rows? I thought I should clear the broken rules upon each validate call, but since I can not clear out the broken rules, how do I do it? Or is there some other way to handle validation an entire list of data such that all rows are valid if any one row is valid?

 

thanks,

JonnyBee replied on Thursday, June 06, 2013

Hi,

Please make sure to start a new thread when you post a new question!!! 

Copyright (c) Marimer LLC