AyCode.Blazor/AyCode.Blazor.Components/docs/MGGRID/MGGRID_PARAMETERS.md

11 KiB

MgGrid — Parameters & Events

Part of the MgGrid system. See README.md for overview and component hierarchy.

Required Parameters

Parameter Type Description
SignalRClient AcSignalRClientBase SignalR client for server communication
Logger TLoggerClient Logger instance
GetAllMessageTag int SignalR tag for loading all items

CRUD Message Tags

Parameter Type Description
GetAllMessageTag int Tag for "get all items" request
GetItemMessageTag int Tag for "get single item" request
AddMessageTag int Tag for "add item" request
UpdateMessageTag int Tag for "update item" request
RemoveMessageTag int Tag for "remove item" request

These are bundled into a SignalRCrudTags during OnInitializedAsync. See AyCode.Services/docs/SIGNALR_DATASOURCE/README.md (in AyCode.Core repo) for details.

Data & Context Parameters

Parameter Type Description
DataSource IList<TDataItem> Bind with AcObservableCollection<TDataItem> for external data. If not set, grid creates its own.
ParentDataItem IId<TId>? Parent entity for detail grids. null = master grid.
KeyFieldNameToParentId string? Property name on TDataItem that references the parent's ID
ContextIds object[]? Additional context passed to AcSignalRDataSource constructor
CustomFilterCriteria string? Consumer-supplied base filter criteria (a DevExpress criteria string) — propagated to the data source, triggers reload; server parses + whitelists it. AND-merged with the grid's automatic FilterCriteria (ADR-0004 unified model). Renamed FilterTextCustomFilterTextCustomFilterCriteria (2026-07-16).

Display & Behavior Parameters

Parameter Type Default Description
Caption string typeof(TDataItem).Name Grid title (shown in fullscreen header)
GridName string "{TDataItem.Name}Grid" Name used in log messages
AutoSaveLayoutName string? "Grid{TDataItem.Name}" Base name for layout storage keys
EnableServerLayouts bool true Roams the UserSave layout tier via the SignalR server endpoint (see MGGRID_LAYOUT.md → Server Roaming). Server calls happen only on the Save/Load layout buttons.

Filter Panel

Parameter Type Default Description
FilterPanel RenderFragment? null Filter controls rendered below the toolbar (composed into the grid's ToolbarTemplate); the slot wraps them in a styled .mg-grid-filter-panel container with a built-in right-aligned Clear button. When set, the toolbar shows a Show/Hide Filters toggle (MGGRID_TOOLBAR.md).
ShowFilterPanel bool true Initial visibility of the filter panel; the toolbar toggle flips it at runtime (IsFilterPanelVisible / ToggleFilterPanel).
FilterPanelClearButtonText string "Clear Filters" Text of the panel's built-in Clear button (IMgGridBase.ClearFilterPanel — clears the panel's own filters; the filter row is untouched). Enabled only while a panel-owned criteria is active (HasActiveFilterPanelCriteria) — enabled + empty-looking controls = an invisible panel filter, surfaced on purpose.

Place MgGridFilterPanelTagBox components (from Components/Grids/) in the slot. Each applies a per-field IN(FieldName, selected...) criteria via IMgGridBase.SetFilterPanelCriteria → DevExpress SetFieldFilterCriteria; DevExpress AND-combines the per-field criteria with each other and with the user's filter row automatically (no clobber). Empty selection clears that field's criteria. Several components in one panel therefore narrow the grid cumulatively (field A and field B).

Seam split: MgTagBox itself is the pure, behavior-free DxTagBox seam (universal — usable anywhere). All grid wiring lives in the derived MgGridFilterPanelTagBox : MgTagBox, IMgGridFilterPanelComponent. Future filter components (dropdown, textbox, checkbox…) follow the same pattern: own Mg* seam + IMgGridFilterPanelComponent; when the second one lands, the shared glue (registration + criteria adapter) is to be extracted into a helper.

Ownership (shared per-field slot). DevExpress keeps ONE criteria slot per field — the filter row and the panel both write it (SetFieldFilterCriteria). The panel therefore only manages criteria its components recognize as their own shape (IMgGridFilterPanelComponent.OwnsCriteria — for the tag box: the IN(FieldName, ...) it writes). A value typed into the column's filter row (e.g. Contains("EUR")) is never cleared by the panel — not on hide, not by the Clear button; the tag box simply shows no selection for it (it is visible in the filter row, so it is not invisible filtering).

<FilterPanel>
    <MgGridFilterPanelTagBox TData="string" TValue="string" FieldName="Status"
                             Data="@_statusOptions" NullText="All statuses" />
</FilterPanel>

Lookup (foreign-key) columns. When the target column holds an ID (e.g. PartnerId) but users pick by name, bind the tag box to the lookup objects and let ValueFieldName supply the IDs. FieldName still names the grid column, so the emitted IN(PartnerId, 3, 7) matches the underlying data field — not the cell's display template:

