109 lines
4.6 KiB
Markdown
109 lines
4.6 KiB
Markdown
# MgGrid — Lifecycle & CRUD
|
|
|
|
> Part of the MgGrid system. See `README.md` for 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
|
|
|
|
```csharp
|
|
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)`.
|