Source of truth (audited 2026-04-09)
  • DataManagementEngineStandard/Editor/Forms/FormsManager.cs and partials
  • DataManagementEngineStandard/Editor/Forms/Interfaces runtime interface contracts
  • DataManagementEngineStandard/Editor/Forms/README.md
  • DataManagementEngineStandard/Editor/Forms/MIGRATION-GUIDE.md
Documentation status
  • This page reflects the audited FormsManager runtime surface and current public naming.
  • FormsManager is the orchestration runtime; IUnitofWork remains the persistence and dirty-state authority.
  • Built-in runtime operations, triggers, LOV orchestration, audit, security, paging, and multi-form flows are implemented in code.
Boundary reminder

FormsManager owns runtime orchestration and state semantics. Canvases, tab pages, cursor movement, LOV dialog rendering, and message-area rendering remain host-UI responsibilities.

Overview

FormsManager is the BeepDM form-orchestration runtime in the TheTechIdea.Beep.Editor.UOWManager namespace. It coordinates block registration, current-block state, navigation, query-mode and CRUD-mode transitions, master/detail synchronization, triggers, LOV application, savepoints, locks, audit capture, security enforcement, paging, cache control, and multi-form communication.

The current public runtime surface is documented here under the FormsManager name.

What this page covers
  • Current public runtime surface and partial-class layout
  • Caller-facing helper managers and orchestration boundaries
  • Mode transitions, CRUD flows, and built-in runtime operations
  • Examples for explicit keys, sequences, identity keys, defaults, audit, security, and paging

Runtime Ownership

Concern FormsManager IUnitofWork
Block orchestration Registers blocks, tracks current form and block, manages relationships No
Navigation and modes Owns query mode, CRUD mode, record navigation, history, and block switching No
Persistence Coordinates when to save, rollback, validate, or fire triggers Executes insert, update, delete, commit, rollback, and query operations
Dirty-state truth Aggregates state across blocks and relationships Owns per-block dirty tracking
Identity and sequence refresh Coordinates key strategy during create and insert flows Owns datasource-backed identity refresh and real sequence interaction
UI responsibilities Provides runtime state and semantics Not applicable

Signature Snapshot

Representative public surface

public partial class FormsManager
{
    public IDMEEditor DMEEditor { get; }
    public string CurrentFormName { get; set; }
    public string CurrentBlockName { get; set; }
    public IReadOnlyDictionary<string, DataBlockInfo> Blocks { get; }
    public bool IsDirty { get; }
    public int BlockCount { get; }

    public IDirtyStateManager DirtyStateManager { get; }
    public IPerformanceManager PerformanceManager { get; }
    public ISystemVariablesManager SystemVariables { get; }
    public IValidationManager Validation { get; }
    public ILOVManager LOV { get; }
    public IItemPropertyManager ItemProperties { get; }
    public ITriggerManager Triggers { get; }
    public ISavepointManager Savepoints { get; }
    public ILockManager Locking { get; }
    public IQueryBuilderManager QueryBuilder { get; }
    public IMessageQueueManager Messages { get; }
    public IBlockPropertyManager BlockProperties { get; }
    public ISequenceProvider Sequences { get; }
    public ITimerManager Timers { get; }
    public IFormRegistry Registry { get; }
    public IFormMessageBus MessageBus { get; }
    public ISharedBlockManager SharedBlocks { get; }
    public IAuditManager AuditManager { get; }
    public ISecurityManager Security { get; }
    public IPagingManager Paging { get; }

    public FormsManager(IDMEEditor dmeEditor, ...);

    public void RegisterBlock<T>(...);
    public DataBlockInfo GetBlock<T>(string blockName);
    public Task<bool> InsertRecordAsync<T>(string blockName, T record = default);
    public Task<LOVResult> ShowLOVAsync(...);
    public Task<bool> OpenFormAsync(string formName);
    public Task<IErrorsInfo> CommitFormAsync();
    public Task<IErrorsInfo> RollbackFormAsync();
    public Task<IErrorsInfo> EnterQueryModeAsync(string blockName);
    public Task<IErrorsInfo> ExecuteQueryAndEnterCrudModeAsync(string blockName, List<AppFilter> filters = null);
    public Task<bool> FirstRecordAsync(string blockName);
    public Task<bool> NextRecordAsync(string blockName);
    public Task<bool> PreviousRecordAsync(string blockName);
    public Task<bool> LastRecordAsync(string blockName);
    public Task<bool> NavigateToRecordAsync(string blockName, int recordIndex);
}