<FilterPanel>
    <MgGridFilterPanelTagBox TData="Partner" TValue="int" FieldName="PartnerId"
                             Data="@Partners" ValueFieldName="Id" TextFieldName="Name"
                             NullText="All partners" />
</FilterPanel>

A nullable FK column (int?) behaves the same — rows whose value is null match no selection.

Sizing. MgGridFilterPanelTagBox defaults its SizeMode to the grid's (IMgGridBase.GridSizeMode) when the consumer leaves it unset, so the panel matches the grid's density with no per-component declaration. An explicit SizeMode always wins.

Layout. The panel is a flex row: controls sit side by side sharing the width and wrap to the next line only when they no longer fit (.mg-grid-filter-panel > *flex / min-width / max-width in mg-grid-info-panel.css; tune there for a different density). It is styled to read as its own band between the toolbar and the group panel, aligned with the native group panel via the grid's own SizeMode-adaptive tokens (--dxbl-grid-group-panel-container-padding-*). Since it is composed into the ToolbarTemplate it physically lives inside .dxbl-grid-toolbar-container; that container's padding is zeroed (:has(.mg-grid-toolbar-with-filter)) and each row supplies its own: the toolbar row (.mg-grid-toolbar-row) reuses the container's native padding tokens, the band reuses the group panel's. Separator above = the band's border-top; below = the container's native border-bottom. A consumer .hide-toolbar class (detail grids) therefore hides the panel together with the toolbar.

Persistence & visibility. The panel's criteria is part of the grid's persisted layout (GridPersistentLayout.FilterCriteria — the AutoSave tier and the server-roamed UserSave tier alike; see MGGRID_LAYOUT.md). Components register with the grid (IMgGridFilterPanelComponent, weakly held; MgGridFilterPanelTagBox does this automatically) and the grid reconciles them after layout restore (incl. on another machine), user-layout load, layout reset, and panel toggle:

  • panel visible → each component re-reads its field's criteria and re-selects (a restored panel filter is visible again); the restore (JS interop) and an async lookup Data arrive in arbitrary order — the tag box re-asserts its selection idempotently on every parameter pass while an owned criteria is active, tracking both the Data instance and its item count (an in-place fill — AcObservableCollection.Replace on a pre-created empty collection — is detected too, and triggers the editor's Reload(): DevExpress snapshots its item list and detects Data changes by reference, so an in-place fill would otherwise never resolve into tags), so tags resolve as soon as both exist; consumers can additionally force a re-run via IMgGridBase.RefreshFilterPanel() after a late lookup load;
  • panel hidden (toolbar toggle or ShowFilterPanel="false") → the components' own criteria are cleared — a panel filter never filters invisibly. Hiding the panel therefore deliberately discards the current selection (filter-row values survive, per Ownership above);
  • a per-field criteria the component does not own is left untouched — the component just shows no selection.

The panel content is always rendered (CSS-hidden when toggled off) so the components stay registered. Known edge — a layout with panel criteria loaded where the grid has no FilterPanel at all: MGGRID_ISSUES.mdACBLAZOR-GRID-I-D4T7.

Implementation note: imperative parameter writes inside DevExpress editors (Values, SizeMode) must be wrapped in BeginUpdate()/EndUpdate() (the parameter tracker throws otherwise) — MgGridFilterPanelTagBox handles this internally.

Design + the server-side forward path (FilterMode.Server): AyCode.Core repo docs/adr/0004-signalr-datasource-server-side-filtering.md.

Event Callbacks

All grid events are re-exposed with OnGrid prefix to avoid collisions with DxGrid base events:

Event DxGrid Equivalent When Fired
OnGridItemDeleting DataItemDeleting Before item removal (can cancel via e.Cancel)
OnGridEditModelSaving EditModelSaving Before item save (can cancel via e.Cancel)
OnGridEditStart EditStart When edit mode begins
OnGridCustomizeEditModel CustomizeEditModel When edit model is being prepared
OnGridFocusedRowChanged FocusedRowChanged When focused row changes
OnDataSourceChanged After data source is loaded/reloaded
OnGridItemChanged After server confirms a CRUD operation
OnGridItemChanging Before a CRUD operation is sent to server

Internal event wiring (in SetParametersAsyncCore, first call):

DxGrid Event → Internal Handler
DataItemDeleting OnItemDeleting
EditModelSaving OnItemSaving
CustomizeEditModel OnCustomizeEditModel
FocusedRowChanged OnFocusedRowChanged
EditStart OnEditStart
EditCanceling OnEditCanceling

Default Grid Settings

Set in SetParametersAsyncCore (first call only):

Setting Value
KeyFieldName "Id"
TextWrapEnabled false
AllowSelectRowByClick true
HighlightRowOnHover true
AutoCollapseDetailRow true
AutoExpandAllGroupRows false

Project adapters typically add more defaults in OnParametersSet (e.g., EditMode, FocusedRowEnabled, PageSize, ShowFilterRow, SizeMode based on IsMasterGrid).