Skip to content

Validate bound objects and report errors

Push pending control edits, trigger business-object rule evaluation, harvest and aggregate error messages, and re-style controls.

Field Value
Operation ID OP-BIND-005
Trigger binder.Validate() (or RefreshValidation()), typically on Save
Inputs Registered binders, registered validation objects
Outputs Boolean overall validity; populated ErrorLabel / SAIFMessage; controls re-styled; FirstControlWithError set
Primary components clsObjectBindManager.Validate, ValidateBindSources, each binder's GetErrors, clsCustomValidator.PerformValidation, clsObjectBinderBase.SetControlFormat
Entry point SAIF.Presentation.Web.Binding.Infragistics111/clsObjectBindManager.vb

Steps

  1. Call BindToObject() so that non-event-driven controls have pushed their values before validation (see Pull control values back into objects). (BR-BIND-027)
  2. Clear the aggregated error list and reset m_FirstErrorControl. (BR-BIND-028)
  3. Call ValidateBindSources(), which iterates every registered validation object, resolves its IsValid property via TypeDescriptor and reads it. Reading IsValid is what causes the SAIF BOF business object to run its rules and populate its error messages.* (BR-BIND-029)
  4. Delegates to the business object's IsValid implementation (clsBusinessBase / clsBusinessCollectionBase, SAIF.Framework.Core): broken rules evaluated by clsRulesManager make IsValid False and populate the object's broken-rules collection.†

Origin: This rule-evaluation step is implemented in SAIF.Framework.Core / clsBusinessBase and executed on behalf of this operation; its internal steps are not visible from this repository.**

  1. For each binder: if it is a custom validator, call PerformValidation(); otherwise call GetErrors(). (BR-BIND-030)
  2. GetErrors selects the property/object pair to inspect — the validation property/source for a dual binder, otherwise the bind property/source — casts the object to IDataErrorInfo, and reads Item(property). (BR-BIND-031)
  3. When the error text is non-empty, set the binder's error flag, split the text on CRLF, strip <BR> markup from each fragment, and add each non-blank fragment to the binder's ControlErrors. (BR-BIND-032) (BR-BIND-033)
  4. For a binder with errors: set the overall result to False, add each message to the manager's error list only if not already present, record the binder's control as FirstControlWithError if none has been recorded yet, and call SetControlFormat(False). (BR-BIND-034) (BR-BIND-035)
  5. For a binder without errors: call SetControlFormat(True), except when the binder's control is the already-recorded first error control (so an error-styled control is not reset by a second, clean binding on the same control). (BR-BIND-036)
  6. SetControlFormat(False) applies errorbordercolor to multiline text boxes and check boxes, errorbackcolor to everything else, and leaves UltraWebGrid / WebDataGrid untouched. (BR-BIND-037) (BR-BIND-038)
  7. SetControlFormat(True) leaves any control already styled disabledbackcolor untouched, sets normal on labels, clears the class on check boxes, skips grids, and otherwise applies defaultbackcolor. (BR-BIND-039) (BR-BIND-040)
  8. Assign FormattedErrorMessage — the distinct messages joined by <BR> — to ErrorLabel.Text and SAIFMessage.Text when those properties are set. (BR-BIND-041) (BR-BIND-042)
  9. Return True only when no binder reported an error.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Validate / RefreshValidation]) --> S1[BindToObject]
    S1 --> S2[Clear error list and first-error-control]
    S2 --> D0{RefreshValidation?}
    D0 -->|No| S3[ValidateBindSources: read IsValid on each source]
    D0 -->|Yes| S4[Skip source validation]
    S3 --> S5[For each binder: GetErrors or PerformValidation]
    S4 --> S5
    S5 --> D{Errors found?}
    D -->|Yes| S6[Aggregate distinct messages<br>SetControlFormat False]
    D -->|No| S7[SetControlFormat True]
    S6 --> S8["ErrorLabel.Text / SAIFMessage.Text = FormattedErrorMessage"]
    S7 --> S8
    S8 --> End([Return overall validity])

Failure and edge-case behavior

  • RefreshValidation() repeats steps 1, 2 and 4–12 above but omits step 3 (ValidateBindSources), so it re-renders existing error state without asking the business objects to re-evaluate (BR-BIND-043).
  • A property-type custom validator delegate appends messages to ControlErrors directly, but PerformValidation never sets the binder's internal error flag in that branch — so those messages do not mark the binder as erroring and may not surface through Validate().*

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified. Statements marked with † were retrieved from dependency library documentation via the Legends CLI RAG service.

Sources

  • SAIF.Presentation.Web.Binding.Infragistics111/clsObjectBindManager.vb