Form Building

One Control, One Pattern

GPALControl: The Shared Base

Every control type -- button, input, checkbox, combo box, data grid, chart, and the rest -- derives from a shared base that provides the settings common to all of them: the visible label, an identifying name for logs, an enabled state, a tooltip, and an event handler. Each specific control type then adds only what is unique to it -- a checked state for checkboxes, a placeholder for text inputs, chart-specific options for charts. The shared settings are the same fluent calls no matter which control you are building.

// WithName, WithEnabled, WithCallback work the same on every control type

var saveButton = GPAL.ButtonFor("Save")

.WithName("SaveButton")

.WithEnabled(true)

.WithCallback<EventHandler>(SaveButton_Click)

.ForEvent(ControlEventType.Click);


var agreeCheckbox = GPAL.CheckboxFor("I agree to the terms");

NOTE

A callback that writes to its own control raises that control's event again, which calls the callback again, which writes again. It is the loop every form ends up guarding with a flag of its own, and GPAL watches for it so you do not have to: a callback entered while it is still running is reported as a WARNING naming the control. Nothing is blocked and nothing is refused, so a workflow that means to set a combo box from its own SelectedIndexChanged still can. On a handler attached with WithCallbackOffUIThread the same loop shows up as a queue that keeps growing rather than a callback inside itself, and GPAL names that instead.

Assembling a Form

GPAL.Form starts the form chain. WithTitle, WithWidth, WithHeight, WithLeft, and WithTop set up the window itself. Each control is passed to WithFormControl, which can be called repeatedly to add controls one at a time. The form does not need to know what type each control is -- it arranges whatever object it receives.

var form = GPAL.Form

.WithTitle("Customer Entry")

.WithWidth(600)

.WithHeight(400)

.WithFormControl(GPAL.InputFor("Customer Name"))

.WithFormControl(GPAL.InputFor("Email Address"))

.WithFormControl(GPAL.ButtonFor("Submit"))

.ToGPALObject();

Picking the Right Control

Every control has a shorthand constructor on GPAL -- ButtonFor, InputFor, CheckboxFor, ComboBoxFor, and so on -- that returns the concrete type directly, no cast required. That typed variable is what you wire up: attach callbacks, set properties at runtime, and read values back after the form closes. GPAL covers every common need: single and multi-line text, yes/no and one-of-many choices, lists, grids, tree views, date and number pickers, file selectors, progress bars, status strips, and layout panels.

WARNING

Passing a control directly to WithFormControl without assigning it to a variable first creates a display-only control -- there is no reference to attach a callback to or read a value from after the form closes. Use the shorthand inline only for controls you never need to interact with in code.

💬 Ask GPAL