4.6 KiB
4.6 KiB
MgGrid — Lifecycle & CRUD
Part of the MgGrid system. See
README.mdfor overview and component hierarchy.
Lifecycle
1. OnInitializedAsync()
├── Validate Logger, SignalRClient (throw if null)
├── Create SignalRCrudTags from message tag parameters
├── Create TSignalRDataSource via Activator.CreateInstance(SignalRClient, crudTags, ContextIds)
├── Set DataSource.FilterText
├── Bind grid Data to data source inner list
└── Subscribe to: OnDataSourceLoaded, OnDataSourceItemChanged, OnSyncingStateChanged
2. SetParametersAsyncCore() [first time]
├── Set KeyFieldName = "Id"
├── Wire 6 DxGrid events → internal handlers (see MGGRID_PARAMETERS.md)
├── Add OnCustomizeElement handler (edit row highlighting, detail cell styling)
└── Set defaults: TextWrapEnabled=false, AllowSelectRowByClick=true, etc.
3. OnParametersSet() [first time]
├── Set GridName default: "{TDataItem.Name}Grid"
├── Set AutoSaveLayoutName default: "Grid{TDataItem.Name}"
├── Wire layout auto-loading/saving handlers
└── Register with GridWrapper via GridWrapper.RegisterGrid(this)
4. OnAfterRenderAsync(firstRender: true)
├── If DataSource parameter was provided: LoadDataSource(dataSourceParam, sync, notify)
└── Else: LoadDataSourceAsync(notify) — fires SignalR GetAll request
CRUD Operations
Adding Items
await grid.AddDataItem(item); // local add, sync later
await grid.AddDataItemAsync(item); // immediate server sync
await grid.InsertDataItem(0, item); // insert at index, sync later
await grid.InsertDataItemAsync(0, item); // insert at index, immediate sync
Other CRUD Methods
| Method | Description |
|---|---|
UpdateDataItem(item) |
Local update, sync later |
UpdateDataItemAsync(item) |
Immediate server sync |
AddOrUpdateDataItem(item) |
Add if new, update if existing |
RemoveDataItem(item) |
Remove by entity reference |
RemoveDataItem(id) |
Remove by ID |
ReloadDataSourceAsync() |
Re-fetch all data from server |
ForceRenderAsync() |
Force grid re-initialization via new render key |
ID Generation for New Items
New items get temporary client-side IDs until the server assigns real ones:
| TId Type | Strategy | Example |
|---|---|---|
Guid |
Guid.NewGuid() |
a1b2c3d4-... |
int |
-1 * AcDomain.NextUniqueInt32 |
-1, -2, -3, ... |
Convention: Negative integer IDs indicate unsaved items. The server replaces them with real auto-increment IDs.
Edit Flow (Inline)
User clicks Edit → OnEditStart → OnCustomizeEditModel
├── For new items: assign temp ID, set parent FK if detail grid
├── Set GridEditState = New/Edit
├── Fire OnGridCustomizeEditModel callback
├── Re-read the edit model after the callback — the consumer may have created/replaced it
│ (official DevExpress pattern for types without a parameterless ctor); any instance the
│ pre-callback block has not seen gets the same temp-ID/parent-FK initialization
└── Notify InfoPanel: SetEditMode() — skipped with a Logger.Warning when no edit model exists
(e.g. stale focused row after a datasource reload; see MGGRID_ISSUES.md#acblazor-grid-i-n7k2)
User clicks Save → OnItemSaving
├── Fire OnGridEditModelSaving callback (can cancel)
├── If new: AddDataItemAsync / InsertDataItemAsync — the local add is immediate; the row appears
│ at the sort position of its temp ID until the server confirms
├── If existing: UpdateDataItemAsync
├── Reset GridEditState = None
└── Clear InfoPanel edit mode
Server confirm (async, per item) → OnDataSourceItemChanged
├── The response is applied to the SAME instance in place (CopyTo — external references stay
│ valid; no collection notification fires)
└── Grid.Reload() re-processes the local view (sort/filter/page) — a new row jumps to its final
sorted position (real ID) without a data re-query
User clicks Cancel → OnEditCanceling
├── Reset GridEditState = None
└── Clear InfoPanel edit mode
Edit Row Highlighting
When GridEditState != None, the focused row and its cells get background-color: #fffbeb (warm yellow) via OnCustomizeElement.
Disposal
DisposeAsync(): sets _isDisposed = true (every async callback checks it and bails), unsubscribes the
three datasource events (OnDataSourceLoaded, OnDataSourceItemChanged, OnSyncingStateChanged) and
OnCustomizeElement, then GC.SuppressFinalize(this).