Partial-Class Topology

File Responsibility
FormsManager.csCore registration, DI wiring, properties, relationship ownership, and block metadata
FormsManager.FormOperations.csOpen, close, commit, rollback, clear-form, and clear-block orchestration
FormsManager.Navigation.csRecord navigation, block switching, history, and GO_BLOCK-style behavior
FormsManager.ModeTransitions.csENTER_QUERY, EXECUTE_QUERY, and CRUD-mode transitions
FormsManager.EnhancedOperations.csInsert, update, delete, audit defaults, and enhanced CRUD orchestration
FormsManager.DataOperations.csUndo/redo, duplicate record, batch commit, export/import, aggregates, and state persistence
FormsManager.GenericOperations.csTyped block registration, typed insert, typed block access, and ShowLOVAsync
FormsManager.BlockProperties.csSET_BLOCK_PROPERTY and GET_BLOCK_PROPERTY wrappers
FormsManager.Alerts.csMESSAGE, alert, confirm, and info-dialog orchestration
FormsManager.Sequences.csSequences, item defaults, copy-field behavior, and record-group helpers
FormsManager.Timers.csCREATE_TIMER, DELETE_TIMER, timer inspection, and trigger integration
FormsManager.MultiFormNavigation.csCALL_FORM, modeless OPEN_FORM, NEW_FORM, and return-to-caller
FormsManager.InterFormComm.cs:GLOBAL.*, parameter handoff, message bus, and shared blocks
FormsManager.KeyTriggers.csKEY-* trigger registration and default key-action helpers
FormsManager.TriggerChaining.csTrigger dependency graph, chain mode, and execution logging
FormsManager.DmlTriggers.csON-INSERT, ON-UPDATE, ON-DELETE, and programmatic trigger raising
FormsManager.Audit.csAudit configuration, audit querying, export, and purge behavior
FormsManager.Security.csSecurity context, block security, field security, and masking
FormsManager.Performance.csPaging, fetch-ahead, cache invalidation, cache stats, and performance wiring

Helper Manager Surface

FormsManager exposes most subsystem capabilities through helper properties so callers can use low-level behavior without re-implementing orchestration. In normal application code, start with FormsManager entry points and reach for helper managers only when you need custom registration or inspection behavior.

Property Interface Purpose
DirtyStateManagerIDirtyStateManagerAggregates unsaved changes, related dirty blocks, and save or rollback decisions
PerformanceManagerIPerformanceManagerCache and performance metrics infrastructure
SystemVariablesISystemVariablesManager:SYSTEM.* runtime variables
ValidationIValidationManagerItem, record, block, and form validation rules
LOVILOVManagerLOV registration, datasource loading, caching, filtering, and value validation
ItemPropertiesIItemPropertyManagerEnabled, visible, read-only, tab order, and field metadata behavior
TriggersITriggerManagerTrigger registration, ordering, scope resolution, and async execution
SavepointsISavepointManagerNamed snapshots and rollback targets
LockingILockManagerClient-side record locking and auto-lock behavior
QueryBuilderIQueryBuilderManagerReusable filter and query templates for blocks
ErrorLogIBlockErrorLogPer-block runtime error tracking without UI coupling
MessagesIMessageQueueManagerStatus and informational message queue for host UI consumption
BlockFactoryIBlockFactoryBuilds UnitOfWork and entity metadata pairs from configured connections
BlockPropertiesIBlockPropertyManagerBacks SET_BLOCK_PROPERTY and GET_BLOCK_PROPERTY
AlertProviderIAlertProviderHost-UI alert bridge for ShowAlertAsync, ConfirmAsync, and info prompts
SequencesISequenceProviderIn-memory sequence support and deterministic test flows
TimersITimerManagerNamed timer lifecycle and WHEN-TIMER-EXPIRED integration
RegistryIFormRegistryActive-form registry for modal and modeless multi-form flows
MessageBusIFormMessageBusPublish, subscribe, and broadcast form messages
SharedBlocksISharedBlockManagerCross-form shared UnitOfWork-backed blocks
AuditManagerIAuditManagerAudit capture, history queries, grouped flush, and storage integration
SecurityISecurityManagerBlock security, field security, masking, and violation logging
PagingIPagingManagerPage size, total-record count, current page, and fetch-ahead tracking
Practical rule

