# 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)`.