LgGridView
LgGridView<TItem> est la grille de données standard de Lagoon. Elle permet d'afficher, filtrer, trier, grouper, paginer, sélectionner, éditer et exporter des données locales ou distantes dans un composant unique.
<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>
- Espace de noms :
Lagoon.UI.Components - Hérite de :
LgFrame - Package NuGet :
Lagoon.UI.GridView
StateId est obligatoire. Si ce paramètre est absent, la grille plante à l'exécution lors de son initialisation. Donnez-lui un identifiant unique et stable pour mémoriser l'état utilisateur (colonnes, filtres, tri, pagination).
LgGridView hérite de LgFrame et gère déjà son chargement. Ne l'enveloppez pas dans un LgLoaderView.
Démonstrations
- Basique
- En-têtes
- Regroupement
- Pagination
- Édition
- Colonnes dynamiques
- Mode carte
- Sélection
- Filtres & tri
- Redimensionnement
- Export
Utilisation
Grille simple avec des Items locaux
Utilisez Items pour une collection déjà présente côté client. Le type TItem est déduit de la collection. Au rendu suivant du parent, la grille recharge ses données quand la liste est remplacée, quand son nombre d'éléments change (un List.Add sur la même instance suffit) ou après un événement d'une ObservableCollection ; pour une autre modification en place (valeur d'un élément), appelez 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
{
// Jeu de données local : utile pour les référentiels courts ou les données déjà chargées côté client.
private List<OrderRow> _orders = new();
// Initialise la liste avant le premier rendu pour que la grille construise ses colonnes sur un modèle stable.
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; }
}
}
Colonnes et contexte de ligne
La balise <Columns> reçoit le modèle de ligne. Donnez toujours un nom explicite au contexte, puis liez les colonnes avec @bind-Value="item.Property". Le même contexte peut piloter des paramètres de colonne comme HideContent, CanEdit ou 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>
Colonnes dynamiques (générées par une boucle)
Le contenu de <Columns> est un fragment Razor : rien n'interdit d'y placer une boucle @foreach / @for pour générer un nombre variable de colonnes à partir d'une source (valeurs d'un enum, éléments d'une collection…). Deux cas typiques : une colonne par clé d'un Dictionary et une colonne par élément d'une List.
Depuis la 4.0, la grille matérialise <Columns> une seule fois (avant le premier rendu) sur un modèle de ligne, puis rend chaque cellule via des accesseurs compilés. La variable de contexte (item) référence donc le modèle, pas la ligne courante. Conséquences pour une boucle :
- liez toujours la valeur par indexeur sur
item(item.Absences[day],item.Skills[index].Level) ; ne capturez pas l'élément de boucle pour le lier, car il pointerait sur l'objet du modèle et toutes les lignes partageraient la même valeur ; - la source de la boucle et le nombre de colonnes sont figés par le modèle : toutes les lignes doivent exposer les mêmes clés / le même nombre d'éléments, dans le même ordre.
ItemModel quand une liaison indexe un membre référencePar défaut la grille construit son modèle avec RuntimeHelpers.GetUninitializedObject : aucun constructeur ni initialiseur de champ n'est exécuté, donc un membre référence (Dictionary, List) reste null. Une liaison qui l'indexe (item.Absences[day]) déréférencerait alors null au moment de l'enregistrement des colonnes (NullReferenceException). Passez une instance déjà peuplée via ItemModel : elle résout les liaisons et fixe le nombre de colonnes générées.
@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" />
@* Une colonne booléenne par jour, liée à un Dictionary<DayOfWeek, bool> via son indexeur. *@
@foreach (DayOfWeek day in Enum.GetValues<DayOfWeek>())
{
<LgGridBooleanColumn Key="@($"ABS{day}")"
@bind-Value="@item.Absences[day]"
Title="@day.ToString()"
GroupName="#Absences"
CanEdit="true" />
}
@* Une colonne numérique par compétence, liée à une List<SkillLevel> par 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
{
// Ordre canonique des compétences : chaque ligne expose les mêmes, dans le même ordre,
// pour que les colonnes générées restent stables d'une ligne à l'autre.
private static readonly string[] SkillNames = { "C#", "Blazor", "SQL", "CSS" };
// Modèle servant à construire la structure des colonnes : toutes les clés du dictionnaire et
// toutes les compétences sont présentes, sinon certaines colonnes ne seraient pas déclarées.
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; }
}
}
Une valeur liée par indexeur reste modifiable (CanEdit="true" fonctionne) tant que la cible est assignable : clé de Dictionary (accès set_Item), élément de tableau, ou propriété avec accesseur set en bout de chemin (item.Skills[index].Level). Si l'expression liée n'est pas assignable (par exemple une valeur calculée), la grille bascule automatiquement la colonne en lecture seule au lieu de présenter un éditeur qui ne pourrait pas réécrire la valeur.
Grille distante avec ControllerUri
Utilisez ControllerUri pour déléguer filtrage, tri, pagination et export au serveur. ControllerQueryArg transmet un argument métier additionnel et AllowCancellation active l'annulation du chargement par le loader intégré de la grille. Un changement de ControllerUri, ou de ControllerQueryArg (comparé par Equals, sur un clone si l'argument implémente ICloneable), recharge la grille.
@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 sérialisé dans les requêtes distantes pour appliquer un filtre métier côté serveur.
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; }
}
}
Contrat endpoint de lecture
- Route :
POST api/Orders/$qd - Body :
DataQueryRequest<OrdersQueryArg> - Retour : requête
IQueryable<OrderVm>décorée avec[Queryable]
[Route("api/[controller]")]
public class OrdersController : LgControllerBase
{
private readonly AppDbContext _db;
public OrdersController(AppDbContext db)
{
_db = db;
}
// Fournit la source distante : l'attribut Queryable applique les filtres, tris et pages envoyés par la grille.
[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; }
}
}
Filtres, filtres par défaut et résumé
Les filtres dépendent du type de colonne : texte (TextFilter), booléen (BooleanFilter<TBool>), numérique (NumericFilter<TNumber>), date (DateFilter<TDateTime>), heure (TimeFilter<TTime>) ou énumération (EnumFilter<TEnum> / EnumerableFilter<,>). DefaultFilter initialise un filtre, DefaultShowFilters affiche la ligne de filtres dès l'ouverture, ShowFiltersSummary affiche le résumé, et OnFilterChanged permet de réagir aux changements.
La visibilité de la ligne de filtres est portée par ShowFilters, liable en two-way (@bind-ShowFilters) :
- sa valeur initiale est conservée, sauf si
DefaultShowFiltersest renseigné (il l'emporte alors au premier rendu) ; - un profil qui contient un filtre affiche toujours la ligne de filtres ; la grille notifie alors
ShowFiltersChanged; - un profil sans filtre ne masque pas la ligne de filtres : elle reste dans l'état courant (ou celui de
DefaultShowFilterss'il est renseigné), y compris en passant d'un profil filtré à un profil sans filtre ; si les filtres ne sont pas rechargés (voir Contenu des profils et chargement partiel), la ligne de filtres garde l'état choisi par l'utilisateur ; - masquer les filtres les vide, que ce soit par le bouton de la barre d'outils ou par le parent (
ShowFiltersqui passe detrueàfalse).
Un profil enregistre aussi l'absence de filtre : une colonne enregistrée sans filtre reste sans filtre au rechargement, même si elle a un DefaultFilter. Le DefaultFilter ne s'applique qu'à une colonne absente du profil (ajoutée après son enregistrement, ou profil par défaut jamais enregistré). Un DefaultFilter ajouté plus tard à une colonne existante ne s'applique donc pas aux utilisateurs dont le profil enregistre déjà cette colonne. Le bouton « Réinitialiser » du menu des colonnes remet les DefaultFilter, comme sur une grille neuve.
@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
{
// Filtre par défaut : limite l'ouverture de page aux lignes déjà pertinentes pour l'utilisateur.
private readonly NumericFilter<int?> _minimumWeightFilter = new();
// Configure la règle numérique avant le rendu initial pour que le profil de grille démarre filtré.
protected override void OnInitialized()
{
_minimumWeightFilter.AddGreaterThan(60, true);
}
// Déclenché à chaque modification de filtre : utile pour synchroniser un badge ou un compteur externe.
private Task OnFilterChangedAsync(GridViewFilterChangedEventArgs args)
{
return Task.CompletedTask;
}
}
Tri et événement OnSortChanged
Un clic sur l'en-tête d'une colonne triable la place en tri principal ; les colonnes déjà triées sont conservées en tris secondaires. DefaultSortDirection sur une colonne définit le tri initial. OnSortChanged reçoit un GridViewSortEventArgs dont Sorts décrit le tri complet après le changement : la liste des colonnes triées, par ordre de tri, sous forme de couples (Key, SortDirection) (identifiant de la colonne et sens). Key et SortDirection donnent directement la colonne et le sens du tri principal (null et None sans tri). L'événement est déclenché après un tri par l'utilisateur et à l'application d'un profil (ou à sa réinitialisation), mais pas au chargement initial, ni à l'application d'un profil qui ne recharge pas le tri (tris courants conservés).
MaxSortedColumns limite le nombre de colonnes triées en même temps (4 par défaut). Si l'utilisateur trie une colonne de plus, le tri de plus faible priorité est retiré. 1 limite la grille à une seule colonne triée (chaque tri remplace le précédent) et 0 supprime la limite. Si le paramètre n'est pas renseigné, l'option globale MaxSortedColumns de app.GridView(...) s'applique (voir Options globales de LgGridView). Une valeur négative lève une exception. Les colonnes de regroupement ne comptent pas dans cette limite.
@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();
// Reçoit le tri complet : args.Sorts[0] est le tri principal (Key = identifiant de la colonne).
private Task OnSortChangedAsync(GridViewSortEventArgs args)
{
foreach ((string key, DataSortDirection direction) in args.Sorts)
{
// Synchroniser un état externe (URL, préférences…)
}
return Task.CompletedTask;
}
private sealed class OrderRow
{
public string Number { get; set; }
public DateTime Date { get; set; }
}
}
Regroupements de données
GroupBy regroupe les lignes par clé de colonne. Séparez plusieurs colonnes d'un même niveau par une virgule et plusieurs niveaux par /. GroupHeaderContent personnalise l'en-tête de groupe tout en conservant DefaultContent si besoin.
@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>
Sélection, clé métier et toolbar de sélection
Pour une sélection stable, renseignez KeyField sur une propriété unique : les éléments sont comparés sur cette clé et la sélection survit au rechargement des données. Sans KeyField, une grille distante (ControllerUri) utilise la propriété Id du modèle comme clé quand il en a une, même si le modèle redéfinit l'égalité : Id doit alors identifier l'élément de façon unique (des lignes partageant un Id, ou dont l'Id n'est pas renseigné, sont sélectionnées ensemble) ; sinon, renseignez KeyField. Une grille locale (Items), ou distante dont le modèle n'a pas de propriété Id, compare les éléments avec l'égalité du type (Equals / IEquatable<T>) : implémentez IEquatable<T> dans le modèle si l'unicité dépend de plusieurs propriétés (sans elle, l'égalité est celle des références et la sélection ne survit pas au rechargement des données distantes). La clé suit un changement de KeyField ou de la source de données (locale ou distante). La même clé retrouve la ligne rechargée par ReloadRow (voir GridEventRefreshMode) : une grille distante sans KeyField dont le modèle n'a pas de propriété Id ne peut pas recharger une ligne. ToolbarSelection ajoute des actions dans la barre affichée en bas de la grille lorsqu'au moins une ligne est sélectionnée.
@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
{
// Sélection liée à la grille : elle reste disponible pour les actions de toolbar.
private ICollection<OrderRow> _selection = new List<OrderRow>();
// Synchronise la collection sélectionnée et permet de connaître l'action utilisateur (sélection, désélection, tout sélectionner).
private Task OnRowSelectionAsync(GridViewSelectionEventArgs<OrderRow> args)
{
_selection = args.Selection;
return Task.CompletedTask;
}
// Supprime la sélection lorsque la fonctionnalité Delete de la grille est utilisée.
private Task OnDeleteAsync(GridViewSelectionActionEventArgs<OrderRow> args)
{
foreach (OrderRow item in args.Selection.ToList())
{
_orders.Remove(item);
}
return Task.CompletedTask;
}
// Exécute une action métier sur la sélection sans dépendre du bouton de suppression standard.
private Task OnArchiveSelectionAsync(ActionEventArgs args)
{
return Task.CompletedTask;
}
}
Clic cellule et commandes de ligne
OnCellClick au niveau de la grille reçoit l'élément de ligne et la clé de colonne. LgGridCommandColumn déclenche OnCommandClick; son RefreshMode décide si la ligne, la grille ou seulement le rendu doivent être actualisés.
@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
{
// Intercepte le clic cellule pour ouvrir un détail uniquement sur certaines colonnes.
private Task OnCellClickAsync(GridViewCellClickEventArgs<OrderRow> args)
{
if (args.ColumnKey == nameof(OrderRow.Number))
{
ShowInformation(args.Item.Number);
}
return Task.CompletedTask;
}
// Centralise les actions de ligne et choisit le niveau de rafraîchissement adapté à chaque commande.
private Task OnCommandClickAsync(GridViewCommandClickEventArgs<OrderRow> args)
{
args.RefreshMode = args.Command == "delete"
? GridEventRefreshMode.ReloadGrid
: GridEventRefreshMode.StateHasChangeRow;
return Task.CompletedTask;
}
}
Toolbar de la grille
LgGridView étant une LgFrame, ajoutez vos boutons dans son fragment Toolbar. Les boutons non entourés par LgCollapsableView restent visibles quel que soit l'état replié ; ViewMode.OnlyExpanded ou ViewMode.OnlyCollapsed permet d'adapter l'affichage.
@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
{
// Référence vers la grille : expose les méthodes publiques de rafraîchissement et d'export.
private LgGridView<OrderRow> _grid;
// Recharge les données de la grille, notamment après un changement de critères externes.
private Task OnRefreshAsync(ActionEventArgs args)
{
return _grid.RefreshAsync();
}
// Ouvre la fenêtre d'options d'export depuis un bouton métier de la toolbar.
private Task OnShowExportOptionsAsync(ActionEventArgs args)
{
return _grid.ShowExportOptionsAsync();
}
}
Édition, ajout et endpoints serveur
EditMode="GridEditMode.Row" édite une ligne complète, généralement avec LgGridEditColumn. EditMode="GridEditMode.Cell" édite cellule par cellule et permet de valider la nouvelle valeur avec OnValueChangingAsync. Activez GridFeature.Add pour afficher l'ajout et GridFeature.Delete pour supprimer la sélection.
@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
{
// Fournit les valeurs par défaut de la ligne ajoutée avant son édition par l'utilisateur.
private OrderRow CreateNewOrder()
{
return new OrderRow
{
Id = _orders.Count + 1,
Date = DateTime.Today,
};
}
// Persiste la nouvelle ligne après validation de l'ajout.
private Task OnValueAddAsync(GridViewItemActionEventArgs<OrderRow> args)
{
return Task.CompletedTask;
}
// Persiste les modifications d'une ligne complète.
private Task OnRowUpdateAsync(GridViewItemActionEventArgs<OrderRow> args)
{
return Task.CompletedTask;
}
// Supprime les lignes sélectionnées, puis laissez la grille rafraîchir son état.
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
{
// Valide une cellule avant sauvegarde : annulez le changement en positionnant 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;
}
}
Données liées entre plusieurs lignes
En mode Cell, chaque changement de valeur valide la ligne éditée entière, comme le serveur valide l'élément enregistré : IValidatableObject et les attributs de validation de tous les membres directs de l'élément, y compris ceux jamais saisis (un champ obligatoire vide est signalé dès la première modification de la ligne) et ceux sans colonne (listés dans le message d'erreur). Les objets imbriqués ne sont pas vérifiés. L'indicateur d'erreur s'affiche sur chaque cellule en erreur de cette ligne, y compris une cellule en lecture seule ou une cellule d'un autre champ (par exemple une règle IValidatableObject qui dépend de la valeur saisie). Quand plusieurs lignes partagent la même donnée, la valeur invalide est visible sur toutes les lignes, mais sans gestionnaire seule la ligne éditée affiche l'indicateur. OnCellValueChanged permet de désigner les lignes liées : après chaque changement de valeur, valide ou non, la grille les valide à nouveau et signale leurs cellules en erreur. Sans gestionnaire, aucune autre ligne n'est revalidée.
@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
{
// Déclare les lignes qui partagent leurs données avec la ligne éditée.
private void OnCellValueChanged(GridViewCellValueChangedEventArgs<LinkedItem> args)
{
args.RevalidateItems(i => i.Shared == args.Item.Shared);
}
}
GridViewCellValueChangedEventArgs<TItem> expose Item, ColumnKey, Value, PreviousValue et IsValid (résultat de la validation de la ligne éditée), ainsi que deux surcharges de RevalidateItems :
RevalidateItems(Func<TItem, bool> predicate)revalide les éléments acceptés par le prédicat ; un prédicatnulllèveArgumentNullException. Plusieurs appels se cumulent : un élément est revalidé dès qu'un des prédicats l'accepte ;RevalidateItems()revalide tous les éléments.
L'élément de la ligne éditée n'est jamais revalidé par ces appels : il a déjà été validé par la cellule. Les éléments retenus sont cherchés parmi les données connues du navigateur : tous les Items d'une grille locale (y compris ceux masqués par un filtre ou situés sur une autre page), ou les données chargées d'une grille distante ; une page distante non chargée n'est pas atteignable. Les lignes affichées sont revalidées tout de suite, les autres à leur affichage. Une ligne en erreur garde son indicateur quand elle quitte l'affichage puis y revient (changement de page, défilement d'une grille virtualisée, rechargement), jusqu'à ce qu'une validation la trouve valide. Une ligne en lecture seule (RowCanEditSelector) n'a pas de formulaire : elle n'affiche pas d'erreur.
Sur une ligne liée, les attributs de validation ne sont vérifiés à nouveau que pour le champ modifié et pour les champs qui étaient déjà en erreur (pour effacer un message devenu faux) : un champ obligatoire jamais saisi n'y est pas signalé. Les erreurs IValidatableObject sont toujours recalculées, sans message dans le toastr pour les lignes liées.
Seule une colonne liée à une propriété directe de l'élément (@bind-Value="item.Code") a un nom de champ de validation. Une colonne liée par un indexeur (item["Comment"]) ou par un chemin imbriqué (item.Data.Code) n'en a pas : sa cellule n'affiche pas d'indicateur et sa valeur est toujours enregistrée, mais sa modification recalcule l'état de la ligne, ce qui met à jour les cellules des autres champs (par exemple une règle sur Max qui dépend de Comment).
L'enregistrement suit la règle de la ligne entière : tant que la ligne éditée a une erreur, même sur un autre champ, la valeur saisie n'est pas enregistrée (IsValid vaut false, pas de PATCH, pas de rechargement, pas d'OnAfterUpdate) ; elle reste écrite dans l'élément et s'affiche. La saisie suivante qui rend la ligne valide l'enregistre. Le message d'erreur liste alors les erreurs des autres champs de la ligne (attributs de validation, erreurs renvoyées par le serveur), qui expliquent pourquoi la valeur n'est pas enregistrée ; l'erreur du champ saisi n'y est pas répétée. Exception : une colonne sans nom de champ n'est jamais bloquée. Sur une grille distante, le PATCH envoie l'élément entier (Data, qui porte aussi la valeur refusée plus tôt) et la colonne éditée (ColumnKey, Value, PreviousValue) : la valeur refusée n'est enregistrée côté serveur que si le contrôleur enregistre Data, pas s'il n'applique que la colonne éditée.
Si le serveur refuse le PATCH avec des erreurs de validation (réponse ValidationProblemDetails ou ModelState, dont les clés désignent les champs de Data, par exemple Data.Weight), l'erreur est affichée comme avant et les cellules de ces champs sont signalées sur la ligne éditée, y compris après un rechargement de la ligne (ReloadRow). Tant que ces champs ne sont pas modifiés, la ligne n'est plus enregistrée ; modifier un champ efface son erreur serveur. Une règle connue du seul serveur n'est pas retrouvée si la ligne quitte l'affichage puis y revient (seuls les attributs de validation sont vérifiés à nouveau). C'est notamment le cas quand le contrôleur valide tout l'élément reçu (validation automatique d'ASP.NET Core sur UpdateDataParameters<TItem>) alors que la grille ne vérifie que les champs modifiés.
L'annulation d'une saisie (touche Échap) rétablit la dernière valeur validée et garde les erreurs encore présentes sur la ligne (sur les autres champs, ou sur cette valeur elle-même) ; elle ne déclenche pas OnCellValueChanged.
OnCellValueChanged est déclenché après l'enregistrement d'une valeur valide, donc après le rechargement demandé par EditRefreshMode : avec ReloadGrid sur une grille distante, args.Item est l'instance d'avant le rechargement, alors que le prédicat reçoit les éléments rechargés. Comparez les éléments par clé ou par donnée (i => i.Group == args.Item.Group), pas par référence.
Après une édition, EditRefreshMode choisit le rafraîchissement (voir GridEventRefreshMode). Sur une grille distante (ControllerUri), ReloadRow recharge la ligne modifiée depuis le serveur en la retrouvant par la valeur de KeyField, ou de la propriété Id du modèle sans KeyField ; si le modèle n'a pas de propriété Id, la grille lève une erreur avant d'envoyer le PATCH ou le PUT : rien n'est envoyé au serveur. ReloadGrid recharge toutes les données ; OnAfterUpdate reçoit alors l'élément rechargé correspondant à la ligne éditée (retrouvé par KeyField ou Id, sinon par l'égalité du type), ou l'élément édité s'il ne figure plus dans les données. Sur une grille locale (Items), ReloadRow est sans effet après une édition.
Contrat endpoints d'édition distante
Quand ControllerUri est renseigné, la grille appelle la même route avec des verbes différents selon l'action :
- POST
api/Orders: ajoute une ligne (TItemen body). - PUT
api/Orders: met à jour une ligne complète en modeRow(TItemen body). - PATCH
api/Orders: met à jour une cellule en modeCell(UpdateDataParameters<TItem>en body). - DELETE
api/Orders: supprime la sélection (ICollection<TItem>en body).
[Route("api/[controller]")]
public class OrdersEditionController : LgControllerBase
{
// Ajoute la ligne créée par la grille lorsque GridFeature.Add est actif.
[HttpPost]
public IActionResult Add([FromBody] OrderVm item)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Met à jour une ligne complète lorsque EditMode vaut GridEditMode.Row.
[HttpPut]
public IActionResult UpdateRow([FromBody] OrderVm item)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Met à jour une seule cellule lorsque EditMode vaut GridEditMode.Cell.
[HttpPatch]
public IActionResult UpdateCell([FromBody] UpdateDataParameters<OrderVm> args)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
// Supprime les lignes sélectionnées lorsque GridFeature.Delete est actif.
[HttpDelete]
public IActionResult Delete([FromBody] ICollection<OrderVm> selection)
{
try
{
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
}
Pagination, disposition et options de colonnes
PaginationSizeSelector définit les tailles proposées (0 signifie « tout afficher »), DefaultPageSize fixe la taille initiale, PagerOnTop place le pager au-dessus. Les fonctionnalités Move, Freeze, Visibility, Resize et Group conditionnent les actions du menu de colonnes intégré.
@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
{
// Liste des tailles de page proposées ; 0 affiche toutes les lignes sur une seule page.
private readonly int[] _pageSizes = new[] { 10, 25, 50, 0 };
// Référence utilisée pour restaurer les largeurs calculées après un changement externe de disposition.
private LgGridView<OrderRow> _grid;
// Remet les colonnes à leur largeur par défaut et met à jour le profil courant.
private Task OnRestoreColumnWidthsAsync(ActionEventArgs args)
{
return _grid.RestoreDefaultColumnWidthsAsync();
}
}
Virtualisation des lignes (depuis la 4.0)
Avec Virtualize="true", seules les lignes visibles dans la zone de défilement sont rendues (composant Blazor <Virtualize>) : le coût d'affichage ne dépend plus du nombre de lignes de la page. C'est utile avec de grandes pages, notamment PageSize = 0 (« tout afficher »). VirtualizeItemSize donne la hauteur estimée d'une ligne en pixels (32 par défaut). Le composant la réajuste ensuite sur la hauteur réelle.
<LgGridView StateId="orders-virtual"
Items="_orders"
DefaultPageSize="0"
Virtualize="true"
VirtualizeItemSize="36">
<Columns Context="item">
<LgGridTextColumn @bind-Value="item.Number" Title="#OrderNumber" />
</Columns>
</LgGridView>
La virtualisation est désactivée par défaut. Pour l'activer sur toutes les grilles de l'application, utilisez OnConfigureBehavior ; le paramètre de la grille garde la priorité :
protected override void OnConfigureBehavior(ApplicationBehavior app)
{
app.GridView(options =>
{
options.Virtualize = true;
options.VirtualizeItemSize = 32f;
});
}
- Une grille groupée garde le rendu classique : la virtualisation ne s'applique qu'au corps non groupé. La ligne d'ajout et la ligne de calcul ne sont jamais virtualisées.
- Une ligne en édition qui sort de la zone visible est démontée. La grille sort alors du mode édition. Les valeurs déjà saisies restent sur l'item, mais elles ne sont pas enregistrées.
Style, copie de texte et accessibilité
RowCssClassSelector ajoute une classe par ligne. Pour autoriser la sélection/copier-coller du texte dans les cellules, ajoutez user-select: text sur la classe gridview-cell. Côté RGAA, préférez AriaLabel ou AriaLabelledBy, et évitez les regroupements (GroupBy, GroupName) ou le déplacement de colonnes lorsque l'ordre de lecture par lecteur d'écran est prioritaire.
@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
{
// Retourne une classe par ligne pour signaler visuellement les commandes à montant élevé.
private string GetRowCssClass(int index, OrderRow item)
{
return item.Amount > 1000m ? "orders-row-warning" : string.Empty;
}
}
.orders-copy-enabled .gridview-cell {
user-select: text;
}
Export des données
Exportable active la fenêtre d'export. VisibleExportList et HiddenExportList filtrent les providers, OnLoadExportProviders ajoute des providers pour une grille donnée, OnExport ajuste les options de la demande, et ConfigureExportColumn modifie les métadonnées de colonne exportée.
@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
{
// Ajoute des providers locaux à cette grille sans modifier la configuration globale de l'application.
private void LoadExportProviders(ExportProviderManager providers)
{
providers.Register<XlsxExportProvider>();
providers.Register<HtmlExportProvider>();
}
// Ajuste la demande d'export juste avant la génération du fichier.
private Task OnExportAsync(GridViewExportEventArgs args)
{
args.FileName = "orders";
args.GroupNameWithTitle = true;
args.IgnoreSort = false;
return Task.CompletedTask;
}
// Renomme ou reformate une colonne selon le provider d'export sélectionné.
private void ConfigureExportColumn(GridViewConfigureExportColumnEventArgs args)
{
if (args.ColumnKey == nameof(OrderRow.Amount))
{
args.ColumnTitle = "#AmountWithTax";
args.ColumnDisplayFormat = "N2";
}
}
}
Providers globaux et export serveur
Configurez les providers client dans OnConfigureBehavior et les providers serveur dans OnConfigureServices. L'export serveur est utilisé lorsque la grille est distante (ControllerUri) et que les sources des colonnes de sélection sont elles aussi distantes.
public partial class Main : LgCustomApplication
{
// Configure les options GridView communes à toute l'application cliente.
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>();
}
}
Export avancé (depuis la 3.33)
- Providers serveur déclaratifs : un contrôleur peut publier ses propres providers d'export via l'attribut
[ExportProvider<T>]; ils apparaissent automatiquement dans la fenêtre d'export, à côté des providers déclarés au niveau de l'application. - Paramètres d'export côté serveur : la méthode
[Queryable]appelée lors d'un export accède à la demande viaqueryArg.Export(culture, fuseau horaire, colonnes, provider sélectionné) quandqueryArg.IsExportRequestest vrai. Côté grille,OnExportpeut transmettre une valeur métier avecargs.SetExportArg<T>(…), relue côté serveur viaqueryArg.Export.GetExportArg<T>(). - Personnalisation de la fenêtre d'export : le paramètre
ExportOptionsContent(RenderFragment<ExportOptionsContext>) injecte du contenu personnalisé dans la modale (champs supplémentaires, options métier). - Capacités déclarées par provider :
IExportProviderDescriptionexposeSupportFilteredRowsetSupportDisplayedColumns(truepar défaut) ; la modale masque les cases « lignes filtrées » / « colonnes affichées » quand la capacité est absente. Ces choix ne sont proposés à l'utilisateur que s'il existe un filtre actif ou des colonnes masquées. - Pipeline d'import symétrique à l'export :
IImportColumn,ImportColumn,[ImportIgnore], sur l'abstraction communeITableColumn.
Contenu des profils et chargement partiel
Un profil enregistre, pour chaque colonne, le filtre, le tri, la position, la visibilité, le gel et la largeur, ainsi que les regroupements et la taille de page de la grille. Chaque élément correspond à un flag de GridFeature : Filter, Sort, Move (position), Visibility, Freeze, Resize (largeur), Group et Paging (taille de page).
ProfileFeatures limite les éléments enregistrés dans les profils et rechargés depuis eux. Move et Freeze vont ensemble, car les colonnes gelées sont les premières de l'ordre des colonnes : exclure l'un exclut l'autre. Contrairement à Features, un élément exclu reste utilisable : il n'est pas écrit dans les profils et, au chargement d'un profil, il garde son état courant (sauf si OnProfileLoadingAsync demande les valeurs par défaut). Si le paramètre n'est pas renseigné, l'option globale ProfileFeatures de app.GridView(...) s'applique (tous les éléments par défaut, voir Options globales de LgGridView).
OnProfileLoadingAsync (Func<GridViewProfileLoadingEventArgs, Task>) est appelé et attendu juste avant l'application d'un profil : la décision peut donc être asynchrone (une confirmation, par exemple). L'argument indique le profil chargé (Profile) et la raison du chargement (Reason, voir GridViewProfileLoadReason) :
LoadedFeaturescontient les éléments à charger, initialisés avec ceux gérés par les profils (ProfileFeatures). Retirer un flag exclut l'élément du chargement ; retirerMoveouFreezeretire les deux ; un élément non géré par les profils ne peut pas être ajouté.ExclusionMode(voirGridViewProfileExclusionMode) fixe l'état des éléments non chargés, y compris ceux exclus parProfileFeatures:KeepCurrent(par défaut) garde l'état courant,Defaultremet les valeurs par défaut (paramètresDefault*des colonnes,GroupByetDefaultPageSizede la grille). À l'initialisation, l'état courant est l'état par défaut : les deux modes sont équivalents.
Si le rappel lève une exception, elle est affichée et le profil est chargé en entier.
En sauvegarde automatique, l'état courant des éléments gérés par les profils est enregistré dans le profil courant à la modification suivante, y compris un élément conservé lors du changement de profil. Le bouton « Réinitialiser » remet tous les éléments à leurs valeurs par défaut, qu'ils soient gérés par les profils ou non.
@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
{
// Filtre client fourni par la page (paramètre d'URL par exemple), appliqué comme filtre par défaut.
private Filter _customerFilter;
// Choisit les él éments du profil appliqués selon la raison du chargement.
private Task OnProfileLoadingAsync(GridViewProfileLoadingEventArgs args)
{
if (args.Reason == GridViewProfileLoadReason.Initialization)
{
// À l'ouverture, le filtre client vient de la page (DefaultFilter), pas du dernier profil utilisé.
args.LoadedFeatures &= ~GridFeature.Filter;
}
else if (args.Reason == GridViewProfileLoadReason.Selection)
{
// Changer de profil change la disposition, mais garde les filtres saisis par l'utilisateur.
args.LoadedFeatures &= ~GridFeature.Filter;
args.ExclusionMode = GridViewProfileExclusionMode.KeepCurrent;
}
return Task.CompletedTask;
}
}
Profils partagés
ProfileId identifie l'espace de persistance, StorageMode choisit le stockage, SharedProfileAdministratorPolicy autorise la gestion des profils partagés et SharedProfileFilter filtre les profils proposés selon les droits ou les cibles.
@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
{
// Filtre réutilisé par une seule grille : il limite la visibilité des profils partagés aux policies attendues.
private readonly OrdersSharedProfileFilter _profileFilter = new();
}
public sealed class OrdersSharedProfileFilter : GridViewSharedProfileFilter
{
// Déclare les cibles proposées dans la fenêtre de création de profil partagé.
protected override void OnInitialized()
{
AddTarget("#Administrators", Policies.GridProfileAdmin);
AddTarget("#OrderManagers", Policies.OrderManager);
}
// Vérifie chaque tag associé au profil partagé avant de l'afficher à l'utilisateur courant.
public override async Task<bool> IsProfileVisibleAsync(string label, IReadOnlyList<string> tags)
{
foreach (string policy in tags)
{
if (!await IsInPolicyAsync(policy))
{
return false;
}
}
return true;
}
}
Propriétés
Paramètres de LgGridView
| Nom | Type | Défaut | Description |
|---|---|---|---|
StateId | string | — | Obligatoire. Identifiant unique pour mémoriser l'état (colonnes, filtres, tri, pagination). Crash runtime si absent. |
KeyField | string | null | Nom de la propriété identifiant une ligne : clé de la sélection (qui survit aux rechargements) et du rechargement d'une ligne (ReloadRow). Vide : une grille distante utilise la propriété Id du modèle s'il en a une ; sinon, les éléments sont comparés avec l'égalité du type (Equals / IEquatable<T>), et une grille distante ne peut pas recharger une ligne (erreur). La clé suit un changement de la source de données (locale ou distante). |
ProfileId | string | null | Identifiant d'un profil partagé (colonnes, filtres sauvegardés côté serveur). |
LayoutMode | GridLayoutMode | FitHeader | Mode de redimensionnement des colonnes au démarrage. |
GroupBy | string | null | Noms de champs de groupement séparés par virgule. |
DefaultGroupCollapsed | bool | false | Groupes repliés par défaut. |
EditMode | GridEditMode | None | Mode d'édition des données. |
DefaultShowFilters | bool? | null | Visibilité initiale des filtres ; quand elle est renseignée, elle remplace la valeur initiale de ShowFilters. |
ShowFilters | bool | false | Two-way binding de la visibilité des filtres ; masquer les filtres (y compris par le parent) les vide. |
ShowFiltersChanged | EventCallback<bool> | — | Callback du two-way binding de ShowFilters. |
OnFilterChanged | EventCallback<GridViewFilterChangedEventArgs> | — | Déclenché quand l'ensemble des filtres actifs change, y compris à l'application d'un profil filtré (Filters indexés par identifiant de colonne, HasFilters()). |
CurrentPage | int | 0 | Page courante (two-way avec CurrentPageChanged). |
DefaultPageSize | int? | null | Nombre de lignes par page par défaut. |
PaginationSizeSelector | int[] | null | Options disponibles pour le nombre de lignes par page, par exemple [10, 25, 50, 0] où 0 signifie « tout afficher ». |
PaginationButtonCount | int | 5 | Nombre de boutons de page affichés. |
GridViewDataCounter | GridViewDataCounter | null | Two-way binding du compteur de données. |
Exportable | bool? | null | Active ou désactive l'export. |
ShowFiltersSummary | bool? | null | Affiche un résumé des filtres actifs dans l'en-tête. |
Features | GridFeature | Default | Fonctionnalités autorisées de la grille. |
MaxSortedColumns | int? | null | Nombre maximal de colonnes triées en même temps (voir Tri et événement OnSortChanged). Si l'utilisateur trie une colonne de plus, le tri de plus faible priorité est retiré. 0 : pas de limite ; une valeur négative lève une exception. Si null, utilise l'option globale MaxSortedColumns de app.GridView(...) (4 par défaut). |
ProfileFeatures | GridFeature? | null | Éléments enregistrés dans les profils et rechargés depuis eux : Filter, Sort, Move, Visibility, Freeze, Resize, Group, Paging ; les autres flags sont ignorés ; Move et Freeze vont ensemble (exclure l'un exclut l'autre). Un élément exclu reste utilisable, n'est pas écrit dans les profils et garde son état courant au chargement d'un profil, sauf si OnProfileLoadingAsync demande les valeurs par défaut (voir Contenu des profils et chargement partiel). Si null, utilise l'option globale ProfileFeatures de app.GridView(...) (tous les éléments par défaut). |
GridStyleType | GridStyleType | Grid | Style visuel de la grille. |
WrapContent | bool | false | Autorise le retour à la ligne dans les cellules. |
Virtualize | bool? | null | Ne rend que les lignes visibles (voir Virtualisation des lignes). Si null, utilise l'option globale Virtualize de app.GridView(...) (false par défaut). Ignoré sur une grille groupée. |
VirtualizeItemSize | float? | null | Hauteur estimée d'une ligne en pixels pour la virtualisation. Si null, utilise l'option globale VirtualizeItemSize (32). |
DisplayDefaultTooltipHeader | bool? | null | Force l'affichage des tooltips dans les en-têtes. |
Paramètres propres à LgGridView<TItem>
| Nom | Type | Défaut | Description |
|---|---|---|---|
Columns | RenderFragment<TItem> | — | Définition des colonnes. Le paramètre de contexte est Context. |
Items | ICollection<TItem> | null | Source de données locale. |
ControllerUri | string | null | URL du contrôleur pour des données distantes via OData / Queryable. |
ControllerQueryArg | object | null | Argument additionnel envoyé avec les requêtes distantes. |
AllowCancellation | bool | false | Autorise l'annulation du chargement en mode ControllerUri. |
SelectableRows | bool | false | Rend les lignes sélectionnables au clic. |
Selection | ICollection<TItem> | null | Collection des éléments sélectionnés (two-way). |
EditRefreshMode | GridEventRefreshMode | None | Mode de rafraîchissement après édition. ReloadRow ne s'applique qu'à une grille distante et requiert KeyField ou une propriété Id dans le modèle (erreur avant l'envoi de la modification sinon). |
NewItem | Func<TItem> | null | Fonction de création d'un nouvel élément en mode ajout de ligne. |
NewItemAsync | Func<Task<TItem>> | null | Version asynchrone de NewItem. |
ItemModel | TItem | null | Instance vide utilisée pour la construction des colonnes. |
RowCssClassSelector | Func<int, TItem, string> | null | Sélecteur de classe CSS par ligne : (index, item) => cssClass. |
GroupHeaderContent | RenderFragment<GridGroupData<TItem>> | null | Contenu personnalisé de l'en-tête de groupe. |
ToolbarSelection | RenderFragment | null | Contenu additionnel de la toolbar de sélection. |
ExportOptionsContent | RenderFragment<ExportOptionsContext> | null | Contenu additionnel dans la boîte de dialogue d'export. |
NoDataTitle | string | "#GridViewNoDataTitle" | Titre affiché quand aucune donnée n'est disponible. |
NoDataDescription | string | "#GridViewNoDataDesc" | Description affichée quand aucune donnée n'est disponible. |
DataErrorTitle | string | "#GridViewErrorTitle" | Titre du message d'erreur de chargement. |
DisplayInputPageSelector | bool? | null | Affiche un sélecteur de page numérique. |
DisplaySuccessSaveMessage | bool? | null | Affiche un message de succès après sauvegarde. |
PagerOnTop | bool? | null | Affiche le pager en haut de la grille. |
AddItemOnTop | bool? | null | Ajoute les nouvelles lignes en tête. |
HiddenExportList | string | null | IDs de providers à masquer, par exemple "xlsx,csv". |
VisibleExportList | string | null | IDs de providers à forcer à l'affichage. |
ExportCulture | string | null | Culture utilisée pour l'export, par exemple "fr-FR". |
ConfigureExportColumn | Action<GridViewConfigureExportColumnEventArgs> | null | Configure chaque colonne lors de l'export. |
OnLoadExportProviders | Action<ExportProviderManager> | null | Initialise les providers d'export. |
Paramètres clés hérités de LgFrame
| Nom | Type | Défaut | Description |
|---|---|---|---|
Title | string | null | Titre affiché dans l'en-tête du frame. |
IconName | string | null | Icône affichée devant le titre. |
Kind | Kind | Kind.Primary | Variante visuelle du frame. |
Collapsable | bool | false | Autorise le repli de la grille. |
Collapsed | bool | false | État replié courant. |
Toolbar | RenderFragment | null | Toolbar rendue dans l'en-tête. |
CssClass | string | null | Classes CSS additionnelles. |
ShowHeader | bool | true | Masque l'en-tête si false. |
Cadre, export et divers
| Paramètre | Type | Description |
|---|---|---|
ChildContent | RenderFragment | Contenu du cadre (rendu). |
TitleContent | RenderFragment | Contenu personnalisé du titre. |
HeaderContent | RenderFragment | Contenu personnalisé de l'en-tête. |
FooterContent | RenderFragment | Contenu personnalisé du pied. |
SummaryContent | RenderFragment | Contenu du résumé. |
HeaderCssClass | string | Classes CSS de l'en-tête. |
ChildCssClass | string | Classes CSS du contenu. |
ButtonSize | ButtonSize? | Taille des boutons du cadre. |
DefaultCollapsed | bool? | État replié par défaut du cadre. |
CollapsedChanged | EventCallback<bool> | Liaison de l'état replié (@bind-Collapsed). |
OnToggle | EventCallback<ToggleFrameEventArgs> | Déclenché au repli/dépli du cadre. |
ExportFileName | string | Nom du fichier exporté. |
EditingState | GridViewEditingState | État d'ajout/édition courant. |
EditingStateChanged | EventCallback<GridViewEditingState> | Liaison de l'état d'ajout/édition. |
OnCommand | EventCallback<CommandEventArgs> | Déclenché à la réception d'une commande (CommandName). |
GridViewDataCounterChanged | EventCallback<GridViewDataCounter> | Liaison des compteurs de données de la grille. |
ProfileSaveMode | GridViewProfileSave? | Mode de sauvegarde des profils de grille. |
AdditionalAttributes | IReadOnlyDictionary<string, object> | Attributs HTML additionnels. |
ParentPolicy | LgAuthorizeView | (en cascade) Policies définies par un ancêtre. |
Événements
| Nom | Type | Description |
|---|---|---|
OnRowSelection | EventCallback<GridViewSelectionEventArgs<TItem>> | Déclenché quand la sélection de ligne change. |
OnSortChanged | EventCallback<GridViewSortEventArgs> | Déclenché après un tri par l'utilisateur ou l'application d'un profil (pas au chargement initial, ni quand le profil ne recharge pas le tri) ; Sorts liste les colonnes triées par ordre de tri, Key / SortDirection sont la colonne et le sens du tri principal. |
OnProfileLoadingAsync | Func<GridViewProfileLoadingEventArgs, Task> | Appelé et attendu juste avant l'application d'un profil (initialisation, sélection, profil par défaut après suppression du profil courant) ; Profile et Reason décrivent le chargement, LoadedFeatures (modifiable) les éléments chargés et ExclusionMode l'état des autres. Une exception est affichée et le profil est alors chargé en entier (voir Contenu des profils et chargement partiel). |
OnCellClick | EventCallback<GridViewCellClickEventArgs<TItem>> | Déclenché lors d'un clic sur une cellule. |
OnCommandClick | EventCallback<GridViewCommandClickEventArgs<TItem>> | Déclenché lors d'un clic sur un bouton de commande. |
OnValueChangingAsync | Func<GridViewValueChangingEventArgs<TItem>, Task> | Validation avant changement de valeur en mode Cell. |
OnCellValueChanged | EventCallback<GridViewCellValueChangedEventArgs<TItem>> | Déclenché après un changement de valeur en mode Cell, valide ou non, après l'enregistrement d'une valeur valide ; RevalidateItems() ou RevalidateItems(predicate) désigne les lignes liées à valider à nouveau, affichées ou non (voir Données liées entre plusieurs lignes). |
OnValueAdd | EventCallback<GridViewItemActionEventArgs<TItem>> | Ajout d'une ligne en mode Row. |
OnRowUpdate | EventCallback<GridViewItemActionEventArgs<TItem>> | Mise à jour d'une ligne en mode Row. |
OnDelete | EventCallback<GridViewSelectionActionEventArgs<TItem>> | Suppression de la sélection. |
OnAfterAdd | EventCallback<GridViewAfterActionEventArgs<TItem>> | Déclenché après ajout en mode Cell. |
OnAfterUpdate | EventCallback<GridViewAfterActionEventArgs<TItem>> | Déclenché après mise à jour en mode Cell. |
OnAfterDelete | EventCallback<GridViewAfterActionEventArgs<TItem>> | Déclenché après suppression en mode Cell. |
OnRowStateChanged | EventCallback<GridViewRowStateChangedEventArgs<TItem>> | Déclenché lors d'un changement d'état d'une ligne. |
OnExport | EventCallback<GridViewExportEventArgs> | Déclenché avant l'export pour le configurer. |
Énumérations associées
GridLayoutMode
Mode de redimensionnement des colonnes (propriété LayoutMode).
| Valeur | Description |
|---|---|
None | Aucun ajustement de largeur des colonnes. |
FitHeader | Ajuste les colonnes pour contenir l'en-tête (valeur par défaut). |
FitData | Ajuste les colonnes pour contenir les données. |
FitColumns | Ajuste les colonnes pour occuper toute la largeur disponible. |
GridEditMode
Mode d'édition de la grille (propriété EditMode).
| Valeur | Description |
|---|---|
None | Édition désactivée (valeur par défaut). |
Cell | Édition gérée au niveau de la cellule. |
Row | Édition gérée au niveau de la ligne. |
GridStyleType
Style visuel de la grille (propriété GridStyleType).
| Valeur | Description |
|---|---|
Grid | Rendu en tableau (valeur par défaut). |
Card | Rendu sous forme de cartes. |
GridEventRefreshMode
Mode de rafraîchissement après édition (propriété EditRefreshMode).
| Valeur | Description |
|---|---|
None | Aucun rafraîchissement du rendu de la ligne (appliqué uniquement à OnCommandClick). |
StateHasChangeRow | Rafraîchit le rendu de la ligne. |
ReloadRow | Recharge les données de la ligne, retrouvée par la valeur de KeyField. Sans KeyField : l'élément est recherché dans Items avec l'égalité du type (Equals / IEquatable<T> ; sans redéfinition de l'égalité, seule la même instance est retrouvée) sur une grille locale ; sur une grille distante, l'élément est retrouvé par sa propriété Id, et la grille lève une erreur si le modèle n'en a pas. Une ligne qui n'est plus trouvée garde son élément. Après une édition, ne s'applique qu'à une grille distante. |
ReloadGrid | Recharge les données de la grille entière. |
GridFeature (flags)
Fonctionnalités autorisées de la grille (propriété Features). Énumération [Flags] :
les valeurs se combinent (GridFeature.Filter | GridFeature.Sort).
| Valeur | Description |
|---|---|
None | Aucune fonctionnalité. |
Filter | Filtrage des colonnes. |
Sort | Tri des colonnes. |
Paging | Pagination. |
Count | Comptage des éléments correspondant au filtre. |
Profile | Gestion des profils. |
Resize | Redimensionnement des colonnes. |
Move | Déplacement des colonnes. |
Freeze | Gel des colonnes par l'utilisateur. |
Group | Regroupement des lignes par l'utilisateur. |
Visibility | Modification de la visibilité des colonnes. |
Edit | Modification des lignes existantes (si EditMode ≠ None). |
Add | Ajout de nouvelles lignes. |
Delete | Option de suppression dans la sélection. |
Default | Combinaison par défaut : `Filter |
All | Tout est autorisé (`Default |
GridViewProfileLoadReason
Raison du chargement d'un profil (propriété Reason de GridViewProfileLoadingEventArgs, argument de OnProfileLoadingAsync).
| Valeur | Description |
|---|---|
Initialization | Initialisation de la grille : dernier profil utilisé, sinon profil par défaut. |
Selection | Sélection du profil par l'utilisateur. |
ProfileRemoved | Suppression du profil courant : le profil par défaut est chargé. |
GridViewProfileExclusionMode
État des éléments exclus du chargement d'un profil (propriété ExclusionMode de GridViewProfileLoadingEventArgs).
| Valeur | Description |
|---|---|
KeepCurrent | Les éléments exclus gardent leur état courant (valeur par défaut). |
Default | Les éléments exclus reprennent leur valeur par défaut (paramètres Default* des colonnes, GroupBy et DefaultPageSize de la grille). |
Kind
Variante visuelle du frame (propriété Kind, héritée de LgFrame).
| Valeur | Description |
|---|---|
Primary | Style principal (valeur par défaut). |
Default | Style par défaut neutre. |
Secondary | Style secondaire. |
Success | Style « succès ». |
Error | Style « erreur ». |
Warning | Style « avertissement ». |
Info | Style « information ». |
Composants liés
LgGridTextColumn— colonne texte et référence des paramètres communsLgGridBaseColumn.LgGridCustomColumn<TColumnValue>— colonne liée à une valeur de type quelconque.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.