Form Lifecycle Events and Firing Order
SyteLine forms follow a predictable event sequence during load, navigation, save, and delete operations. When a form opens, StdFormLoaded fires first, followed by StdObjectLoaded for the initial record. When users navigate between records, StdObjectLoaded fires for each record displayed.
During saves, StdFormPreSave fires before validation, StdObjectSaved fires after the successful save, and StdFormPostSave completes the cycle. Understanding this sequence prevents common bugs like running validation logic after the save has already committed.
- Form open sequence: StdFormLoaded → StdObjectLoaded (fires for first loaded record)
- Record navigation: StdObjectLoaded fires each time a new record is displayed in the form
- Save sequence: StdFormPreSave → (IDO UpdateCollection) → StdObjectSaved → StdFormPostSave
- New record: StdObjectNew fires when user clicks New, before any data entry on the blank record
- Delete: StdObjectDeleted fires after the IDO DeleteCommand completes successfully
Implementing Common Event Handler Patterns
The most frequent event handler use cases include setting default values on new records, enforcing field-level validation before saves, computing derived fields when data loads, and refreshing dependent controls after saves. For default values, use StdObjectNew to populate fields like dates, status codes, and user-specific defaults. GenerateMessage and setting Cancel = true to block invalid saves.
For computed fields, use StdObjectLoaded to calculate totals, format display values, and control field visibility.
- Default values in StdObjectNew: ThisForm.PrimaryIDOCollection.SetCurrentObjectProperty("Status", "N")
- Pre-save validation: if (string.IsNullOrEmpty(custNum)) { e.Cancel = true; ThisForm.GenerateMessage(...); }
- Computed fields in StdObjectLoaded: totalAmount = qty * unitPrice; SetCurrentObjectProperty("ExtAmount", totalAmount)
- Post-save refresh: StdObjectSaved handler reloads related grids using ThisForm.Components["GridName"].Refresh()
- Conditional logic in StdObjectLoaded: enable/disable fields based on Status or Type property values
Event Handler Best Practices and Pitfalls
Several common mistakes in event handler development cause subtle bugs that are difficult to trace. Modifying property values in StdObjectLoaded without checking if the form is in a dirty state triggers an unintended save prompt. Performing long-running operations in StdFormPreSave makes the form appear to freeze.
Calling IDO methods in StdObjectNew before the record context is fully initialized causes null reference exceptions. Always test your event handlers with rapid record navigation, bulk operations, and concurrent user scenarios to catch race conditions.
- Check form dirty state before setting values in StdObjectLoaded: if (!ThisForm.PrimaryIDOCollection.IsDirty)
- Use async patterns for long operations in event handlers; never block the UI thread for more than 200ms
- Avoid circular event triggers: setting a property in StdObjectLoaded should not re-fire the same event
- Test with rapid F5/F6 navigation between records to catch StdObjectLoaded timing issues
- Log event handler entry/exit in development: helps trace the exact firing sequence during debugging
Try it here, free
SyteLine Form Personalization Checklist
A practical checklist for scoping, building, testing, documenting and upgrading SyteLine form personalizations without creating upgrade debt.
Netray AI agents generate complete event handler implementations with proper lifecycle awareness, validation patterns, and error handling. Build robust SyteLine forms faster.