Use FormsManager methods for orchestration entry points like commit, rollback, query, navigation, and LOV application. Use helper managers for registration, inspection, custom rule wiring, or host-specific integration.

Form Lifecycle and Mode Transitions

The normal lifecycle is open form, register blocks, enter query mode when needed, execute a query, navigate, edit, and commit or rollback through a single form-level orchestration point.

Lifecycle example

var manager = new FormsManager(dmeEditor)
{
    CurrentFormName = "CUSTOMER_ORDERS"
};

await manager.OpenFormAsync("CUSTOMER_ORDERS");
await manager.EnterQueryModeAsync("CUSTOMERS");

var filters = new List<AppFilter>
{
    new AppFilter { FieldName = "Country", Operator = "=", FilterValue = "USA" }
};

await manager.ExecuteQueryAndEnterCrudModeAsync("CUSTOMERS", filters);
await manager.FirstRecordAsync("CUSTOMERS");
await manager.NextRecordAsync("CUSTOMERS");

var result = await manager.CommitFormAsync();
if (result.Flag != Errors.Ok)
{
    await manager.RollbackFormAsync();
}
Operation Method Notes
Open current form runtimeOpenFormAsync(string formName)Initializes the current form lifecycle and state
Close current formCloseFormAsync()Performs shutdown orchestration and cleanup
Enter query modeEnterQueryModeAsync(string blockName)Switches the target block into query mode
Execute query and return to CRUD modeExecuteQueryAndEnterCrudModeAsync(...)Runs filters, reloads block data, then restores normal editing mode
Navigate recordsFirstRecordAsync, NextRecordAsync, PreviousRecordAsync, LastRecordAsync, NavigateToRecordAsync, GoRecordAsyncValidation and history are part of the orchestration path
Switch blocks and itemsSwitchToBlockAsync, GoBlockAsync, NextBlockAsync, PreviousBlockAsync, GoItemAsync, NextItemAsync, PreviousItemAsyncUpdates current block context, item focus metadata, and block-instance behavior
Commit formCommitFormAsync()Runs validation, trigger wiring, dirty-state save, audit flush, and lock cleanup
Rollback formRollbackFormAsync()Restores dirty blocks and clears transient state

Block Registration and CRUD Flow

Prefer typed registration so FormsManager can create records with the correct CLR type, use typed accessors, and keep new-record flows compatible with validation, LOVs, audit, and key generation.

Typed block registration and master-detail wiring

manager.RegisterBlock<CustomerDto>(
    blockName: "CUSTOMERS",
    unitOfWork: customerUow,
    entityStructure: customerEntity,
    dataSourceName: "Northwind",
    isMasterBlock: true);

manager.RegisterBlock<OrderDto>(
    blockName: "ORDERS",
    unitOfWork: orderUow,
    entityStructure: orderEntity,
    dataSourceName: "Northwind");

manager.CreateMasterDetailRelation(
    masterBlockName: "CUSTOMERS",
    detailBlockName: "ORDERS",
    masterKeyField: "CustomerId",
    detailForeignKeyField: "CustomerId");

var orderBlock = manager.GetBlock<OrderDto>("ORDERS");
await manager.InsertRecordAsync<OrderDto>("ORDERS", new OrderDto { Status = "Draft" });

Duplicate, export, and import

