# 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 ├── Set GridEditState = New/Edit ├── For new items: assign temp ID, set parent FK if detail grid ├── Notify InfoPanel: SetEditMode() └── Fire OnGridCustomizeEditModel callback User clicks Save → OnItemSaving ├── Fire OnGridEditModelSaving callback (can cancel) ├── If new: AddDataItemAsync / InsertDataItemAsync ├── If existing: UpdateDataItemAsync ├── Reset GridEditState = None └── Clear InfoPanel edit mode 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()` handles cleanup: 1. Set `_isDisposed = true` (guards all async callbacks) 2. Unsubscribe from `OnDataSourceLoaded`, `OnDataSourceItemChanged`, `OnSyncingStateChanged` 3. Remove `OnCustomizeElement` handler 4. `GC.SuppressFinalize(this)` All async callbacks check `_isDisposed` before proceeding.