Boutons de grille
Les boutons de la barre d’outils à grille contrôlent la façon dont les utilisateurs interagissent avec les enregistrements dans un MainGrid ou SubGrid. Les boutons sont placés à l’intérieur du Buttons fragment de rendu et apparaissent automatiquement dans la barre d’outils de la grille.
Catégories de boutons
Il existe trois catégories de boutons de grille selon leur gestion des opérations d’enregistrement :
- Boutons de dialogue — Ouvrez un formulaire dans une boîte de dialogue pour créer ou modifier des enregistrements en ligne sans quitter la page.
- Boutons de navigation — Naviguez vers une URL de page distincte pour créer ou modifier des enregistrements.
- Boutons d’action — Effectuez des opérations comme supprimer, lier ou délier directement des enregistrements.
Choisir la bonne approche
Choisissez la forme du bouton en fonction du contexte dont l’utilisateur a besoin et de la quantité de nouvel état impliqué. Les trois seaux ci-dessous couvrent les cas typiques.
- Dialogue (en ligne) — Utilisez
NewRecordGridButton/OpenRecordGridButtonlorsque le formulaire correspond à une seule boîte de dialogue et que l’utilisateur bénéficie de rester sur la page actuelle (par exemple, en ajoutant un contact à un enregistrement de compte sans perdre les autres modifications non enregistrées du compte). Combinez avecBehavior="GridActionBehavior.WithGridContext"(par défaut) pour intégrer la sauvegarde du nouvel enregistrement dans le commit transactionnel du contexte parent. - Naviguer (page complète) — Utiliser
NavigateNewRecordGridButton/NavigateOpenRecordGridButtonlorsque la création ou la modification a besoin d’une surface plus riche que ce qu’un dialogue peut offrir confortablement : de nombreux champs, plusieurs onglets, des enregistrements liés propres, des pièces jointes ou des URL partageables. La route possède la sienneRecordContext, donc la grille mère n’a pas besoin d’être consciente de la complexité du formulaire. - Assistant (dialogue en plusieurs étapes) — À utiliser
NewRecordGridButton FormType="FormType.WizardForm"lorsque le formulaire comporte suffisamment de champs pour qu’un écran soit chargé, mais que les entrées sont suffisamment interdépendantes pour que la répartition entre les pages vaille le coût de navigation. Forme courante : la page 1 capture l’identité / la classification, la page 2 capture des détails qui dépendent des choix de la page 1.
Modes de flux et comportement de sauvegarde
Chaque bouton de grille basé sur le dialogue (NewRecordGridButton, OpenRecordGridButton, la paire lien/déliaison M2M) accepte un Behavior paramètre qui contrôle quand l’appel Dataverse sous-jacent est déclenché. Les deux valeurs correspondent à des séquences de requêtes substantiellement différentes :
Comportement = Immédiatement
Le bouton Enregistrer de la boîte de dialogue envoie la demande de création / mise à jour / association / dissociation directement à Dataverse via ExecuteMultipleAsync, rafraîchit la grille, puis ferme la boîte de dialogue. Le / RecordContext environnant MainContext (s’il y en a) ne voit pas le changement — il est déjà engagé.
- L’utilisateur clique sur Enregistrer dans la boîte de dialogue.
- Le dialogue valide, puis envoie un ou plusieurs
OrganizationRequests àExecuteMultipleAsynctravers . - Retour serveur ; la grille se rafraîchit ; Le dialogue se termine.
Choisissez ceci : le dialogue est autonome (pas de bouton Enregistrer au niveau de la page environnant), ou l’utilisateur souhaite vraiment que chaque action au niveau de ligne soit un commit à part entière. Chaque sauvegarde ici est indépendante — la complétion partielle d’un flux de travail multi-lignes reste sur le serveur.
Comportement = AvecContexteGrille (par défaut)
Le bouton Enregistrer de la boîte de dialogue met en scène la requête dans la file d’attente de la grille (_rowsToCreate / _rowsToUpdate dans Blazor, l’équivalent React dans useGridContext()) et ferme la boîte de dialogue. L’appel Dataverse lui-même ne s’active qu’une fois que le bouton Enregistrer de / RecordContextenvironnant MainContext n’est pas cliqué.
- L’utilisateur clique sur Enregistrer dans la boîte de dialogue → enregistrement (ou mise à jour / associé / dissociation) est mis en file d’attente sur la grille.
- Le dialogue se ferme. Le contexte parent de la page bascule vers
IsDirty=true; le bouton Enregistrer au niveau de la page s’active. - L’utilisateur clique sur la sauvegarde au niveau de la page → chaque changement de grille en file + la mise à jour propre de l’enregistrement parent + toutes les demandes en attente des autres descendants sont regroupées en un seul
ExecuteMultipleAsyncfichier . - Retour serveur ; la page se rafraîchit ; files d’attente dégagées ;
IsDirtyse retourne en arrière.
Choisissez ceci : la page a un parent RecordContext avec son propre bouton Enregistrer — l’utilisateur s’attend à une sémantique « sauvegarder toute la page », et un commit partiel (parent sauvegardé, lignes enfants non) serait un pire résultat que de tout reconstituer. C’est la norme pour cette raison.
Par défaut, c’est WithGridContext
WithGridContextest la fonction par défaut pour chaque bouton basé sur le dialogue — Immédiatement est l’option d’adhésion. Si votre grille se trouve en dehors d’un contexte parent (une page d’annonce autonome sans enregistrement au-dessus), la file n’a nulle part où se vider et le dialogue revient automatiquement à la sémantique Immédiatement.
NouveauBouton de la Grille du Record
Ouvre un formulaire de dialogue pour créer un nouvel enregistrement. Nécessite un TForm paramètre de type spécifiant le composant Razor pour être rendu en tant que forme.
Utilisez Location pour contrôler où apparaît le dialogue : DialogLocation.Center (par défaut) ou DialogLocation.Right (panneau latéral).
Utilisez FormType pour choisir entre une forme standard (FormType.Form) ou un assistant à plusieurs étapes (FormType.WizardForm).
À utiliser Behavior pour contrôler la date de création de l’enregistrement : GridActionBehavior.Immediately sauvegarde immédiatement sur Dataverse, tandis que GridActionBehavior.WithGridContext (par défaut) reporte la sauvegarde jusqu’à ce que le contexte parent soit validé.
{/* Au centre du dialogue avec la forme standard */}
<NewRecordGridButton>
<NewContactForm />
</NewRecordGridButton>
{/* Panneau latéral avec forme standard */}
<NewRecordGridButton location="panel">
<NewContactForm />
</NewRecordGridButton>
{/* Dialogue central sous forme de sorcier — les enfants sont <WizardRecordPage>
(pas besoin d’un prop FormType ; le bouton détecte automatiquement). */}
<NewRecordGridButton location="center">
<WizardRecordPage>
<TextEdit columnName="firstname" />
<TextEdit columnName="lastname" />
</WizardRecordPage>
<WizardRecordPage>
<MoneyEdit columnName="annualincome" />
</WizardRecordPage>
</NewRecordGridButton>
{/* Sauvegarder immédiatement au lieu de reporter */}
<NewRecordGridButton behavior="immediately">
<NewContactForm />
</NewRecordGridButton><!-- Au centre du dialogue avec la forme standard -->
<NewRecordGridButton TForm="NewContactForm" />
<!-- Panneau latéral avec forme standard -->
<NewRecordGridButton TForm="NewContactForm"
Location="DialogLocation.Right" />
<!-- Dialogue au centre avec la forme de l’assistant -->
<NewRecordGridButton TForm="NewContactForm"
Location="DialogLocation.Center"
FormType="FormType.WizardForm" />
<!-- Sauvegarder immédiatement au lieu de reporter -->
<NewRecordGridButton TForm="NewContactForm"
Behavior="GridActionBehavior.Immediately" />Exemple de type standard
Le TForm paramètre de type spécifie un composant Razor qui définit la disposition du formulaire. Un formulaire standard est simplement un composant Razor contenant des composants d’éditeur. Il peut inclure des onglets, des sections ou toute mise en page dont vous avez besoin.
// EditContactForm.tsx
<TabList>
<Tab value="general">Généralités</Tab>
<Tab value="other">Autres</Tab>
</TabList>
{activeTab === 'general' && (
<>
<TextEdit columnName="firstname" />
<TextEdit columnName="middlename" />
<TextEdit columnName="lastname" />
</>
)}
{activeTab === 'other' && (
<>
<MoneyEdit columnName="annualincome" />
<TextEdit columnName="telephone1" type="tel" />
</>
)}<!-- EditContactForm.razor -->
<FluentTabs Style="width: 100%">
<FluentTab Label="Généralités">
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="middlename" />
<TextEdit ColumnName="lastname" />
</FluentTab>
<FluentTab Label="Autres">
<MoneyEdit ColumnName="annualincome" />
<TextEdit ColumnName="telephone1"
TextFieldType="TextFieldType.Tel" />
</FluentTab>
</FluentTabs>Exemple de formulaire Wizard
Un formulaire d’assistant divise le processus de création en plusieurs étapes. Définissez chaque étape à l’aide de WizardRecordPage composants. Utilisez FormType="FormType.WizardForm" le bouton pour activer le mode assistant.
// NewContactForm.tsx
<WizardRecordPage>
<TextEdit columnName="firstname" />
<TextEdit columnName="middlename" />
<TextEdit columnName="lastname" />
</WizardRecordPage>
<WizardRecordPage>
<MoneyEdit columnName="annualincome" />
<TextEdit columnName="telephone1" type="tel" />
</WizardRecordPage><!-- NewContactForm.razor -->
<WizardRecordPage>
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="middlename" />
<TextEdit ColumnName="lastname" />
</WizardRecordPage>
<WizardRecordPage>
<MoneyEdit ColumnName="annualincome" />
<TextEdit ColumnName="telephone1"
TextFieldType="TextFieldType.Tel" />
</WizardRecordPage>Note
Lors de l’utilisation d’une forme d’assistant, on met
FormType="FormType.WizardForm"sur leNewRecordGridButton. L’assistant affiche la navigation Retour/Suivant et valide chaque page avant d’avancer.
Validation par page
Chacune WizardRecordPage se place par défaut sur ForceSuccessfulValidationBeforeSave="true": le bouton suivant de l’assistant exécute les validateurs de la page active avant d’avancer et annule la transition si un champ requis est vide ou invalide. Réglez false sur des pages qui ne contiennent que des champs optionnels pour que l’utilisateur puisse les passer. Le bouton Terminer de la page finale valide toujours, peu importe ce drapeau — le rejet côté serveur de la création est la seule façon de le contourner.
<WizardRecordPage>
{/* Champs obligatoires ici — l’utilisateur ne peut pas avancer tant qu’ils ne sont pas remplis */}
<TextEdit columnName="firstname" />
<TextEdit columnName="lastname" />
</WizardRecordPage>
<WizardRecordPage forceSuccessfulValidationBeforeSave={false}>
{/* Champs optionnels — l’utilisateur peut avancer même avec des erreurs de validation */}
<MoneyEdit columnName="annualincome" />
</WizardRecordPage><WizardRecordPage>
<!-- Champs obligatoires ici — l’utilisateur ne peut pas avancer tant qu’ils ne sont pas remplis -->
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="lastname" />
</WizardRecordPage>
<WizardRecordPage ForceSuccessfulValidationBeforeSave="false">
<!-- Champs optionnels — l’utilisateur peut avancer même avec des erreurs de validation -->
<MoneyEdit ColumnName="annualincome" />
</WizardRecordPage>Enregistrement partagé entre les pages
Tous WizardRecordPage les composants à l’intérieur d’un NewRecordGridButton partagent le même objet sous-jacent TableRecord — l’édition firstname à la page 1 et annualincome à la page 2 aboutit à une seule charge utile de création à la fin. Les s par page RecordContextse lient à la même instance d’enregistrement, de sorte que la navigation entre les étapes préserve les modifications en cours.
OpenRecordGridButton
Ouvre un formulaire de dialogue pour modifier le(s) enregistrement(s) sélectionné(s). Par exemple NewRecordGridButton, il nécessite un TForm paramètre de type. Lorsque plusieurs enregistrements sont sélectionnés, le formulaire affiche des champs partagés et applique des modifications à tous les enregistrements sélectionnés.
Le bouton d’édition se déclenche automatiquement lorsqu’une ligne est double-cliquée dans la grille. Réglez AllowNavigateOnRowDoubleClick="false" sur la grille pour supprimer le gestionnaire de double-clic.
Par défaut, la colonne du nom principal du tableau s’affiche également comme un hyperlien à chaque ligne, et cliquer sur le lien déclenche la même action d’édition que le double-clic. Définissez AllowNavigateOnPrimaryNameClick="false" sur la grille pour supprimer l’hyperliaison et afficher la cellule du nom principal en texte clair. Le lien hypertexte n’apparaît que lorsqu’un OpenRecordGridButton ou NavigateOpenRecordGridButton est enregistré, donc les grilles sans bouton d’édition ne sont pas affectées.
{/* Dialogue central (par défaut) */}
<OpenRecordGridButton>
<EditContactForm />
</OpenRecordGridButton>
{/* Panneau latéral */}
<OpenRecordGridButton location="panel">
<EditContactForm />
</OpenRecordGridButton>
{/* Sauvegarder immédiatement */}
<OpenRecordGridButton behavior="immediately">
<EditContactForm />
</OpenRecordGridButton>
{/* Supprimer le lien hypertexte du nom principal (le double-clic sur la ligne déclenche toujours la modification) */}
<MainGrid tableName="contact" allowNavigateOnPrimaryNameClick={false}>
<GridButtons>
<OpenRecordGridButton>
<EditContactForm />
</OpenRecordGridButton>
</GridButtons>
</MainGrid>
{/* Supprimer le gestionnaire de double-clic de ligne (le lien hypertexte du nom principal fonctionne toujours) */}
<MainGrid tableName="contact" allowOpenOnRowDoubleClick={false}>
<GridButtons>
<OpenRecordGridButton>
<EditContactForm />
</OpenRecordGridButton>
</GridButtons>
</MainGrid><!-- Dialogue central (par défaut) -->
<OpenRecordGridButton TForm="EditContactForm" />
<!-- Panneau latéral -->
<OpenRecordGridButton TForm="EditContactForm"
Location="DialogLocation.Right" />
<!-- Sauvegarder immédiatement -->
<OpenRecordGridButton TForm="EditContactForm"
Behavior="GridActionBehavior.Immediately" />
<!-- Supprimer le lien hypertexte du nom principal (le double-clic sur la ligne déclenche toujours la modification) -->
<MainGrid TableName="contact"
AllowNavigateOnPrimaryNameClick="false">
<Buttons>
<OpenRecordGridButton TForm="EditContactForm" />
</Buttons>
</MainGrid>
<!-- Supprimer le gestionnaire de double-clic de ligne (le lien hypertexte du nom principal fonctionne toujours) -->
<MainGrid TableName="contact"
AllowNavigateOnRowDoubleClick="false">
<Buttons>
<OpenRecordGridButton TForm="EditContactForm" />
</Buttons>
</MainGrid>NaviguerNouvelleEnregistrementBoutonGrille
Navigue vers une URL pour créer un nouvel enregistrement. Définissez le Url paramètre sur la page cible. Lorsqu’il est utilisé dans un SubGrid, le contexte de relation de l’enregistrement parent est automatiquement ajouté sous forme de paramètres de chaîne de requête.
Utilisez le OnClick rappel pour définir dynamiquement l’URL en fonction du contexte de la grille. Cela est utile pour les grilles multi-tables où l’URL dépend de la table de la vue sélectionnée.
{/* URL statique */}
<NavigateNewRecordGridButton url="/contacts/new" />
{/* URL dynamique basée sur la vue sélectionnée */}
<NavigateNewRecordGridButton
url="/contacts/new"
onClick={(ctx) => {
switch (ctx.gridContext.selectedView?.tableName) {
case 'contact': ctx.url = '/contacts/new'; break;
case 'account': ctx.url = '/accounts/new'; break;
default: throw new Error('Table inconnue');
}
}}
/><!-- URL statique -->
<NavigateNewRecordGridButton Url="/contacts/new" />
<!-- URL dynamique basée sur la vue sélectionnée -->
<NavigateNewRecordGridButton OnClick="OnNewClick" />
@code {
private async Task OnNewClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/new",
"account" => "/accounts/new",
_ => throw new Exception("Table inconnue"),
};
}
}NaviguerOuvrirEnregistrementGrilleBouton
Navigue vers une URL pour modifier l’enregistrement sélectionné. Le Url paramètre prend en charge {0} comme un substitut pour l’ID de l’enregistrement sélectionné.
{/* Construis l’URL par enregistrement via urlFor */}
<NavigateOpenRecordGridButton
urlFor={(record) => `/contacts/edit?contactId=${record.id}`}
/>
{/* URL dynamique basée sur la vue sélectionnée */}
<NavigateOpenRecordGridButton
urlFor={(record, ctx) => {
switch (ctx.selectedView?.tableName) {
case 'contact': return `/contacts/edit?contactId=${record.id}`;
case 'account': return `/accounts/edit?accountId=${record.id}`;
default: throw new Error('Table inconnue');
}
}}
/><!-- {0} est remplacé par l’ID de l’enregistrement sélectionné -->
<NavigateOpenRecordGridButton Url="/contacts/edit?contactId={0}" />
<!-- URL dynamique -->
<NavigateOpenRecordGridButton OnClick="OnEditClick" />
@code {
private async Task OnEditClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/edit?contactId={0}",
"account" => "/accounts/edit?accountId={0}",
_ => throw new Exception("Table inconnue"),
};
}
}NaviguerEnregistrerBoutonGrille
Un bouton de navigation polyvalent avec une étiquette, une icône et une URL personnalisées. Utilisez cela pour des actions de navigation personnalisées qui ne correspondent pas au nouveau schéma ou à l’édition.
<NavigateRecordGridButton
title="Voir les détails"
url="/records/details?id={0}"
buttonEnabledBehavior={GridButtonBehavior.OnlyOneSelected}
/><NavigateRecordGridButton Title="Voir les détails"
Url="/records/details?id={0}"
ButtonEnabledBehavior="GridButtonBehavior.WhenOneSelected" />SuppresserEnregistrementBoutonGrille
Supprime les enregistrements sélectionnés après avoir demandé la confirmation. À utiliser Mode pour contrôler si les enregistrements sont supprimés BulkOperationMode.Individually (un par un avec la progression) ou dans un seul lot.
{/* Supprimez-les un par un avec la progression */}
<DeleteRecordGridButton mode="individually" />
{/* Supprimer en un seul lot */}
<DeleteRecordGridButton mode="bulk" />
{/* Supprimer immédiatement sans reporter */}
<DeleteRecordGridButton behavior="immediately" /><!-- Supprimez-les un par un avec la progression -->
<DeleteRecordGridButton Mode="BulkOperationMode.Individually" />
<!-- Supprimer en un seul lot -->
<DeleteRecordGridButton Mode="BulkOperationMode.Batch" />
<!-- Supprimer immédiatement sans reporter -->
<DeleteRecordGridButton Behavior="GridActionBehavior.Immediately" />LinkExistingRecordGridButtonGrille
Ouvre une boîte de dialogue de recherche pour trouver et associer des enregistrements existants via une relation plusieurs-à-plusieurs. Applicable uniquement dans SubGrid les relations N :N.
<LinkExistingRecordGridButton />
{/* Associez-vous immédiatement */}
<LinkExistingRecordGridButton behavior="immediately" /><LinkExistingRecordGridButton />
<!-- Associez-vous immédiatement -->
<LinkExistingRecordGridButton Behavior="GridActionBehavior.Immediately" />DélierExistingRecordGrillBouton
Dissocie les dossiers sélectionnés d’une relation de plusieurs à plusieurs après avoir été sollicité pour confirmation. Applicable uniquement dans SubGrid les relations N :N.
<UnlinkExistingRecordGridButton />
{/* Dissociez-vous immédiatement */}
<UnlinkExistingRecordGridButton behavior="immediately" /><UnlinkExistingRecordGridButton />
<!-- Dissociez-vous immédiatement -->
<UnlinkExistingRecordGridButton Behavior="GridActionBehavior.Immediately" />GridButton
Un bouton entièrement personnalisé avec un OnClick rappel qui reçoit le fichier courant GridContext. Utilisez cela pour implémenter des actions personnalisées dans la barre d’outils.
<SubGrid relationshipName="contact_customer_accounts">
<GridButtons>
<NewRecordGridButton>
<NewContactForm />
</NewRecordGridButton>
<OpenRecordGridButton>
<EditContactForm />
</OpenRecordGridButton>
<DeleteRecordGridButton />
{/* Bouton personnalisé */}
<GridButton
label="Exportation"
icon={<ArrowDownload20Regular />}
enabledBehavior={GridButtonBehavior.OneOrMoreSelected}
onClick={async (ctx) => {
const selectedRecords = ctx.selectedRecords;
// Logique personnalisée — exporter, imprimer, envoyer des e-mails, etc.
}}
/>
</GridButtons>
</SubGrid><SubGrid RelationshipName="contact_customer_accounts">
<Buttons>
<NewRecordGridButton TForm="NewContactForm" />
<OpenRecordGridButton TForm="EditContactForm" />
<DeleteRecordGridButton />
<!-- Bouton personnalisé -->
<GridButton Label="Exportation"
Icon="@(new Icons.Regular.Size20.ArrowDownload())"
IsButtonEnabled="DefaultGridButtonBehavior.GetBehavior(GridButtonBehavior.WhenOneOrMoreSelected)"
OnClick="OnExportClick" />
</Buttons>
</SubGrid>
@code {
private async Task OnExportClick(GridContext context)
{
var selectedRecords = context.SelectedRecords;
// Logique personnalisée — exporter, imprimer, envoyer des e-mails, etc.
}
}Paramètres communs
Behavior— Contrôle si l’opération est exécutée immédiatement (GridActionBehavior.Immediately) ou différée jusqu’à ce que le contexte parent sauvegarde (GridActionBehavior.WithGridContext).Mode— Pour les boutons supprimer/lien/délier, il s’agit de contrôler si les opérations en bloc s’exécutent individuellement avec un retour d’avancement ou dans une seule requête batch.IsButtonEnabled/IsButtonVisible— Prédice qui contrôle l’état du bouton en fonction de la ligne sélectionnée en cours.
GridButton Classe
Paramètres
Nom | Type | Par défaut | Description |
|---|---|---|---|
Appearance | Appearance? | Stealth | Apparence visuelle du bouton de la barre d’outils. Par défaut à Appearance.Stealth Donc le bouton se lit comme transparent au repos et ne peint qu’un arrière-plan en survol — correspondant aux boutons Rafraîchissement et Paramètres de la grille. Le CSS à portée de la grille (Appearance.Accent pour un appel à l’action principal). |
Enabled | bool? | True | Outrepasse l’état activé du bouton quel que soit le résultat du GridButton.IsButtonEnabled prédicat. |
Icon | Icon? | Une icône optionnelle s’affiche sur le bouton. | |
IsButtonEnabled | Func<IEnumerable<GridRowContext>, bool> | Un prédicat évalué par rapport à la sélection de ligne courante pour déterminer si le bouton est activé. | |
IsButtonVisible | Func<IEnumerable<GridRowContext>, bool> | Un prédicat évalué par rapport à la sélection de ligne en cours pour déterminer si le bouton est visible. | |
IsOpenRecordButton | bool | False | Précise que c’est le bouton « Modifier » pour la grille. Un seul bouton devrait avoir cette propriété réglée sur « vrai » dans une grille. Le gestionnaire d’événements de ce bouton est appelé lorsqu’une ligne est « double-cliquée » dans la grille. |
Label | string? | L’inscription du texte s’affichait sur le bouton. | |
Tooltip | string? | Une infobulle optionnelle s’affiche lorsque l’utilisateur survole le bouton. |
AppearanceAppearance.Stealth Donc le bouton se lit comme transparent au repos et ne peint qu’un arrière-plan en survol — correspondant aux boutons Rafraîchissement et Paramètres de la grille. Le CSS à portée de la grille (Appearance.Accent pour un appel à l’action principal).EnabledGridButton.IsButtonEnabled prédicat.IconIsButtonEnabledIsButtonVisibleIsOpenRecordButtonLabelTooltipÉvénements
Nom | Type | Description |
|---|---|---|
OnClick | EventCallback<GridContext> | Déclenche lorsque le bouton est appuyé, fournissant le courant Components.GridContext au manipulateur. |
OnClickComponents.GridContext au manipulateur.