LgGridView
LgGridView<TItem> is Lagoon's standard data grid. It displays, filters, sorts, groups, pages, selects, edits, and exports local or remote data in a single component.
<LgGridView StateId="orders-grid" Items="_orders">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" />
</Columns>
</LgGridView>
- Namespace :
Lagoon.UI.Components - Inherits from :
LgFrame - NuGet package :
Lagoon.UI.GridView
StateId is required. If this parameter is missing, the grid crashes at runtime during initialization. Give it a unique and stable identifier to remember user state (columns, filters, sort, pagination).
LgGridView inherits from LgFrame and manages its own loading. Do not wrap it in LgLoaderView.
Demonstrations
- Basic
- Headers
- Grouping
- Pagination
- Editing
- Dynamic columns
- Card mode
- Selection
- Filters & sort
- Resizing
- Export
Usage
Simple grid with local Items
Use Items for a collection already present on the client side. The type TItem is inferred from the collection. On the next render of the parent, the grid reloads its data when the list is replaced, when its item count changes (a List.Add on the same instance is enough), or after an event from an ObservableCollection; for any other in-place modification (element value), call RefreshAsync().
@inherits LgPage
<LgGridView StateId="orders-local"
Items="_orders"
Title="#OrdersGridTitle"
Kind="Kind.Primary">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridDateColumn @bind-Value="item.Date" Title="#OrderDate" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" />
<LgGridBooleanColumn @bind-Value="item.IsValidated" Title="#Validated" />
</Columns>
</LgGridView>
public partial class OrdersPage : LgPage
{
// Local dataset: useful for short reference lists or data already loaded on the client.
private List<OrderRow> _orders = new();
// Initializes the list before the first render so the grid builds its columns on a stable model.
protected override void OnInitialized()
{
_orders = new List<OrderRow>
{
new() { Id = 1, Number = "CMD-001", Date = new DateTime(2024, 1, 15), Amount = 120.50m, IsValidated = true },
new() { Id = 2, Number = "CMD-002", Date = new DateTime(2024, 1, 18), Amount = 89.00m, IsValidated = false },
};
}
private sealed class OrderRow
{
public int Id { get; set; }
public string Number { get; set; }
public DateTime Date { get; set; }
public decimal Amount { get; set; }
public bool IsValidated { get; set; }
}
}
Columns and row context
The <Columns> tag receives the row model. Always give the context an explicit name, then bind columns with @bind-Value="item.Property". The same context can drive column parameters like HideContent, CanEdit, or DefaultVisible.
@inherits LgPage
<LgGridView StateId="orders-columns" Items="_orders" Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" DefaultFrozen="true" />
<LgGridTextColumn @bind-Value="item.Comment"
Title="#InternalComment"
HideContent="@(!item.IsValidated)"
CanEdit="@item.IsValidated" />
</Columns>
</LgGridView>
Dynamic columns (generated by a loop)
The content of <Columns> is a Razor fragment: nothing prevents you from placing a @foreach / @for loop to generate a variable number of columns from a source (enum values, collection items, etc.). Two typical cases: one column per key of a Dictionary and one column per item of a List.
Since 4.0, the grid materializes <Columns> only once (before the first render) on a model row, then renders each cell via compiled accessors. The context variable (item) therefore references the model, not the current row. Consequences for a loop:
- always bind the value by indexer on
item(item.Absences[day],item.Skills[index].Level); do not capture the loop item to bind it, as it would point to the model object and all rows would share the same value; - the source of the loop and the number of columns are frozen by the model: all rows must expose the same keys / the same number of items, in the same order.
ItemModel when a binding indexes a reference memberBy default the grid builds its model with RuntimeHelpers.GetUninitializedObject: no constructor or field initializer is executed, so a reference member (Dictionary, List) remains null. A binding that indexes it (item.Absences[day]) would then dereference null at the time column registration happens (NullReferenceException). Pass an already-populated instance via ItemModel: it resolves the bindings and fixes the number of generated columns.
@inherits LgPage
<LgGridView StateId="team-planning"
TItem="TeamMember"
Items="_members"
EditMode="GridEditMode.Row"
ItemModel="_columnModel">
<Columns Context="item">
<LgGridEditColumn />
<LgGridTextColumn @bind-Value="item.Name" Title="#MemberName" CanEdit="true" />
@* One boolean column per day, bound to a Dictionary<DayOfWeek, bool> via its indexer. *@
@foreach (DayOfWeek day in Enum.GetValues<DayOfWeek>())
{
<LgGridBooleanColumn Key="@($"ABS{day}")"
@bind-Value="@item.Absences[day]"
Title="@day.ToString()"
GroupName="#Absences"
CanEdit="true" />
}
@* One numeric column per skill, bound to a List<SkillLevel> by position. *@
@for (int i = 0; i < item.Skills.Count; i++)
{
int index = i;
<LgGridNumericColumn Key="@($"SKILL{index}")"
@bind-Value="@item.Skills[index].Level"
Title="@item.Skills[index].Name"
GroupName="#Skills"
CanEdit="true" />
}
</Columns>
</LgGridView>
public partial class TeamPlanningPage : LgPage
{
// Canonical order of skills: each row exposes the same ones, in the same order,
// so that the generated columns remain stable from row to row.
private static readonly string[] SkillNames = { "C#", "Blazor", "SQL", "CSS" };
// Model used to build the column structure: all dictionary keys and
// all skills are present, otherwise some columns would not be declared.
private readonly TeamMember _columnModel = new()
{
Absences = Enum.GetValues<DayOfWeek>().ToDictionary(day => day, _ => false),
Skills = SkillNames.Select(name => new SkillLevel { Name = name, Level = 0 }).ToList(),
};
private List<TeamMember> _members = new();
private sealed class TeamMember
{
public string Name { get; set; }
public Dictionary<DayOfWeek, bool> Absences { get; set; } = new();
public List<SkillLevel> Skills { get; set; } = new();
}
private sealed class SkillLevel
{
public string Name { get; set; }
public int Level { get; set; }
}
}
A value bound by indexer remains modifiable (CanEdit="true" works) as long as the target is assignable: Dictionary key (access via set_Item), array element, or property with set accessor at the end of the path (item.Skills[index].Level). If the bound expression is not assignable (for example a computed value), the grid automatically switches the column to read-only instead of presenting an editor that could not rewrite the value.
Remote grid with ControllerUri
Use ControllerUri to delegate filtering, sorting, pagination, and export to the server. ControllerQueryArg transmits an additional business argument and AllowCancellation enables cancellation of loading by the grid's integrated loader. A change in ControllerUri or ControllerQueryArg (compared by Equals, on a clone if the argument implements ICloneable) reloads the grid.
@inherits LgPage
<LgGridView TItem="OrderVm"
StateId="orders-remote"
ControllerUri="api/Orders"
ControllerQueryArg="_queryArg"
AllowCancellation="true"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" />
</Columns>
</LgGridView>
public partial class OrdersRemotePage : LgPage
{
// Argument serialized in remote requests to apply a business filter on the server side.
private readonly OrdersQueryArg _queryArg = new()
{
CustomerId = 42,
};
private sealed class OrdersQueryArg
{
public int CustomerId { get; set; }
}
private sealed class OrderVm
{
public int Id { get; set; }
public string Number { get; set; }
public string CustomerName { get; set; }
public decimal Amount { get; set; }
}
}
Read endpoint contract
- Route :
POST api/Orders/$qd - Body :
DataQueryRequest<OrdersQueryArg> - Return :
IQueryable<OrderVm>request decorated with[Queryable]
[Route("api/[controller]")]
public class OrdersController : LgControllerBase
{
private readonly AppDbContext _db;
public OrdersController(AppDbContext db)
{
_db = db;
}
// Provides the remote source: the Queryable attribute applies the filters, sorts and pages sent by the grid.
[HttpPost("$qd")]
[Queryable]
public IActionResult GetOrders([FromBody] DataQueryRequest<OrdersQueryArg> args)
{
try
{
IQueryable<OrderVm> query = _db.Orders.Select(o => new OrderVm
{
Id = o.Id,
Number = o.Number,
CustomerName = o.Customer.Name,
Amount = o.Amount,
CustomerId = o.CustomerId,
});
if (args.Arg?.CustomerId is int customerId)
{
query = query.Where(o => o.CustomerId == customerId);
}
return Ok(query);
}
catch (Exception ex)
{
return Problem(ex);
}
}
public sealed class OrdersQueryArg
{
public int CustomerId { get; set; }
}
public sealed class OrderVm
{
public int Id { get; set; }
public string Number { get; set; }
public string CustomerName { get; set; }
public decimal Amount { get; set; }
public int CustomerId { get; set; }
}
}
Filters, default filters, and summary
Filters depend on the column type: text (TextFilter), boolean (BooleanFilter<TBool>), numeric (NumericFilter<TNumber>), date (DateFilter<TDateTime>), time (TimeFilter<TTime>), or enumeration (EnumFilter<TEnum> / EnumerableFilter<,>). DefaultFilter initializes a filter, DefaultShowFilters displays the filter row on opening, ShowFiltersSummary displays the summary, and OnFilterChanged allows you to react to changes.
The visibility of the filter row is managed by ShowFilters, bindable two-way (@bind-ShowFilters):
- its initial value is preserved, unless
DefaultShowFiltersis set (it then takes precedence on first render); - a profile containing a filter always displays the filter row; the grid then notifies
ShowFiltersChanged; - a profile without a filter does not hide the filter row: it remains in the current state (or that of
DefaultShowFiltersif set), even when switching from a filtered profile to one without; if filters are not reloaded (see Profile content and partial loading), the filter row keeps the state chosen by the user; - hiding filters clears them, whether by the toolbar button or by the parent (
ShowFilterschanging fromtruetofalse).
A profile also records the absence of a filter: a column recorded without a filter remains without a filter on reload, even if it has a DefaultFilter. The DefaultFilter applies only to a column absent from the profile (added after its creation, or default profile never saved). A DefaultFilter added later to an existing column does not apply to users whose profile already records that column. The "Reset" button in the column menu reapplies the DefaultFilter, as on a new grid.
@inherits LgPage
<LgGridView StateId="orders-filter"
Items="_orders"
DefaultShowFilters="true"
ShowFiltersSummary="true"
OnFilterChanged="OnFilterChangedAsync"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridNumericColumn @bind-Value="item.Weight" Title="#Weight" DefaultFilter="_minimumWeightFilter" />
</Columns>
</LgGridView>
public partial class OrdersFilterPage : LgPage
{
// Default filter: limits page opening to rows already relevant to the user.
private readonly NumericFilter<int?> _minimumWeightFilter = new();
// Configures the numeric rule before initial render so the grid profile starts filtered.
protected override void OnInitialized()
{
_minimumWeightFilter.AddGreaterThan(60, true);
}
// Triggered each time a filter is modified: useful for synchronizing an external badge or counter.
private Task OnFilterChangedAsync(GridViewFilterChangedEventArgs args)
{
return Task.CompletedTask;
}
}
Sorting and OnSortChanged event
Clicking on a sortable column header places it in primary sort; columns already sorted are kept as secondary sorts. DefaultSortDirection on a column defines the initial sort. OnSortChanged receives a GridViewSortEventArgs whose Sorts describes the complete sort after the change: the list of sorted columns, in sort order, as pairs (Key, SortDirection) (column identifier and direction). Key and SortDirection directly give the column and direction of the primary sort (null and None for no sort). The event fires after user sorting and when a profile is applied (or reset), but not on initial load, nor when a profile loads without reloading sort (current sorts preserved).
MaxSortedColumns limits the number of columns sorted at the same time (4 by default). If the user sorts one more column, the sort of lowest priority is removed. 1 limits the grid to a single sorted column (each sort replaces the previous one) and 0 removes the limit. If the parameter is not set, the global MaxSortedColumns option of app.GridView(...) applies (see Global options for LgGridView). A negative value raises an exception. Grouping columns do not count against this limit.
@inherits LgPage
<LgGridView StateId="orders-sort"
Items="_orders"
OnSortChanged="OnSortChangedAsync"
MaxSortedColumns="2"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" DefaultSortDirection="DataSortDirection.Asc" />
<LgGridDateColumn @bind-Value="item.Date" Title="#OrderDate" />
</Columns>
</LgGridView>
public partial class OrdersSortPage : LgPage
{
private readonly List<OrderRow> _orders = new();
// Receives the complete sort: args.Sorts[0] is the primary sort (Key = column identifier).
private Task OnSortChangedAsync(GridViewSortEventArgs args)
{
foreach ((string key, DataSortDirection direction) in args.Sorts)
{
// Synchronize external state (URL, preferences, etc.)
}
return Task.CompletedTask;
}
private sealed class OrderRow
{
public string Number { get; set; }
public DateTime Date { get; set; }
}
}
Data grouping
GroupBy groups rows by column key. Separate multiple columns of the same level with a comma and multiple levels with /. GroupHeaderContent customizes the group header while preserving DefaultContent if needed.
@inherits LgPage
<LgGridView StateId="orders-grouping"
Items="_orders"
GroupBy="Year,Month/Day"
DefaultGroupCollapsed="true"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridNumericColumn @bind-Value="item.Year" Title="#Year" />
<LgGridNumericColumn @bind-Value="item.Month" Title="#Month" />
<LgGridNumericColumn @bind-Value="item.Day" Title="#Day" />
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
</Columns>
<GroupHeaderContent Context="group">
@group.DefaultContent
</GroupHeaderContent>
</LgGridView>
Selection, business key, and selection toolbar
For stable selection, populate KeyField with a unique property. If uniqueness depends on multiple properties, implement IEquatable<T> in the model. ToolbarSelection adds actions to the toolbar displayed at the bottom of the grid when at least one row is selected.
@inherits LgPage
<LgGridView StateId="orders-selection"
Items="_orders"
KeyField="Id"
SelectableRows="true"
Selection="_selection"
OnRowSelection="OnRowSelectionAsync"
Features="@(GridFeature.Default | GridFeature.Delete)"
OnDelete="OnDeleteAsync"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridSelectionColumn DisableSelectAll="true" />
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" />
</Columns>
<ToolbarSelection>
<LgToolbarGroup>
<LgToolbarButton Text="#ArchiveSelection"
IconName="@IconNames.All.Archive"
OnClick="OnArchiveSelectionAsync" />
</LgToolbarGroup>
</ToolbarSelection>
</LgGridView>
public partial class OrdersSelectionPage : LgPage
{
// Selection bound to the grid: it remains available for toolbar actions.
private ICollection<OrderRow> _selection = new List<OrderRow>();
// Synchronizes the selected collection and allows knowing the user action (select, deselect, select all).
private Task OnRowSelectionAsync(GridViewSelectionEventArgs<OrderRow> args)
{
_selection = args.Selection;
return Task.CompletedTask;
}
// Deletes the selection when the Delete feature of the grid is used.
private Task OnDeleteAsync(GridViewSelectionActionEventArgs<OrderRow> args)
{
foreach (OrderRow item in args.Selection.ToList())
{
_orders.Remove(item);
}
return Task.CompletedTask;
}
// Executes a business action on the selection without depending on the standard delete button.
private Task OnArchiveSelectionAsync(ActionEventArgs args)
{
return Task.CompletedTask;
}
}
Cell click and row commands
OnCellClick at the grid level receives the row item and column key. LgGridCommandColumn triggers OnCommandClick; its RefreshMode decides whether the row, the grid, or only the rendering should be refreshed.
@inherits LgPage
<LgGridView StateId="orders-actions"
Items="_orders"
OnCellClick="OnCellClickAsync"
OnCommandClick="OnCommandClickAsync"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridCommandColumn Key="order-actions"
CommandName="open"
ButtonText="#Open"
ButtonAriaLabel="#OpenOrder"
IconName="@IconNames.All.Eye">
<LgGridCommand CommandName="duplicate" Text="#Duplicate" IconName="@IconNames.All.Files" />
<LgGridCommand CommandName="delete" Text="#Delete" IconName="@IconNames.Delete" ConfirmationMessage="#ConfirmDelete" />
</LgGridCommandColumn>
</Columns>
</LgGridView>
public partial class OrdersActionsPage : LgPage
{
// Intercepts cell click to open a detail only on certain columns.
private Task OnCellClickAsync(GridViewCellClickEventArgs<OrderRow> args)
{
if (args.ColumnKey == nameof(OrderRow.Number))
{
ShowInformation(args.Item.Number);
}
return Task.CompletedTask;
}
// Centralizes row actions and chooses the appropriate refresh level for each command.
private Task OnCommandClickAsync(GridViewCommandClickEventArgs<OrderRow> args)
{
args.RefreshMode = args.Command == "delete"
? GridEventRefreshMode.ReloadGrid
: GridEventRefreshMode.StateHasChangeRow;
return Task.CompletedTask;
}
}
Grid toolbar
Since LgGridView is an LgFrame, add your buttons in its Toolbar fragment. Buttons not surrounded by LgCollapsableView remain visible regardless of the collapsed state; ViewMode.OnlyExpanded or ViewMode.OnlyCollapsed allows you to adapt the display.
@inherits LgPage
<LgGridView StateId="orders-toolbar" Items="_orders" Collapsable="true" Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
</Columns>
<Toolbar>
<LgToolbarButton Text="#Refresh" IconName="@IconNames.All.ArrowClockwise" OnClick="OnRefreshAsync" />
<LgCollapsableView ViewMode="ViewMode.OnlyExpanded">
<LgToolbarButton Text="#ExportOptions" IconName="@IconNames.All.Download" OnClick="OnShowExportOptionsAsync" />
</LgCollapsableView>
<LgCollapsableView ViewMode="ViewMode.OnlyCollapsed">
<LgToolbarButton Text="#GridCollapsed" IconName="@IconNames.All.ArrowsExpand" />
</LgCollapsableView>
</Toolbar>
</LgGridView>
public partial class OrdersToolbarPage : LgPage
{
// Reference to the grid: exposes public methods for refreshing and exporting.
private LgGridView<OrderRow> _grid;
// Reloads the grid data, especially after a change in external criteria.
private Task OnRefreshAsync(ActionEventArgs args)
{
return _grid.RefreshAsync();
}
// Opens the export options window from a business button in the toolbar.
private Task OnShowExportOptionsAsync(ActionEventArgs args)
{
return _grid.ShowExportOptionsAsync();
}
}
Editing, adding, and server endpoints
EditMode="GridEditMode.Row" edits a complete row, typically with LgGridEditColumn. EditMode="GridEditMode.Cell" edits cell by cell and allows you to validate the new value with OnValueChangingAsync. Enable GridFeature.Add to display adding and GridFeature.Delete to delete the selection.
@inherits LgPage
<LgGridView StateId="orders-edit"
Items="_orders"
EditMode="GridEditMode.Row"
Features="@(GridFeature.Default | GridFeature.Add | GridFeature.Delete)"
NewItem="CreateNewOrder"
OnValueAdd="OnValueAddAsync"
OnRowUpdate="OnRowUpdateAsync"
OnDelete="OnDeleteAsync"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridEditColumn />
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" CanAdd="true" CanEdit="true" />
<LgGridDateColumn @bind-Value="item.Date" Title="#OrderDate" CanAdd="true" CanEdit="true" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" CanAdd="true" CanEdit="true" />
</Columns>
</LgGridView>
public partial class OrdersEditionPage : LgPage
{
// Provides the default values for the added row before editing by the user.
private OrderRow CreateNewOrder()
{
return new OrderRow
{
Id = _orders.Count + 1,
Date = DateTime.Today,
};
}
// Persists the new row after validation of the addition.
private Task OnValueAddAsync(GridViewItemActionEventArgs<OrderRow> args)
{
return Task.CompletedTask;
}
// Persists the changes to an entire row.
private Task OnRowUpdateAsync(GridViewItemActionEventArgs<OrderRow> args)
{
return Task.CompletedTask;
}
// Deletes the selected rows, then let the grid refresh its state.
private Task OnDeleteAsync(GridViewSelectionActionEventArgs<OrderRow> args)
{
foreach (OrderRow item in args.Selection.ToList())
{
_orders.Remove(item);
}
return Task.CompletedTask;
}
}
@inherits LgPage
<LgGridView StateId="orders-cell-edit"
Items="_orders"
EditMode="GridEditMode.Cell"
OnValueChangingAsync="OnValueChangingAsync"
DisplaySuccessSaveMessage="true"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" CanEdit="false" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" CanEdit="true" />
</Columns>
</LgGridView>
public partial class OrdersCellEditionPage : LgPage
{
// Validates a cell before saving: cancel the change by setting args.Cancel.
private Task OnValueChangingAsync(GridViewValueChangingEventArgs<OrderRow> args)
{
if (args.ColumnKey == nameof(OrderRow.Amount) && args.Value is decimal amount && amount < 0m)
{
args.Cancel = true;
}
return Task.CompletedTask;
}
}
Data linked across multiple rows
In Cell mode, each value change validates the entire edited row, just as the server validates the saved item: IValidatableObject and validation attributes on all direct members of the item, including those never edited (a required empty field is reported on first row modification) and those without a column (listed in the error message). Nested objects are not checked. The error indicator displays on each cell in error on that row, including on read-only cells or cells of another field (for example an IValidatableObject rule that depends on the entered value). When multiple rows share the same data, the invalid value is visible on all rows, but without a handler only the edited row shows the indicator. OnCellValueChanged designates linked rows: after each value change, valid or not, the grid revalidates them and reports their error cells. Without a handler, no other row is revalidated.
@inherits LgPage
<LgGridView StateId="linked-rows"
Items="_items"
EditMode="GridEditMode.Cell"
OnCellValueChanged="OnCellValueChanged">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Value" Title="Value" CanEdit="true" />
</Columns>
</LgGridView>
public partial class LinkedRowsPage : LgPage
{
// Declares rows that share their data with the edited row.
private void OnCellValueChanged(GridViewCellValueChangedEventArgs<LinkedItem> args)
{
args.RevalidateItems(i => i.Shared == args.Item.Shared);
}
}
GridViewCellValueChangedEventArgs<TItem> exposes Item, ColumnKey, Value, PreviousValue and IsValid (validation result of the edited row), as well as two overloads of RevalidateItems:
RevalidateItems(Func<TItem, bool> predicate)revalidates items accepted by the predicate; anullpredicate raisesArgumentNullException. Multiple calls accumulate: an item is revalidated as soon as one of the predicates accepts it;RevalidateItems()revalidates all items.
The edited row item is never revalidated by these calls: it has already been validated by the cell. Retained items are searched among data known to the browser: all Items of a local grid (including those hidden by a filter or on another page), or data loaded by a remote grid; an unloaded remote page is not reachable. Displayed rows are revalidated immediately, others on display. A row in error keeps its indicator when it leaves the display then returns (page change, virtualized grid scroll, reload), until validation finds it valid. A read-only row (RowCanEditSelector) has no form: it does not display an error.
On a linked row, validation attributes are only checked again for the modified field and for fields already in error (to erase a now-false message): a required field never entered is not reported. IValidatableObject errors are always recalculated, without toastr message for linked rows.
Only a column bound to a direct member of the item (@bind-Value="item.Code") has a validation field name. A column bound by an indexer (item["Comment"]) or by a nested path (item.Data.Code) has none: its cell does not display an indicator and its value is always saved, but its modification recalculates the row state, updating cells of other fields (for example a rule on Max that depends on Comment).
Saving follows the entire row rule: as long as the edited row has an error, even on another field, the entered value is not saved (IsValid is false, no PATCH, no reload, no OnAfterUpdate); it remains written on the item and displays. The next entry that makes the row valid saves it. The error message then lists the errors of the other fields of the row (validation attributes, errors returned by the server), which explain why the value is not saved; the error of the entered field is not repeated there. Exception: a column without a field name is never blocked. On a remote grid, the PATCH sends the entire item (Data, which also carries the previously refused value) and the edited column (ColumnKey, Value, PreviousValue): the refused value is only saved on the server if the controller saves Data, not if it only applies the edited column.
If the server refuses the PATCH with validation errors (response ValidationProblemDetails or ModelState, whose keys designate fields of Data, for example Data.Weight), the error displays as before and cells of these fields are flagged on the edited row, even after row reload (ReloadRow). As long as these fields are not modified, the row is no longer saved; modifying a field erases its server error. A rule known only to the server is not found if the row leaves the display then returns (only validation attributes are checked again). This is notably the case when the controller validates the entire received item (automatic ASP.NET Core validation on UpdateDataParameters<TItem>) whereas the grid only checks modified fields.
Canceling an edit (Escape key) restores the last validated value and keeps any errors still present on the row (on other fields, or on this value itself); it does not trigger OnCellValueChanged.
OnCellValueChanged is triggered after saving a valid value, therefore after the reload requested by EditRefreshMode: with ReloadGrid on a remote grid, args.Item is the instance before reload, whereas the predicate receives reloaded items. Compare items by key or by data (i => i.Group == args.Item.Group), not by reference.
After editing, EditRefreshMode chooses the refresh (see GridEventRefreshMode). On a remote grid (ControllerUri), ReloadRow reloads the modified row from the server by finding it via the value of KeyField, or the model's Id property without KeyField; if the model has no Id property, the grid raises an error before sending the PATCH or PUT: nothing is sent to the server. ReloadGrid reloads all data; OnAfterUpdate then receives the reloaded item corresponding to the edited row (found by KeyField or Id, else by type equality), or the edited item if it no longer appears in the data. On a local grid (Items), ReloadRow has no effect after editing.
Remote editing endpoints contract
When ControllerUri is provided, the grid calls the same route with different verbs depending on the action:
- POST
api/Orders: adds a row (TItemin body). - PUT
api/Orders: updates a complete row inRowmode (TItemin body). - PATCH
api/Orders: updates a cell inCellmode (UpdateDataParameters<TItem>in body). - DELETE
api/Orders: deletes the selection (ICollection<TItem>in body).
[Route("api/[controller]")]
public class OrdersEditionController : LgControllerBase
{
// Adds the row created by the grid when GridFeature.Add is active.
[HttpPost]
public IActionResult Add([FromBody] OrderVm item)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Updates an entire row when EditMode is GridEditMode.Row.
[HttpPut]
public IActionResult UpdateRow([FromBody] OrderVm item)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Updates a single cell when EditMode is GridEditMode.Cell.
[HttpPatch]
public IActionResult UpdateCell([FromBody] UpdateDataParameters<OrderVm> args)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Deletes the selected rows when GridFeature.Delete is active.
[HttpDelete]
public IActionResult Delete([FromBody] ICollection<OrderVm> selection)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
}
Pagination, layout, and column options
PaginationSizeSelector defines the proposed sizes (0 means "show all"), DefaultPageSize sets the initial size, PagerOnTop places the pager above. The Move, Freeze, Visibility, Resize, and Group features control the actions of the integrated column menu.
@inherits LgPage
<LgGridView @ref="_grid"
StateId="orders-layout"
Items="_orders"
Features="@(GridFeature.Filter | GridFeature.Sort | GridFeature.Paging | GridFeature.Resize | GridFeature.Visibility | GridFeature.Freeze)"
LayoutMode="GridLayoutMode.FitColumns"
DefaultPageSize="25"
PaginationSizeSelector="_pageSizes"
PaginationButtonCount="7"
DisplayInputPageSelector="true"
PagerOnTop="true"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" DefaultWidth="160px" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" DefaultWidth="2fr" />
</Columns>
</LgGridView>
public partial class OrdersLayoutPage : LgPage
{
// List of page sizes proposed; 0 displays all rows on a single page.
private readonly int[] _pageSizes = new[] { 10, 25, 50, 0 };
// Reference used to restore calculated widths after an external layout change.
private LgGridView<OrderRow> _grid;
// Resets columns to their default width and updates the current profile.
private Task OnRestoreColumnWidthsAsync(ActionEventArgs args)
{
return _grid.RestoreDefaultColumnWidthsAsync();
}
}
Row virtualization (since 4.0)
With Virtualize="true", only rows visible in the scroll area are rendered (Blazor <Virtualize> component): display cost no longer depends on the number of rows per page. This is useful with large pages, especially PageSize = 0 ("show all"). VirtualizeItemSize gives the estimated height of a row in pixels (32 by default). The component then adjusts it to the actual height.
<LgGridView StateId="orders-virtual"
Items="_orders"
DefaultPageSize="0"
Virtualize="true"
VirtualizeItemSize="36">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
</Columns>
</LgGridView>
Virtualization is disabled by default. To enable it on all grids in the application, use OnConfigureBehavior; the grid parameter takes precedence:
protected override void OnConfigureBehavior(ApplicationBehavior app)
{
app.GridView(options =>
{
options.Virtualize = true;
options.VirtualizeItemSize = 32f;
});
}
- A grouped grid keeps the classic rendering: virtualization only applies to the non-grouped body. The add row and calculation row are never virtualized.
- A row being edited that leaves the visible area is unmounted. The grid then exits edit mode. Already-entered values remain on the item, but they are not saved.
Style, text copy, and accessibility
RowCssClassSelector adds a class per row. To allow text selection/copy-paste in cells, add user-select: text to the gridview-cell class. On the RGAA side, prefer AriaLabel or AriaLabelledBy, and avoid grouping (GroupBy, GroupName) or moving columns when screen reader reading order is a priority.
@inherits LgPage
<LgGridView StateId="orders-style"
Items="_orders"
AriaLabel="#OrdersGridAria"
RowCssClassSelector="GetRowCssClass"
CssClass="orders-copy-enabled"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" />
</Columns>
</LgGridView>
public partial class OrdersStylePage : LgPage
{
// Returns a class per row to visually signal high-amount orders.
private string GetRowCssClass(int index, OrderRow item)
{
return item.Amount > 1000m ? "orders-row-warning" : string.Empty;
}
}
.orders-copy-enabled .gridview-cell {
user-select: text;
}
Data export
Exportable enables the export window. VisibleExportList and HiddenExportList filter providers, OnLoadExportProviders adds providers for a given grid, OnExport adjusts the request options, and ConfigureExportColumn modifies exported column metadata.
@inherits LgPage
<LgGridView StateId="orders-export"
Items="_orders"
Exportable="true"
VisibleExportList="xlsx,csv"
ExportCulture="fr-FR"
OnLoadExportProviders="LoadExportProviders"
OnExport="OnExportAsync"
ConfigureExportColumn="ConfigureExportColumn"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" ExportTitle="#CustomerExport" />
<LgGridNumericColumn @bind-Value="item.Amount" Title="#Amount" DisplayFormat="N2" />
</Columns>
</LgGridView>
public partial class OrdersExportPage : LgPage
{
// Adds local providers to this grid without modifying the application's global configuration.
private void LoadExportProviders(ExportProviderManager providers)
{
providers.Register<XlsxExportProvider>();
providers.Register<HtmlExportProvider>();
}
// Adjusts the export request just before file generation.
private Task OnExportAsync(GridViewExportEventArgs args)
{
args.FileName = "orders";
args.GroupNameWithTitle = true;
args.IgnoreSort = false;
return Task.CompletedTask;
}
// Renames or reformats a column depending on the selected export provider.
private void ConfigureExportColumn(GridViewConfigureExportColumnEventArgs args)
{
if (args.ColumnKey == nameof(OrderRow.Amount))
{
args.ColumnTitle = "#AmountWithTax";
args.ColumnDisplayFormat = "N2";
}
}
}
Global providers and server export
Configure client providers in OnConfigureBehavior and server providers in OnConfigureServices. Server export is used when the grid is remote (ControllerUri) and the sources of selection columns are also remote.
public partial class Main : LgCustomApplication
{
// Configures GridView options common to the entire client application.
protected override void OnConfigureBehavior(ApplicationBehavior app)
{
base.OnConfigureBehavior(app);
app.GridView(options =>
{
options.ExportWithFilters = true;
options.Exportable = true;
});
app.ExportProviderManager.Register<XlsxExportProvider>();
app.ExportProviderManager.Register<HtmlExportProvider>();
}
}
Advanced export (since 3.33)
- Declarative server providers : a controller can publish its own export providers via the
[ExportProvider<T>]attribute; they appear automatically in the export window, alongside providers declared at the application level. - Server-side export parameters : the
[Queryable]method called during an export accesses the request viaqueryArg.Export(culture, timezone, columns, selected provider) whenqueryArg.IsExportRequestis true. On the grid side,OnExportcan transmit a business value withargs.SetExportArg<T>(…), read on the server side viaqueryArg.Export.GetExportArg<T>(). - Export window customization : the
ExportOptionsContentparameter (RenderFragment<ExportOptionsContext>) injects custom content into the modal (additional fields, business options). - Capabilities declared by provider :
IExportProviderDescriptionexposesSupportFilteredRowsandSupportDisplayedColumns(trueby default); the modal hides the "filtered rows" / "displayed columns" checkboxes when the capability is absent. These choices are only proposed to the user if there is an active filter or hidden columns. - Import pipeline symmetric to export:
IImportColumn,ImportColumn,[ImportIgnore], on the common abstractionITableColumn.
Profile content and partial loading
A profile records, for each column, the filter, sort, position, visibility, freeze, and width, as well as the grid's groupings and page size. Each item corresponds to a flag in GridFeature: Filter, Sort, Move (position), Visibility, Freeze, Resize (width), Group and Paging (page size).
ProfileFeatures limits the items recorded in profiles and reloaded from them. Move and Freeze go together, as frozen columns are the first in column order: excluding one excludes the other. Unlike Features, an excluded item remains usable: it is not written to profiles and, when loading a profile, it keeps its current state (unless OnProfileLoadingAsync requests default values). If the parameter is not set, the global ProfileFeatures option of app.GridView(...) applies (all items by default, see Global options for LgGridView).
OnProfileLoadingAsync (Func<GridViewProfileLoadingEventArgs, Task>) is called and awaited just before a profile is applied: the decision can therefore be asynchronous (a confirmation, for example). The argument indicates the loaded profile (Profile) and the reason for loading (Reason, see GridViewProfileLoadReason):
LoadedFeaturescontains the items to load, initialized with those managed by profiles (ProfileFeatures). Removing a flag excludes the item from loading; removingMoveorFreezeremoves both; an item not managed by profiles cannot be added.ExclusionMode(seeGridViewProfileExclusionMode) sets the state of items not loaded, including those excluded byProfileFeatures:KeepCurrent(default) keeps the current state,Defaultresets default values (columnDefault*parameters, gridGroupByandDefaultPageSize). At initialization, current state is default state: the two modes are equivalent.
If the callback raises an exception, it is displayed and the profile is loaded in full.
On automatic save, the current state of items managed by profiles is saved in the current profile on the next modification, including an item kept when switching profiles. The "Reset" button resets all items to their default values, whether managed by profiles or not.
@inherits LgPage
<LgGridView StateId="orders-partial-profiles"
Items="_orders"
ProfileFeatures="@(GridFeature.Filter | GridFeature.Sort | GridFeature.Move | GridFeature.Freeze | GridFeature.Visibility | GridFeature.Resize)"
OnProfileLoadingAsync="OnProfileLoadingAsync"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" DefaultFilter="_customerFilter" />
</Columns>
</LgGridView>
public partial class OrdersPartialProfilesPage : LgPage
{
// Client filter provided by the page (URL parameter for example), applied as default filter.
private Filter _customerFilter;
// Chooses which profile items are applied based on the load reason.
private Task OnProfileLoadingAsync(GridViewProfileLoadingEventArgs args)
{
if (args.Reason == GridViewProfileLoadReason.Initialization)
{
// On opening, the client filter comes from the page (DefaultFilter), not the last used profile.
args.LoadedFeatures &= ~GridFeature.Filter;
}
else if (args.Reason == GridViewProfileLoadReason.Selection)
{
// Changing profile changes the layout, but keeps filters entered by the user.
args.LoadedFeatures &= ~GridFeature.Filter;
args.ExclusionMode = GridViewProfileExclusionMode.KeepCurrent;
}
return Task.CompletedTask;
}
}
Shared profiles
ProfileId identifies the persistence space, StorageMode chooses the storage, SharedProfileAdministratorPolicy authorizes the management of shared profiles, and SharedProfileFilter filters the proposed profiles according to permissions or targets.
@inherits LgPage
<LgGridView StateId="orders-profiles"
ProfileId="orders-admin"
Items="_orders"
Features="GridFeature.Default"
StorageMode="GridViewProfileStorage.Local"
SharedProfileAdministratorPolicy="Policies.GridProfileAdmin"
SharedProfileFilter="_profileFilter"
Title="#OrdersGridTitle">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
<LgGridTextColumn @bind-Value="item.CustomerName" Title="#Customer" />
</Columns>
</LgGridView>
public partial class OrdersProfilesPage : LgPage
{
// Filter reused by a single grid: it limits the visibility of shared profiles to expected policies.
private readonly OrdersSharedProfileFilter _profileFilter = new();
}
public sealed class OrdersSharedProfileFilter : GridViewSharedProfileFilter
{
// Declares the targets proposed in the shared profile creation window.
protected override void OnInitialized()
{
AddTarget("#Administrators", Policies.GridProfileAdmin);
AddTarget("#OrderManagers", Policies.OrderManager);
}
// Checks each tag associated with the shared profile before displaying it to the current user.
public override async Task<bool> IsProfileVisibleAsync(string label, IReadOnlyList<string> tags)
{
foreach (string policy in tags)
{
if (!await IsInPolicyAsync(policy))
{
return false;
}
}
return true;
}
}
Properties
Parameters of LgGridView
| Name | Type | Default | Description |
|---|---|---|---|
StateId | string | — | Required. Unique identifier to remember state (columns, filters, sort, pagination). Crashes at runtime if missing. |
KeyField | string | null | Name of the property identifying a row: selection key (which survives reloads) and row reload (ReloadRow). Empty: a remote grid uses the model's Id property if it has one; otherwise, items are compared with type equality (Equals / IEquatable<T>), and a remote grid cannot reload a row (error). The key follows a change of the data source (local or remote). |
ProfileId | string | null | Identifier of a shared profile (columns, filters saved on the server side). |
LayoutMode | GridLayoutMode | FitHeader | Mode of column resizing at startup. |
GroupBy | string | null | Names of grouping fields separated by commas. |
DefaultGroupCollapsed | bool | false | Groups collapsed by default. |
EditMode | GridEditMode | None | Data editing mode. |
DefaultShowFilters | bool? | null | Initial filter visibility; when set, it overrides the initial value of ShowFilters. |
ShowFilters | bool | false | Two-way binding of filter visibility; hiding filters (including by the parent) clears them. |
ShowFiltersChanged | EventCallback<bool> | — | Callback of the two-way binding of ShowFilters. |
OnFilterChanged | EventCallback<GridViewFilterChangedEventArgs> | — | Triggered when the set of active filters changes, including when a filtered profile is applied (Filters indexed by column identifier, HasFilters()). |
CurrentPage | int | 0 | Current page (two-way with CurrentPageChanged). |
DefaultPageSize | int? | null | Default number of rows per page. |
PaginationSizeSelector | int[] | null | Available options for the number of rows per page, for example [10, 25, 50, 0] where 0 means "show all". |
PaginationButtonCount | int | 5 | Number of page buttons displayed. |
GridViewDataCounter | GridViewDataCounter | null | Two-way binding of the data counter. |
Exportable | bool? | null | Enables or disables export. |
ShowFiltersSummary | bool? | null | Displays a summary of active filters in the header. |
Features | GridFeature | Default | Allowed grid features. |
MaxSortedColumns | int? | null | Maximum number of columns sorted at the same time (see Sorting and OnSortChanged event). If the user sorts one more column, the lowest priority sort is removed. 1 limits the grid to a single sorted column (each sort replaces the previous one) and 0 removes the limit. If not set, the global MaxSortedColumns option of app.GridView(...) applies (4 by default). A negative value raises an exception. Grouping columns do not count against this limit. |
ProfileFeatures | GridFeature? | null | Items recorded in profiles and reloaded from them: Filter, Sort, Move, Visibility, Freeze, Resize, Group, Paging; other flags are ignored; Move and Freeze go together (excluding one excludes the other). An excluded item remains usable, is not written to profiles, and keeps its current state on profile load, unless OnProfileLoadingAsync requests default values (see Profile content and partial loading). If null, the global ProfileFeatures option of app.GridView(...) applies (all items by default). |
GridStyleType | GridStyleType | Grid | Visual style of the grid. |
WrapContent | bool | false | Allows wrapping in cells. |
Virtualize | bool? | null | Renders only visible rows (see Row virtualization). If null, uses the global Virtualize option of app.GridView(...) (false by default). Ignored on a grouped grid. |
VirtualizeItemSize | float? | null | Estimated height of a row in pixels for virtualization. If null, uses the global VirtualizeItemSize option (32). |
DisplayDefaultTooltipHeader | bool? | null | Forces tooltip display in headers. |
Parameters specific to LgGridView<TItem>
| Name | Type | Default | Description |
|---|---|---|---|
Columns | RenderFragment<TItem> | — | Column definition. The context parameter is Context. |
Items | ICollection<TItem> | null | Local data source. |
ControllerUri | string | null | Controller URL for remote data via OData / Queryable. |
ControllerQueryArg | object | null | Additional argument sent with remote requests. |
AllowCancellation | bool | false | Allows loading cancellation in ControllerUri mode. |
SelectableRows | bool | false | Makes rows selectable on click. |
Selection | ICollection<TItem> | null | Collection of selected items (two-way). |
EditRefreshMode | GridEventRefreshMode | None | Refresh mode after editing. ReloadRow applies only to a remote grid and requires KeyField or an Id property in the model (error before sending the modification otherwise). |
NewItem | Func<TItem> | null | Function to create a new item in row add mode. |
NewItemAsync | Func<Task<TItem>> | null | Asynchronous version of NewItem. |
ItemModel | TItem | null | Empty instance used to build columns. |
RowCssClassSelector | Func<int, TItem, string> | null | CSS class selector per row: (index, item) => cssClass. |
GroupHeaderContent | RenderFragment<GridGroupData<TItem>> | null | Custom group header content. |
ToolbarSelection | RenderFragment | null | Additional selection toolbar content. |
ExportOptionsContent | RenderFragment<ExportOptionsContext> | null | Additional content in the export modal. |
NoDataTitle | string | "#GridViewNoDataTitle" | Title displayed when no data is available. |
NoDataDescription | string | "#GridViewNoDataDesc" | Description displayed when no data is available. |
DataErrorTitle | string | "#GridViewErrorTitle" | Title of the load error message. |
DisplayInputPageSelector | bool? | null | Displays a numeric page selector. |
DisplaySuccessSaveMessage | bool? | null | Displays a success message after saving. |
PagerOnTop | bool? | null | Displays the pager above the grid. |
AddItemOnTop | bool? | null | Adds new rows at the top. |
HiddenExportList | string | null | IDs of providers to hide, for example "xlsx,csv". |
VisibleExportList | string | null | IDs of providers to force to display. |
ExportCulture | string | null | Culture used for export, for example "fr-FR". |
ConfigureExportColumn | Action<GridViewConfigureExportColumnEventArgs> | null | Configures each column during export. |
OnLoadExportProviders | Action<ExportProviderManager> | null | Initializes export providers. |
Key parameters inherited from LgFrame
| Name | Type | Default | Description |
|---|---|---|---|
Title | string | null | Title displayed in the frame header. |
IconName | string | null | Icon displayed before the title. |
Kind | Kind | Kind.Primary | Visual variant of the frame. |
Collapsable | bool | false | Allows the grid to be collapsed. |
Collapsed | bool | false | Current collapsed state. |
Toolbar | RenderFragment | null | Toolbar rendered in the header. |
CssClass | string | null | Additional CSS classes. |
ShowHeader | bool | true | Hides the header if false. |
Frame, export, and miscellaneous
| Parameter | Type | Description |
|---|---|---|
ChildContent | RenderFragment | Frame content (rendered). |
TitleContent | RenderFragment | Custom title content. |
HeaderContent | RenderFragment | Custom header content. |
FooterContent | RenderFragment | Custom footer content. |
SummaryContent | RenderFragment | Summary content. |
HeaderCssClass | string | Header CSS classes. |
ChildCssClass | string | Content CSS classes. |
ButtonSize | ButtonSize? | Size of frame buttons. |
DefaultCollapsed | bool? | Default collapsed state of the frame. |
CollapsedChanged | EventCallback<bool> | Binding of the collapsed state (@bind-Collapsed). |
OnToggle | EventCallback<ToggleFrameEventArgs> | Triggered on frame collapse/expand. |
ExportFileName | string | Name of the exported file. |
EditingState | GridViewEditingState | Current add/edit state. |
EditingStateChanged | EventCallback<GridViewEditingState> | Binding of the add/edit state. |
OnCommand | EventCallback<CommandEventArgs> | Triggered on receipt of a command (CommandName). |
GridViewDataCounterChanged | EventCallback<GridViewDataCounter> | Binding of grid data counters. |
ProfileSaveMode | GridViewProfileSave? | Grid profile save mode. |
AdditionalAttributes | IReadOnlyDictionary<string, object> | Additional HTML attributes. |
ParentPolicy | LgAuthorizeView | (cascading) Policies defined by an ancestor. |
Events
| Name | Type | Description |
|---|---|---|
OnRowSelection | EventCallback<GridViewSelectionEventArgs<TItem>> | Triggered when row selection changes. |
OnSortChanged | EventCallback<GridViewSortEventArgs> | Triggered after user sorting or profile application (not on initial load, nor when the profile does not reload sort); Sorts lists sorted columns in sort order, Key / SortDirection are the column and direction of the primary sort. |
OnProfileLoadingAsync | Func<GridViewProfileLoadingEventArgs, Task> | Called and awaited just before a profile is applied (initialization, selection, default profile after current profile deletion); Profile and Reason describe the load, LoadedFeatures (modifiable) the items loaded, and ExclusionMode the state of others. An exception is displayed and the profile is then loaded in full (see Profile content and partial loading). |
OnCellClick | EventCallback<GridViewCellClickEventArgs<TItem>> | Triggered on cell click. |
OnCommandClick | EventCallback<GridViewCommandClickEventArgs<TItem>> | Triggered on command button click. |
OnValueChangingAsync | Func<GridViewValueChangingEventArgs<TItem>, Task> | Validation before value change in Cell mode. |
OnCellValueChanged | EventCallback<GridViewCellValueChangedEventArgs<TItem>> | Triggered after a value change in Cell mode, valid or not, after a valid value is saved; RevalidateItems() or RevalidateItems(predicate) designates linked rows to validate again, displayed or not (see Data linked across multiple rows). |
OnValueAdd | EventCallback<GridViewItemActionEventArgs<TItem>> | Row addition in Row mode. |
OnRowUpdate | EventCallback<GridViewItemActionEventArgs<TItem>> | Row update in Row mode. |
OnDelete | EventCallback<GridViewSelectionActionEventArgs<TItem>> | Deletion of the selection. |
OnAfterAdd | EventCallback<GridViewAfterActionEventArgs<TItem>> | Triggered after add in Cell mode. |
OnAfterUpdate | EventCallback<GridViewAfterActionEventArgs<TItem>> | Triggered after update in Cell mode. |
OnAfterDelete | EventCallback<GridViewAfterActionEventArgs<TItem>> | Triggered after deletion in Cell mode. |
OnRowStateChanged | EventCallback<GridViewRowStateChangedEventArgs<TItem>> | Triggered when a row state changes. |
OnExport | EventCallback<GridViewExportEventArgs> | Triggered before export to configure it. |
Related enumerations
GridLayoutMode
Column resizing mode (property LayoutMode).
| Value | Description |
|---|---|
None | No column width adjustment. |
FitHeader | Adjusts columns to fit the header (default value). |
FitData | Adjusts columns to fit the data. |
FitColumns | Adjusts columns to fill the available width. |
GridEditMode
Grid editing mode (property EditMode).
| Value | Description |
|---|---|
None | Editing disabled (default value). |
Cell | Editing handled at the cell level. |
Row | Editing handled at the row level. |
GridStyleType
Visual style of the grid (property GridStyleType).
| Value | Description |
|---|---|
Grid | Rendered as a table (default value). |
Card | Rendered as cards. |
GridEventRefreshMode
Refresh mode after editing (property EditRefreshMode).
| Value | Description |
|---|---|
None | No rendering refresh of the row (applied only to OnCommandClick). |
StateHasChangeRow | Refreshes the row rendering. |
ReloadRow | Reloads the row data, found by the value of KeyField. Without KeyField: the item is searched in Items with type equality (Equals / IEquatable<T>; without equality redefinition, only the same instance is found) on a local grid; on a remote grid, the item is found by its Id property, and the grid raises an error if the model has none. A row that is no longer found keeps its item. After editing, applies only to a remote grid. |
ReloadGrid | Reloads the entire grid data. |
GridFeature (flags)
Allowed grid features (property Features). [Flags] enumeration:
values combine (GridFeature.Filter | GridFeature.Sort).
| Value | Description |
|---|---|
None | No features. |
Filter | Column filtering. |
Sort | Column sorting. |
Paging | Pagination. |
Count | Counting of elements matching the filter. |
Profile | Profile management. |
Resize | Column resizing. |
Move | Column moving. |
Freeze | Column freezing by the user. |
Group | Row grouping by the user. |
Visibility | Column visibility modification. |
Edit | Modification of existing rows (if EditMode ≠ None). |
Add | Adding new rows. |
Delete | Delete option in selection. |
Default | Default combination: `Filter |
All | All is allowed (`Default |
GridViewProfileLoadReason
Reason for loading a profile (property Reason of GridViewProfileLoadingEventArgs, argument of OnProfileLoadingAsync).
| Value | Description |
|---|---|
Initialization | Grid initialization: last used profile, otherwise default profile. |
Selection | User selection of the profile. |
ProfileRemoved | Deletion of the current profile: the default profile is loaded. |
GridViewProfileExclusionMode
State of items excluded from profile loading (property ExclusionMode of GridViewProfileLoadingEventArgs).
| Value | Description |
|---|---|
KeepCurrent | Excluded items keep their current state (default value). |
Default | Excluded items resume their default value (column Default* parameters, grid GroupBy and DefaultPageSize). |
Kind
Visual variant of the frame (property Kind, inherited from LgFrame).
| Value | Description |
|---|---|
Primary | Primary style (default value). |
Default | Neutral default style. |
Secondary | Secondary style. |
Success | "Success" style. |
Error | "Error" style. |
Warning | "Warning" style. |
Info | "Information" style. |
Related components
LgGridTextColumn— text column and reference of common parametersLgGridBaseColumn.LgGridCustomColumn<TColumnValue>— column bound to a value of any type.LgGridNumericColumn<TColumnValue>,LgGridDateColumn<TColumnValue>,LgGridTimeColumn<TColumnValue>,LgGridBooleanColumn<TColumnValue>.LgGridEnumColumn<TColumnValue>,LgGridEnumListColumn<TColumnValue>,LgGridSelectColumn<TColumnValue, TDataSourceItem>,LgGridSelectMultipleColumn<TColumnValue, TDataSourceItem>,LgGridTagBoxColumn.LgGridColorColumn<TColumnValue>,LgGridImageColumn<TItem>,LgGridSummaryColumn<TColumnValue>.LgGridCommandColumn,LgGridEditColumn,LgGridSelectionColumn,LgGridSeparatorColumn.