await manager.DuplicateCurrentRecordAsync("ORDERS");

using var jsonStream = new MemoryStream();
await manager.ExportBlockToJsonAsync("ORDERS", jsonStream);

jsonStream.Position = 0;
await manager.ImportBlockFromJsonAsync("ORDERS_ARCHIVE", jsonStream, clearFirst: true);
Master/detail ownership

Relationship registration, key resolution, and detail synchronization are FormsManager concerns. Keep UnitOfWork focused on entity persistence rather than relationship orchestration.

Key Generation and Record Creation

Key handling is part of the new-record and insert pipeline. FormsManager coordinates the strategy, but the datasource-backed UnitOfWork remains the authority for persisted identities and real sequence refresh.

  1. Preserve explicit keys supplied by caller, default factory, or trigger.
  2. Leave datasource-managed identity keys unset until insert or commit refresh completes.
  3. Prefer datasource or UnitOfWork sequence generation before the in-memory FormsManager sequence provider.
  4. Use FormsManager sequences for deterministic tests or non-database-backed flows.
  5. Handle composite keys field by field.
  6. Do not allocate keys during query, paging, navigation, or cache prefetch.

Explicit key preserved

await manager.InsertRecordAsync<CustomerDto>("CUSTOMERS", new CustomerDto
{
    CustomerId = "ALFKI",
    CompanyName = "Alfreds Futterkiste"
});

Sequence-backed key

manager.SetItemDefault("ORDERS", "Status", () => "Draft");

var nextNumber = manager.GetNextSequence("ORDER_SEQ");

await manager.InsertRecordAsync<OrderDto>("ORDERS", new OrderDto
{
    OrderNumber = nextNumber,
    CustomerId = "ALFKI"
});

Datasource identity key

await manager.InsertRecordAsync<OrderLineDto>("ORDER_LINES", new OrderLineDto
{
    OrderId = existingOrderId,
    ProductId = 12,
    Quantity = 3
    // Leave identity key unset. The datasource refresh path populates it after insert or commit.
});

Default-value factory

manager.SetItemDefault("ORDERS", "CreatedAt", () => DateTime.UtcNow);
manager.SetItemDefault("ORDERS", "CreatedBy", () => Environment.UserName);

await manager.InsertRecordAsync<OrderDto>("ORDERS", new OrderDto());

Built-in Runtime Operations

Area FormsManager surface Notes
Block propertiesSetBlockProperty, GetBlockProperty, SetDefaultWhere, SetOrderBy, SetInsertAllowed, SetUpdateAllowed, SetDeleteAllowed, SetQueryAllowedBacked by DataBlockInfo and the block-property manager
NavigationSwitchToBlockAsync, GoBlockAsync, NextBlockAsync, PreviousBlockAsync, GoItemAsync, NextItemAsync, PreviousItemAsync, GoRecordAsync, NavigateToRecordAsync, FirstRecordAsync, NextRecordAsync, PreviousRecordAsync, LastRecordAsyncItem focus metadata is runtime-owned; actual cursor rendering remains UI-owned
Messages and alertsSetMessage, ClearMessage, ShowAlertAsync, ConfirmAsync, ShowInfoAsyncBacked by injected IAlertProvider
LOV orchestrationShowLOVAsync, LOV.RegisterLOVRuntime loads and applies values; visual dialog remains UI-owned
Defaults and copySetItemDefault, CopyFieldValueApplied during new-record and field-copy flows
SequencesGetNextSequence, PeekNextSequence, ResetSequence, CreateSequencePrefer datasource or UnitOfWork sequence generation first
TimersCreateTimer, DeleteTimer, GetTimer, GetAllTimersTimer expiration feeds WHEN-TIMER-EXPIRED
System variablesSystemVariablesRepresents :SYSTEM.* runtime state

Built-in usage example

manager.SetDefaultWhere("ORDERS", "IsDeleted = 0");
manager.SetOrderBy("ORDERS", "OrderDate desc");
manager.SetInsertAllowed("ORDERS", true);

