Vues de tableau dans Xamarin.Mac
Cet article traite de l’utilisation des vues de table dans une application Xamarin.Mac. Il décrit la création de vues de table dans Xcode et Interface Builder et l’interaction avec celles-ci dans le code.
Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes vues de table qu’un développeur travaillant dans Objective-C et Xcode . Étant donné que Xamarin.Mac s’intègre directement à Xcode, vous pouvez utiliser le Générateur d’interface de Xcode pour créer et gérer vos vues de table (ou éventuellement les créer directement en code C#).
Un affichage Tableau affiche les données dans un format tabulaire contenant une ou plusieurs colonnes d’informations dans plusieurs lignes. En fonction du type d’affichage table créé, l’utilisateur peut trier par colonne, réorganiser des colonnes, ajouter des colonnes, supprimer des colonnes ou modifier les données contenues dans la table.
Dans cet article, nous allons aborder les principes fondamentaux de l’utilisation des vues de tableau dans une application Xamarin.Mac. Il est fortement recommandé de commencer par travailler sur l’article Hello, Mac , en particulier les sections Introduction to Xcode et Interface Builderet Outlets and Actions , car il couvre les concepts et techniques clés que nous allons utiliser dans cet article.
Vous pouvez également consulter la section Exposition des classes/méthodes C# du Objective-C document Xamarin.Mac Internals . Elle explique les commandes Register
et Export
utilisées pour relier vos classes C# à Objective-C des objets et des éléments d’interface utilisateur.
Présentation des vues de table
Un affichage Tableau affiche les données dans un format tabulaire contenant une ou plusieurs colonnes d’informations dans plusieurs lignes. Les affichages de tableau sont affichés à l’intérieur des affichages de défilement (NSScrollView
) et, à compter de macOS 10.7, vous pouvez utiliser n’importe quel NSView
affichage au lieu de Cellules (NSCell
) pour afficher les lignes et les colonnes. Cela dit, vous pouvez toujours utiliser NSCell
, mais vous allez généralement sous-classer NSTableCellView
et créer vos lignes et colonnes personnalisées.
Un mode Table ne stocke pas ses propres données, mais s’appuie sur une source de données (NSTableViewDataSource
) pour fournir à la fois les lignes et les colonnes requises, selon les besoins.
Le comportement d’un affichage table peut être personnalisé en fournissant une sous-classe du délégué d’affichage table (NSTableViewDelegate
) pour prendre en charge la gestion des colonnes de table, le type pour sélectionner les fonctionnalités, la sélection et la modification de ligne, le suivi personnalisé et les vues personnalisées pour les colonnes et les lignes individuelles.
Lors de la création d’affichages de tableau, Apple suggère les éléments suivants :
- Autorisez l’utilisateur à trier la table en cliquant sur un en-tête de colonne.
- Créez des en-têtes de colonne qui sont des noms ou des expressions substantifs courtes qui décrivent les données affichées dans cette colonne.
Pour plus d’informations, consultez la section Affichages de contenu des Instructions d’Apple relatives à l’interface utilisateur OS X.
Création et gestion des vues de table dans Xcode
Lorsque vous créez une application Xamarin.Mac Cocoa, vous obtenez une fenêtre vide standard par défaut. Cette fenêtre est définie dans un .storyboard
fichier automatiquement inclus dans le projet. Pour modifier la conception de vos fenêtres, dans le Explorateur de solutions, double-cliquez sur le Main.storyboard
fichier :
La conception de fenêtre s’ouvre dans le générateur d’interface de Xcode :
Tapez table
dans la zone de recherche de l’inspecteur de bibliothèque pour faciliter la recherche des contrôles d’affichage table :
Faites glisser un affichage Tableau sur le contrôleur d’affichage dans l’éditeur d’interface, faites-le remplir la zone de contenu du contrôleur d’affichage et définissez-le sur l’emplacement où il se réduit et s’agrandit avec la fenêtre de l’éditeur de contraintes :
Sélectionnez l’affichage Table dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :
- Mode contenu : vous permet d’utiliser des affichages (
NSView
) ou des cellules (NSCell
) pour afficher les données dans les lignes et les colonnes. À compter de macOS 10.7, vous devez utiliser views. - Floats Group Rows : si
true
, l’affichage Tableau dessine les cellules groupées comme si elles flottaient. - Colonnes : définit le nombre de colonnes affichées.
- En-têtes : si
true
, les colonnes auront des en-têtes. - Réorganisation : si
true
, l’utilisateur peut faire glisser la réorganisation des colonnes dans la table. - Redimensionnement : si
true
, l’utilisateur peut faire glisser les en-têtes de colonne pour redimensionner les colonnes. - Dimensionnement des colonnes : contrôle la façon dont la table dimensionne automatiquement les colonnes.
- Surbrillance : contrôle le type de mise en surbrillance utilisée par le tableau lorsqu’une cellule est sélectionnée.
- Autres lignes : si
true
, une autre ligne aura une couleur d’arrière-plan différente. - Grille horizontale : sélectionne le type de bordure dessinée horizontalement entre les cellules.
- Grille verticale : sélectionne le type de bordure dessinée verticalement entre les cellules.
- Couleur de grille : définit la couleur de la bordure de cellule.
- Arrière-plan : définit la couleur d’arrière-plan de la cellule.
- Sélection : vous permet de contrôler la façon dont l’utilisateur peut sélectionner des cellules dans le tableau comme suit :
- Multiple : si
true
, l’utilisateur peut sélectionner plusieurs lignes et colonnes. - Colonne : si
true
, l’utilisateur peut sélectionner des colonnes. - Type Sélectionner : si
true
, l’utilisateur peut taper un caractère pour sélectionner une ligne. - Vide : si
true
, l’utilisateur n’est pas tenu de sélectionner une ligne ou une colonne, la table n’autorise aucune sélection du tout.
- Multiple : si
- Enregistrement automatique : nom sous lequel le format des tables est automatiquement enregistré.
- Informations sur les colonnes : si
true
, l’ordre et la largeur des colonnes sont automatiquement enregistrés. - Sauts de ligne : sélectionnez la façon dont la cellule gère les sauts de ligne.
- Tronque la dernière ligne visible : si
true
, la cellule sera tronquée dans les données ne peut pas tenir à l’intérieur de ses limites.
Important
Sauf si vous conservez une application Xamarin.Mac héritée, NSView
les vues de table basées doivent être utilisées sur NSCell
les vues de table basées. NSCell
est considéré comme hérité et peut ne pas être pris en charge à l’avenir.
Sélectionnez une colonne de table dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :
- Titre : définit le titre de la colonne.
- Alignement : définissez l’alignement du texte dans les cellules.
- Police de titre : sélectionne la police du texte d’en-tête de la cellule.
- Clé de tri : clé utilisée pour trier les données dans la colonne. Laissez vide si l’utilisateur ne peut pas trier cette colonne.
- Sélecteur : action utilisée pour effectuer le tri. Laissez vide si l’utilisateur ne peut pas trier cette colonne.
- Ordre : ordre de tri des données des colonnes.
- Redimensionnement : sélectionne le type de redimensionnement de la colonne.
- Modifiable : si
true
, l’utilisateur peut modifier les cellules d’un tableau basé sur des cellules. - Masqué : si
true
, la colonne est masquée.
Vous pouvez également redimensionner la colonne en faisant glisser sa poignée (centrée verticalement sur le côté droit de la colonne) vers la gauche ou la droite.
Nous allons sélectionner chaque colonne dans notre vue Table et attribuer à la première colonne un titre et Product
la deuxième Details
colonne .
Sélectionnez une vue de cellule de tableau (NSTableViewCell
) dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :
Il s’agit de toutes les propriétés d’une vue standard. Vous avez également la possibilité de redimensionner les lignes de cette colonne ici.
Sélectionnez une cellule d’affichage de tableau (par défaut, il s’agit d’un NSTextField
) dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :
Vous aurez toutes les propriétés d’un champ de texte standard à définir ici. Par défaut, un champ de texte standard est utilisé pour afficher les données d’une cellule dans une colonne.
Sélectionnez une vue de cellule de tableau (NSTableFieldCell
) dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :
Les paramètres les plus importants sont les suivants :
- Disposition : sélectionnez la façon dont les cellules de cette colonne sont disposées.
- Utilise le mode ligne unique : si
true
, la cellule est limitée à une seule ligne. - Largeur de la disposition du premier runtime : si
true
, la cellule préfère la largeur définie pour elle (manuellement ou automatiquement) lorsqu’elle s’affiche lors de la première exécution de l’application. - Action : contrôle l’envoi de l’action Modifier pour la cellule.
- Comportement : définit si une cellule est sélectionnable ou modifiable.
- Texte enrichi : si la valeur est
true
, la cellule peut afficher du texte mis en forme et mis en forme. - Annuler : si
true
, la cellule assume la responsabilité de son comportement d’annulation.
Sélectionnez l’affichage cellule de tableau (NSTableFieldCell
) en bas d’une colonne de table dans la hiérarchie d’interface :
Cela vous permet de modifier la vue cellule de tableau utilisée comme modèle de base pour toutes les cellules créées pour la colonne donnée.
Ajout d’actions et de sorties
Comme tout autre contrôle d’interface utilisateur Cocoa, nous devons exposer notre vue Table et ses colonnes et cellules au code C# à l’aide d’actions et de sorties (en fonction des fonctionnalités requises).
Le processus est le même pour tout élément Table View que nous voulons exposer :
Basculez vers l’Éditeur assistant et vérifiez que le
ViewController.h
fichier est sélectionné :Sélectionnez l’affichage Table dans la hiérarchie d’interface, cliquez avec la touche Ctrl enfoncée et faites glisser vers le
ViewController.h
fichier.Créez un outlet pour le mode Table appelé
ProductTable
:Créez des sorties pour les colonnes de tables ainsi appelées
ProductColumn
etDetailsColumn
:Enregistrez les modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Ensuite, nous allons écrire le code affichant des données pour la table lors de l’exécution de l’application.
Remplissage de l’affichage Table
Avec notre vue table conçue dans Le Générateur d’interface et exposée via un outlet, nous devons ensuite créer le code C# pour le remplir.
Tout d’abord, nous allons créer une Product
classe pour contenir les informations des lignes individuelles. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter un>nouveau fichier... Sélectionnez Classe vide générale>, entrez Product
comme Nom, puis cliquez sur le bouton Nouveau :
Faites en sorte que le Product.cs
fichier ressemble à ce qui suit :
using System;
namespace MacTables
{
public class Product
{
#region Computed Properties
public string Title { get; set;} = "";
public string Description { get; set;} = "";
#endregion
#region Constructors
public Product ()
{
}
public Product (string title, string description)
{
this.Title = title;
this.Description = description;
}
#endregion
}
}
Ensuite, nous devons créer une sous-classe de NSTableDataSource
pour fournir les données de notre table à mesure qu’elles sont demandées. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter un>nouveau fichier... Sélectionnez Classe vide générale>, entrez ProductTableDataSource
comme Nom, puis cliquez sur le bouton Nouveau.
Modifiez le ProductTableDataSource.cs
fichier et faites-le ressembler à ce qui suit :
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDataSource : NSTableViewDataSource
{
#region Public Variables
public List<Product> Products = new List<Product>();
#endregion
#region Constructors
public ProductTableDataSource ()
{
}
#endregion
#region Override Methods
public override nint GetRowCount (NSTableView tableView)
{
return Products.Count;
}
#endregion
}
}
Cette classe dispose d’un stockage pour les éléments de l’affichage table et remplace le GetRowCount
pour renvoyer le nombre de lignes dans la table.
Enfin, nous devons créer une sous-classe de NSTableDelegate
pour fournir le comportement de notre table. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter un>nouveau fichier... Sélectionnez Classe vide générale>, entrez ProductTableDelegate
comme Nom, puis cliquez sur le bouton Nouveau.
Modifiez le ProductTableDelegate.cs
fichier et faites-le ressembler à ce qui suit :
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDelegate: NSTableViewDelegate
{
#region Constants
private const string CellIdentifier = "ProdCell";
#endregion
#region Private Variables
private ProductTableDataSource DataSource;
#endregion
#region Constructors
public ProductTableDelegate (ProductTableDataSource datasource)
{
this.DataSource = datasource;
}
#endregion
#region Override Methods
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = CellIdentifier;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = false;
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
#endregion
}
}
Lorsque nous créons une instance du ProductTableDelegate
, nous passons également une instance du ProductTableDataSource
qui fournit les données de la table. La GetViewForItem
méthode est chargée de renvoyer une vue (données) pour afficher la cellule d’une colonne et d’une ligne de type « give ». Si possible, une vue existante est réutilisée pour afficher la cellule, sinon une nouvelle vue doit être créée.
Pour remplir la table, nous allons modifier le ViewController.cs
fichier et faire en sorte que la AwakeFromNib
méthode ressemble à ce qui suit :
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Create the Product Table Data Source and populate it
var DataSource = new ProductTableDataSource ();
DataSource.Products.Add (new Product ("Xamarin.iOS", "Allows you to develop native iOS Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Android", "Allows you to develop native Android Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Mac", "Allows you to develop Mac native Applications in C#"));
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (DataSource);
}
Si nous exécutons l’application, les éléments suivants s’affichent :
Tri par colonne
Nous allons autoriser l’utilisateur à trier les données de la table en cliquant sur un en-tête de colonne. Tout d’abord, double-cliquez sur le Main.storyboard
fichier pour l’ouvrir et le modifier dans Interface Builder. Sélectionnez la Product
colonne, entrez Title
pour la clé de tri, compare:
pour le sélecteur , puis sélectionnez Ascending
la commande :
Sélectionnez la Details
colonne, entrez Description
pour la clé de tri, compare:
pour le sélecteur , puis sélectionnez Ascending
la commande :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Nous allons maintenant modifier le ProductTableDataSource.cs
fichier et ajouter les méthodes suivantes :
public void Sort(string key, bool ascending) {
// Take action based on key
switch (key) {
case "Title":
if (ascending) {
Products.Sort ((x, y) => x.Title.CompareTo (y.Title));
} else {
Products.Sort ((x, y) => -1 * x.Title.CompareTo (y.Title));
}
break;
case "Description":
if (ascending) {
Products.Sort ((x, y) => x.Description.CompareTo (y.Description));
} else {
Products.Sort ((x, y) => -1 * x.Description.CompareTo (y.Description));
}
break;
}
}
public override void SortDescriptorsChanged (NSTableView tableView, NSSortDescriptor[] oldDescriptors)
{
// Sort the data
if (oldDescriptors.Length > 0) {
// Update sort
Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
} else {
// Grab current descriptors and update sort
NSSortDescriptor[] tbSort = tableView.SortDescriptors;
Sort (tbSort[0].Key, tbSort[0].Ascending);
}
// Refresh table
tableView.ReloadData ();
}
La Sort
méthode nous permet de trier les données dans la source de données en fonction d’un champ de classe donné Product
dans l’ordre croissant ou décroissant. La méthode remplacée SortDescriptorsChanged
est appelée chaque fois que l’utilisation clique sur un en-tête de colonne. La valeur clé que nous définissons dans Le Générateur d’interface et l’ordre de tri de cette colonne lui seront transmises.
Si nous exécutons l’application et que nous cliquons dans les en-têtes de colonne, les lignes seront triées selon cette colonne :
Sélection de ligne
Si vous souhaitez autoriser l’utilisateur à sélectionner une seule ligne, double-cliquez sur le fichier pour l’ouvrir Main.storyboard
et le modifier dans le Générateur d’interface. Sélectionnez l’affichage Table dans la hiérarchie d’interface et décochez la case à cocher Multiple dans l’inspecteur d’attributs :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Ensuite, modifiez le ProductTableDelegate.cs
fichier et ajoutez la méthode suivante :
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
Cela permet à l’utilisateur de sélectionner n’importe quelle ligne dans le mode Tableau. Retournez false
le ShouldSelectRow
pour toute ligne que vous ne souhaitez pas que l’utilisateur puisse sélectionner ou false
pour chaque ligne si vous ne souhaitez pas que l’utilisateur puisse sélectionner des lignes.
Le mode Table (NSTableView
) contient les méthodes suivantes pour l’utilisation de la sélection de lignes :
DeselectRow(nint)
- Désélectionne la ligne donnée dans le tableau.SelectRow(nint,bool)
- Sélectionne la ligne donnée.false
Passez le deuxième paramètre pour ne sélectionner qu’une seule ligne à la fois.SelectedRow
- Retourne la ligne actuelle sélectionnée dans le tableau.IsRowSelected(nint)
- Retournetrue
si la ligne donnée est sélectionnée.
Sélection de plusieurs lignes
Si vous souhaitez autoriser l’utilisateur à sélectionner plusieurs lignes, double-cliquez sur le fichier pour l’ouvrir Main.storyboard
et le modifier dans le Générateur d’interface. Sélectionnez la vue Table dans la hiérarchie d’interface et case activée la case à cocher Multiple dans l’inspecteur d’attributs :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Ensuite, modifiez le ProductTableDelegate.cs
fichier et ajoutez la méthode suivante :
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
Cela permet à l’utilisateur de sélectionner n’importe quelle ligne dans le mode Tableau. Retournez false
le ShouldSelectRow
pour toute ligne que vous ne souhaitez pas que l’utilisateur puisse sélectionner ou false
pour chaque ligne si vous ne souhaitez pas que l’utilisateur puisse sélectionner des lignes.
Le mode Table (NSTableView
) contient les méthodes suivantes pour l’utilisation de la sélection de lignes :
DeselectAll(NSObject)
- Désélectionne toutes les lignes de la table. Utilisezthis
pour le premier paramètre à envoyer l’objet en effectuant la sélection.DeselectRow(nint)
- Désélectionne la ligne donnée dans le tableau.SelectAll(NSobject)
- Sélectionne toutes les lignes de la table. Utilisezthis
pour le premier paramètre à envoyer l’objet en effectuant la sélection.SelectRow(nint,bool)
- Sélectionne la ligne donnée.false
Passez pour le deuxième paramètre effacez la sélection et sélectionnez une seule ligne, passeztrue
pour étendre la sélection et inclure cette ligne.SelectRows(NSIndexSet,bool)
- Sélectionne l’ensemble de lignes donné.false
Passez pour le deuxième paramètre effacez la sélection et sélectionnez uniquement ces lignes, passeztrue
pour étendre la sélection et inclure ces lignes.SelectedRow
- Retourne la ligne actuelle sélectionnée dans le tableau.SelectedRows
- Retourne unNSIndexSet
contenant les index des lignes sélectionnées.SelectedRowCount
- Retourne le nombre de lignes sélectionnées.IsRowSelected(nint)
- Retournetrue
si la ligne donnée est sélectionnée.
Tapez pour sélectionner la ligne
Si vous souhaitez autoriser l’utilisateur à taper un caractère avec le mode Tableau sélectionné et à sélectionner la première ligne contenant ce caractère, double-cliquez sur le fichier pour l’ouvrir Main.storyboard
et le modifier dans le Générateur d’interface. Sélectionnez l’affichage Table dans la hiérarchie d’interface et case activée la case à cocher Sélectionner le type dans l’inspecteur d’attributs :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Nous allons maintenant modifier le ProductTableDelegate.cs
fichier et ajouter la méthode suivante :
public override nint GetNextTypeSelectMatch (NSTableView tableView, nint startRow, nint endRow, string searchString)
{
nint row = 0;
foreach(Product product in DataSource.Products) {
if (product.Title.Contains(searchString)) return row;
// Increment row counter
++row;
}
// If not found select the first row
return 0;
}
La GetNextTypeSelectMatch
méthode prend le donné searchString
et retourne la ligne du premier Product
qui contient cette chaîne dans .Title
Si nous exécutons l’application et tapez un caractère, une ligne est sélectionnée :
Réorganisation des colonnes
Si vous souhaitez autoriser l’utilisateur à faire glisser des colonnes de réorganisation dans le mode Tableau, double-cliquez sur le fichier pour l’ouvrir Main.storyboard
et le modifier dans le Générateur d’interface. Sélectionnez la vue Table dans la hiérarchie d’interface et case activée la case à cocher Réorganiser dans l’inspecteur d’attribut :
Si nous donnons une valeur pour la propriété Enregistrement automatique et case activée le champ Informations sur la colonne, toutes les modifications que nous apporterons à la disposition de la table seront automatiquement enregistrées pour nous et restaurées lors de la prochaine exécution de l’application.
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Nous allons maintenant modifier le ProductTableDelegate.cs
fichier et ajouter la méthode suivante :
public override bool ShouldReorder (NSTableView tableView, nint columnIndex, nint newColumnIndex)
{
return true;
}
La ShouldReorder
méthode doit retourner true
pour toute colonne qu’elle souhaite autoriser à faire glisser la réorganisation dans le newColumnIndex
, sinon, retourne false
;
Si nous exécutons l’application, nous pouvons faire glisser les en-têtes de colonne pour réorganiser nos colonnes :
Modification des cellules
Si vous souhaitez autoriser l’utilisateur à modifier les valeurs d’une cellule donnée, modifiez le ProductTableDelegate.cs
fichier et modifiez la GetViewForItem
méthode comme suit :
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = tableColumn.Title;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = true;
view.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.Tag].Title = view.StringValue;
break;
case "Details":
DataSource.Products [(int)view.Tag].Description = view.StringValue;
break;
}
};
}
// Tag view
view.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Maintenant, si nous exécutons l’application, l’utilisateur peut modifier les cellules dans l’affichage Tableau :
Utilisation d’images dans les vues de tableau
Pour inclure une image dans la cellule d’un NSTableView
, vous devez modifier la façon dont les données sont retournées par la méthode deGetViewForItem
NSTableViewDelegate's
l’affichage Table afin d’utiliser un NSTableCellView
au lieu du type standard NSTextField
. Par exemple :
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
if (tableColumn.Title == "Product") {
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
} else {
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
}
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
view.Identifier = tableColumn.Title;
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
}
// Tag view
view.TextField.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tags.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Pour plus d’informations, consultez la section Utilisation d’images avec des vues de tableau de notre documentation Utilisation des images .
Ajout d’un bouton Supprimer à une ligne
En fonction des exigences de votre application, il peut arriver que vous deviez fournir un bouton d’action pour chaque ligne du tableau. À titre d’exemple, nous allons développer l’exemple d’affichage table créé ci-dessus pour inclure un bouton Supprimer sur chaque ligne.
Tout d’abord, modifiez le Main.storyboard
dans le Générateur d’interface de Xcode, sélectionnez l’affichage Table et augmentez le nombre de colonnes à trois (3). Ensuite, remplacez le titre de la nouvelle colonne par Action
:
Enregistrez les modifications apportées au Storyboard et revenez à Visual Studio pour Mac pour synchroniser les modifications.
Ensuite, modifiez le ViewController.cs
fichier et ajoutez la méthode publique suivante :
public void ReloadTable ()
{
ProductTable.ReloadData ();
}
Dans le même fichier, modifiez la création du délégué d’affichage table à l’intérieur de la ViewDidLoad
méthode comme suit :
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (this, DataSource);
À présent, modifiez le ProductTableDelegate.cs
fichier pour inclure une connexion privée au contrôleur d’affichage et prendre le contrôleur en tant que paramètre lors de la création d’une nouvelle instance du délégué :
#region Private Variables
private ProductTableDataSource DataSource;
private ViewController Controller;
#endregion
#region Constructors
public ProductTableDelegate (ViewController controller, ProductTableDataSource datasource)
{
this.Controller = controller;
this.DataSource = datasource;
}
#endregion
Ensuite, ajoutez la nouvelle méthode privée suivante à la classe :
private void ConfigureTextField (NSTableCellView view, nint row)
{
// Add to view
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
// Configure
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
// Wireup events
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch (view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
// Tag view
view.TextField.Tag = row;
}
Cette opération prend toutes les configurations de l’affichage texte qui ont été effectuées précédemment dans la GetViewForItem
méthode et les place dans un emplacement unique pouvant être appelé (puisque la dernière colonne du tableau n’inclut pas un affichage texte, mais un bouton).
Enfin, modifiez la GetViewForItem
méthode et faites-la ressembler à ce qui suit :
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
// Configure the view
view.Identifier = tableColumn.Title;
// Take action based on title
switch (tableColumn.Title) {
case "Product":
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Details":
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Action":
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
// Add to view
view.AddSubview (button);
break;
}
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
return view;
}
Examinons plusieurs sections de ce code plus en détail. Tout d’abord, si une NSTableViewCell
action est en cours de création est effectuée en fonction du nom de la colonne. Pour les deux premières colonnes (Product et Details), la nouvelle ConfigureTextField
méthode est appelée.
Pour la colonne Action , un nouveau NSButton
est créé et ajouté à la cellule en tant que sous-affichage :
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
...
// Add to view
view.AddSubview (button);
La propriété du Tag
bouton est utilisée pour contenir le numéro de la ligne en cours de traitement. Ce numéro sera utilisé ultérieurement lorsque l’utilisateur demande la suppression d’une ligne dans l’événement button Activated
:
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
Au début du gestionnaire d’événements, nous obtenons le bouton et le produit qui se trouve sur la ligne de table donnée. Ensuite, une alerte est présentée à l’utilisateur confirmant la suppression de la ligne. Si l’utilisateur choisit de supprimer la ligne, la ligne donnée est supprimée de la source de données et la table est rechargée :
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
Enfin, si la cellule Vue de tableau est réutilisée au lieu d’être créée, le code suivant la configure en fonction de la colonne en cours de traitement :
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
Pour la colonne Action , tous les sous-affichages sont analysés jusqu’à ce que le NSButton
soit trouvé, puis sa Tag
propriété est mise à jour pour pointer vers la ligne actuelle.
Une fois ces modifications en place, lorsque l’application est exécutée, chaque ligne dispose d’un bouton Supprimer :
Lorsque l’utilisateur clique sur un bouton Supprimer , une alerte s’affiche lui demandant de supprimer la ligne donnée :
Si l’utilisateur choisit supprimer, la ligne est supprimée et la table est redessinée :
Vues de table de liaison de données
En utilisant Key-Value techniques de codage et de liaison de données dans votre application Xamarin.Mac, vous pouvez réduire considérablement la quantité de code que vous devez écrire et gérer pour remplir et utiliser des éléments d’interface utilisateur. Vous avez également l’avantage de découpler davantage vos données de stockage (modèle de données) de votre interface utilisateur frontale (Model-View-Controller), ce qui permet une conception d’application plus facile à gérer et plus flexible.
Key-Value Coding (KVC) est un mécanisme permettant d’accéder indirectement aux propriétés d’un objet, en utilisant des clés (chaînes spécialement mises en forme) pour identifier les propriétés au lieu d’y accéder via des variables instance ou des méthodes d’accesseur (get/set
). En implémentant des accesseurs compatibles codage Key-Value dans votre application Xamarin.Mac, vous obtenez l’accès à d’autres fonctionnalités macOS telles que l’observation Key-Value (KVO), la liaison de données, les données principales, les liaisons Cocoa et la scriptabilité.
Pour plus d’informations, consultez la section Liaison de données d’affichage table de notre documentation sur la liaison de données et le codage Key-Value .
Résumé
Cet article a examiné en détail l’utilisation des vues de tableau dans une application Xamarin.Mac. Nous avons vu les différents types et utilisations des vues de table, comment créer et gérer des vues de table dans le générateur d’interface de Xcode et comment utiliser des vues de table en code C#.