var timer = manager.CreateTimer("REFRESH_ORDERS", TimeSpan.FromSeconds(30), repeating: true);
var confirmed = await manager.ConfirmAsync("Commit", "Save all pending changes?");

if (confirmed)
{
    await manager.CommitFormAsync();
}

Multi-Form, Globals, and Messaging

FormsManager implements modal and modeless form flows through the form registry, call stack, globals, parameter handoff, message bus, and shared block manager.

Concept Method Behavior
Current form openOpenFormAsync(string formName)Initializes the current form lifecycle
Modal child formCallFormAsync(..., FormCallMode.Modal)Suspends caller until child returns
Modeless child formOpenFormAsync(string formName, Dictionary<string, object> parameters)Independent child runtime tracked by the registry
Replace formNewFormAsyncReplaces the current form in the registry and call flow
Return to callerReturnToCallerAsyncCan hand return data back to the calling form
Global valuesSetGlobalVariable, GetGlobalVariableRepresents :GLOBAL.*
Parameter handoffCallFormAsync, OpenFormAsync, GetFormParameterCaller passes named parameters to target form
Inter-form messagingPostMessage, SubscribeToMessage, UnsubscribeFromMessagePublish and receive messages through the shared bus
Shared UnitOfWork blocksCreateSharedBlock, SharedBlocksExpose UoW-backed blocks across form instances

Modal form, globals, and messaging

manager.SetGlobalVariable("ACTIVE_CUSTOMER_ID", "ALFKI");

manager.SubscribeToMessage("CustomerChanged", message =>
{
    Console.WriteLine($"Received {message.MessageType} from {message.SenderForm}");
});

manager.PostMessage("ORDER_FORM", "CustomerChanged", "ALFKI");

await manager.CallFormAsync(
    "ORDER_FORM",
    new Dictionary<string, object> { ["CustomerId"] = "ALFKI" },
    FormCallMode.Modal);

Triggers, Validation, and LOVs

Trigger system

FormsManager wires trigger behavior across insert, update, delete, query, commit, navigation, key events, and timer expiration. Trigger chaining, dependency tracking, and execution logging are part of the runtime.

Key trigger registration

manager.RegisterKeyTrigger(
    KeyTriggerType.KEY_COMMIT,
    "ORDERS",
    args =>
    {
        Console.WriteLine("Commit key trigger fired");
        return Task.CompletedTask;
    });
Capability Surface Notes
Scope-aware trigger registrationTriggers managerForm, block, item, and global scope
Key triggersRegisterKeyTrigger, RegisterKeyTriggerAsync, FireKeyTriggerAsyncIncludes default actions like commit and navigation
DML triggersON-INSERT, ON-UPDATE, ON-DELETEInvoked through DML trigger partials
Programmatic trigger raisingRaiseFormTriggerAsyncUse when the caller must explicitly invoke a named trigger
Trigger librariesTriggerLibraryProvides audit stamp, auto-number, cascade delete, and field-format helpers
Dependency graph and loggingFormsManager.TriggerChaining.csSupports ordered execution and diagnostics

Validation

Validation rules can run at item, record, block, form, and cross-block scope. FormsManager integrates validation into field changes, query transitions, navigation, and commit flows.

Validation registration example

manager.Validation.RegisterItemRule("ORDERS", "Quantity", value =>
{
    return value is int quantity && quantity > 0
        ? ValidationResult.Success()
        : ValidationResult.Failure("Quantity must be greater than zero.");
});

LOV orchestration

Register LOV definitions through the LOV helper, then apply a selected row through ShowLOVAsync. That keeps data loading, cache reuse, and related-field population inside the FormsManager orchestration path.

LOV registration and application

var customerLov = LOVDefinition
    .CreateLookup("CUSTOMER_LOV", "Northwind", "Customers", "CustomerId", "CompanyName")
    .MapField("CompanyName", "CustomerName");

manager.LOV.RegisterLOV("ORDERS", "CustomerId", customerLov);

var lovResult = await manager.ShowLOVAsync("ORDERS", "CustomerId", searchText: "alf");
var selected = lovResult.Records.FirstOrDefault();

if (selected != null)
{
    await manager.ShowLOVAsync("ORDERS", "CustomerId", selectedRecord: selected);
}
LOV return-field behavior

LOVManager uses an internal __RETURN_VALUE__ sentinel. Callers should prefer FormsManager.ShowLOVAsync because it translates that sentinel back to the real bound field name before applying the selected values to the current record.

Audit, Security, and Performance

Area Representative methods Notes
AuditSetAuditUser, ConfigureAudit, GetAuditLog, GetFieldHistory, ExportAuditToCsvAsyncField-change feed plus pluggable audit stores
SecuritySetSecurityContext, SetBlockSecurity, SetFieldSecurity, GetMaskedFieldValueUI disabling is not the only protection; runtime CRUD checks still enforce rules
PagingSetBlockPageSize, SetTotalRecordCount, LoadPageAsync, SetFetchAheadDepthPagingManager tracks state; it does not query the datasource by itself
Cache and metricsInvalidateBlockCache, SetBlockCacheTtl, GetCacheStats, CheckCacheMemoryPressurePerformance manager owns cache statistics and eviction-related behavior

Audit, security, and paging example

manager.SetAuditUser("fahad");
manager.ConfigureAudit(config =>
{
    config.Enabled = true;
    config.AuditedBlocks.Add("ORDERS");
});

manager.SetSecurityContext(new SecurityContext
{
    UserName = "fahad",
    Roles = new List<SecurityRole>
    {
        new SecurityRole
        {
            Name = "OrderClerk",
            Permissions = SecurityPermission.Query | SecurityPermission.Update
        }
    }
});

manager.SetBlockPageSize("ORDERS", 50);
manager.SetTotalRecordCount("ORDERS", 1200);
manager.SetFetchAheadDepth("ORDERS", 2);

var page = await manager.LoadPageAsync("ORDERS", 3);
var auditEntries = manager.GetAuditLog("ORDERS");
var cacheStats = manager.GetCacheStats();

Coverage Snapshot

Forms runtime concept FormsManager equivalent Status
ENTER_QUERYEnterQueryModeAsyncImplemented
EXECUTE_QUERYExecuteQueryAndEnterCrudModeAsync, ExecuteQueryAsyncImplemented
COMMIT_FORMCommitFormAsyncImplemented
ROLLBACK_FORMRollbackFormAsyncImplemented
SHOW_LOVShowLOVAsync plus LOV.RegisterLOVImplemented in runtime; visual chooser remains UI-owned
SET_BLOCK_PROPERTY / GET_BLOCK_PROPERTYSetBlockProperty, GetBlockPropertyImplemented
CALL_FORM / OPEN_FORM / NEW_FORMCallFormAsync, overloads of OpenFormAsync, NewFormAsyncImplemented
:GLOBAL.*SetGlobalVariable, GetGlobalVariableImplemented
MESSAGE / SHOW_ALERTSetMessage, ClearMessage, ShowAlertAsync, ConfirmAsyncImplemented
CREATE_TIMER / DELETE_TIMERCreateTimer, DeleteTimerImplemented
PRE or POST triggers, DML triggers, KEY-* triggersTriggers, key-trigger wrappers, DML trigger partials, chaining supportImplemented
Audit trailAuditManager, audit configuration, export, history queriesImplemented
Security and maskingSecurity, block and field security, maskingImplemented
Paging and cache controlPaging, PerformanceManager, cache invalidation helpersImplemented

Known Boundaries and Hardening Areas

UI-owned boundaries
  • canvases and tab pages
  • focus rendering and cursor movement between visible controls
  • LOV dialog presentation and row-selection UI
  • keyboard routing from host controls into key-trigger execution
  • status-area and message-area rendering
Residual hardening areas
  • Some CRUD and update seams still rely on reflection-based fallback paths rather than strongly typed UnitOfWork contracts.
  • Programmatic RaiseFormTriggerAsync usage should continue to be reviewed where explicit trigger-raise semantics are expected.
  • Remote cache invalidation remains dependent on the broader host integration and datasource notification model.