Vues de table 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 eux 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 dans le code C#).
Une vue de tableau affiche des données dans un format tabulaire contenant une ou plusieurs colonnes d’informations dans plusieurs lignes. En fonction du type de vue table en cours de création, 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 de base de l’utilisation des vues de table dans une application Xamarin.Mac. Il est fortement suggéré que vous travaillez tout d’abord dans l’article Hello, Mac , en particulier les sections Introduction to Xcode and Interface Builder et Outlets and Actions , car elle couvre les concepts et techniques clés que nous utiliserons dans cet article.
Vous pouvez également examiner les classes /méthodes C# exposantes dans Objective-Cla section du document interne Xamarin.Mac, ainsi que les Register
Export
instructions utilisées pour connecter vos classes C# à des objets et des Objective-C éléments d’interface utilisateur.
Présentation des vues de table
Une vue de tableau affiche des données dans un format tabulaire contenant une ou plusieurs colonnes d’informations dans plusieurs lignes. Les vues de tableau s’affichent à l’intérieur des vues de défilement (NSScrollView
) et à partir de macOS 10.7, vous pouvez utiliser n’importe quelle NSView
cellule (NSCell
) pour afficher à la fois les lignes et les colonnes. Cela dit, vous pouvez toujours utiliser NSCell
toutefois, vous allez généralement sous-classer NSTableCellView
et créer vos lignes et colonnes personnalisées.
Une vue table ne stocke pas ses propres données, au lieu de cela, elle s’appuie sur une source de données (NSTableViewDataSource
) pour fournir les lignes et les colonnes requises, selon les besoins.
Le comportement d’une vue de table peut être personnalisé en fournissant une sous-classe du délégué d’affichage de table (NSTableViewDelegate
) pour prendre en charge la gestion des colonnes de table, le type pour sélectionner les fonctionnalités, la sélection de lignes et la modification, le suivi personnalisé et les vues personnalisées pour les colonnes et lignes individuelles.
Lors de la création de vues de table, Apple suggère les éléments suivants :
- Autoriser l’utilisateur à trier la table en cliquant sur un en-têtes de colonne.
- Créez des en-têtes de colonne qui sont des noms ou des expressions abrégées qui décrivent les données affichées dans cette colonne.
Pour plus d’informations, consultez la section Affichages de contenu des instructions relatives à l’interface humaine OS X d’Apple.
Création et maintenance 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 votre conception windows, dans le Explorateur de solutions, double-cliquez sur le Main.storyboard
fichier :
Cela ouvre la conception de fenêtre 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 Table View :
Faites glisser une vue de tableau sur le contrôleur de vue dans l’éditeur d’interface, remplissez la zone de contenu du contrôleur de vue et définissez-la sur l’emplacement où elle se réduit et augmente avec la fenêtre de l’éditeur de contrainte :
Sélectionnez l’affichage table dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attribut :
- Mode contenu : vous permet d’utiliser des vues (
NSView
) ou des cellules (NSCell
) pour afficher les données dans les lignes et les colonnes. À compter de macOS 10.7, vous devez utiliser les vues. - Floats Group Rows - If
true
, l’affichage Tableau dessine les cellules groupées comme s’ils sont flottants. - 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 les colonnes dans la table. - Redimensionnement : si
true
, l’utilisateur pourra 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.
- Mise en surbrillance : contrôle le type de mise en surbrillance du tableau lorsqu’une cellule est sélectionnée.
- Autres lignes : si
true
, jamais une autre ligne aura une couleur d’arrière-plan différente. - Grille horizontale : sélectionne le type de bordure dessinée entre les cellules horizontalement.
- Grille verticale : sélectionne le type de bordure dessinée entre les cellules verticalement.
- Couleur de grille : définit la couleur de 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. - Tapez Select - If
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 s’adapter à 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’attribut :
- 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 pour les données des colonnes.
- Redimensionnement : sélectionne le type de redimensionnement de la colonne.
- Modifiable : si
true
, l’utilisateur peut modifier des cellules dans 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) gauche ou droite.
Nous allons sélectionner chaque colonne dans notre affichage table et donner à la première colonne un titre et Product
le deuxième Details
.
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’attribut :
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 Table View (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’attribut :
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 d’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’attribut :
Les paramètres les plus importants ici 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. - Première largeur de disposition du runtime - Si
true
, la cellule préfère la largeur définie pour elle (manuellement ou automatiquement) lorsqu’elle est affichée la première fois que l’application est exécutée. - Action : contrôle le moment où l’action d’édition est envoyée pour la cellule.
- Comportement : définit si une cellule est sélectionnable ou modifiable.
- Texte enrichi - Si
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 de cellule de tableau (NSTableFieldCell
) en bas d’une colonne de tableau dans la hiérarchie d’interface :
Cela vous permet de modifier l’affichage de cellule de tableau utilisé comme modèle de base pour toutes les cellules créées pour la colonne donnée.
Ajout d’actions et de points de sortie
Tout comme n’importe quel 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 n’importe quel é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 sur le contrôle et faites glisser vers le
ViewController.h
fichier.Créez un point de sortie pour la vue table appelée
ProductTable
:Créez des points de sortie pour les colonnes de tables également appelées
ProductColumn
etDetailsColumn
:Enregistrez les modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Ensuite, nous allons écrire le code pour afficher des données pour la table lors de l’exécution de l’application.
Remplissage de la vue Table
Avec notre vue de table conçue dans le Générateur d’interface et exposée via une sortie, 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
le 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 permettant de NSTableDataSource
fournir les données de notre table à mesure qu’elle est demandée. 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
le 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 notre vue table et remplace le GetRowCount
nombre de lignes dans la table.
Enfin, nous devons créer une sous-classe permettant de NSTableDelegate
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
le 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 transmettons également une instance de la ProductTableDataSource
table qui fournit les données de la table. La GetViewForItem
méthode est responsable du renvoi d’une vue (données) pour afficher la cellule d’une colonne et d’une ligne donner. Si possible, une vue existante sera 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
Permettez à l’utilisateur de trier les données dans la table en cliquant sur un en-tête de colonne. Tout d’abord, double-cliquez sur le Main.storyboard
fichier pour l’ouvrir pour modification dans le Générateur d’interface. Sélectionnez la Product
colonne, entrez Title
la clé de tri, compare:
pour le sélecteur et sélectionnez Ascending
l’ordre :
Sélectionnez la Details
colonne, entrez Description
la clé de tri, compare:
pour le sélecteur et sélectionnez Ascending
l’ordre :
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 substituée SortDescriptorsChanged
est appelée chaque fois que l’utilisation clique sur un en-tête de colonne. Il est passé la valeur clé que nous définissons dans le Générateur d’interface et l’ordre de tri de cette colonne.
Si nous exécutons l’application et cliquez dans les en-têtes de colonne, les lignes seront triées par cette colonne :
Sélection de lignes
Si vous souhaitez autoriser l’utilisateur à sélectionner une seule ligne, double-cliquez sur le Main.storyboard
fichier pour l’ouvrir pour modification dans Interface Builder. Sélectionnez la vue table dans la hiérarchie d’interface et décochez la case Multiple dans l’inspecteur d’attribut :
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 unique dans l’affichage table. Retournez false
pour toute ShouldSelectRow
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.
La vue 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. Passezfalse
le deuxième paramètre pour sélectionner une seule ligne à la fois.SelectedRow
- Retourne la ligne active 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 Main.storyboard
fichier pour l’ouvrir pour modification dans Interface Builder. Sélectionnez l’affichage de table dans la hiérarchie d’interface et 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 unique dans l’affichage table. Retournez false
pour toute ShouldSelectRow
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.
La vue table (NSTableView
) contient les méthodes suivantes pour l’utilisation de la sélection de lignes :
DeselectAll(NSObject)
- Désélectionne toutes les lignes du tableau. Utilisezthis
le premier paramètre à envoyer dans l’objet effectuant la sélection.DeselectRow(nint)
- Désélectionne la ligne donnée dans le tableau.SelectAll(NSobject)
- Sélectionne toutes les lignes du tableau. Utilisezthis
le premier paramètre à envoyer dans l’objet effectuant la sélection.SelectRow(nint,bool)
- Sélectionne la ligne donnée.false
Passez le deuxième paramètre pour effacer la sélection et sélectionnez une seule ligne, passeztrue
pour étendre la sélection et incluez cette ligne.SelectRows(NSIndexSet,bool)
- Sélectionne l’ensemble de lignes donné.false
Passez le deuxième paramètre pour effacer la sélection et sélectionnez uniquement une ligne, passeztrue
pour étendre la sélection et incluez ces lignes.SelectedRow
- Retourne la ligne active 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 une ligne
Si vous souhaitez permettre à l’utilisateur de taper un caractère avec l’affichage table sélectionné et de sélectionner la première ligne contenant ce caractère, double-cliquez sur le Main.storyboard
fichier pour l’ouvrir pour modification dans le Générateur d’interface. Sélectionnez l’affichage tableau dans la hiérarchie d’interface et cochez la case Sélectionner le type dans l’inspecteur d’attribut :
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 la valeur donnée searchString
et retourne la ligne du premier Product
qui a cette chaîne dans elle est Title
.
Si nous exécutons l’application et tapez un caractère, une ligne est sélectionnée :
Réorganiser les colonnes
Si vous souhaitez autoriser l’utilisateur à faire glisser des colonnes de réorganisation dans l’affichage table, double-cliquez sur le Main.storyboard
fichier pour l’ouvrir pour modification dans le Générateur d’interface. Sélectionnez l’affichage de table dans la hiérarchie d’interface et cochez la case Réorganiser dans l’inspecteur d’attribut :
Si nous accordons une valeur à la propriété Enregistrement automatique et vérifiez le champ Informations sur la colonne, toutes les modifications apportées à la disposition de la table seront automatiquement enregistrées pour nous et restaurées la prochaine fois que l’application est exécutée.
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 n’importe quelle colonne qu’elle souhaite autoriser à faire glisser à nouveau dans le newColumnIndex
retour , sinon ;false
Si nous exécutons l’application, nous pouvons faire glisser les en-têtes de colonne autour 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 le cadre de la cellule d’un NSTableView
, vous devez modifier la façon dont les données sont retournées par la méthode de NSTableViewDelegate's
GetViewForItem
la vue table pour utiliser une NSTableCellView
valeur plutôt que la méthode classique 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 Using Images with Table Views de notre documentation Working with Image .
Ajout d’un bouton Supprimer à une ligne
En fonction des exigences de votre application, il se peut que vous deviez fournir un bouton d’action pour chaque ligne du tableau. Par exemple, nous allons développer l’exemple d’affichage de table créé ci-dessus pour inclure un bouton Supprimer sur chaque ligne.
Tout d’abord, modifiez le Main.storyboard
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 dans le 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é de vue table à l’intérieur de ViewDidLoad
la 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 de vue 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;
}
Cela prend toutes les configurations d’affichage de texte qui étaient précédemment effectuées dans la GetViewForItem
méthode et les place dans un emplacement unique et pouvant être appelé (étant donné que la dernière colonne de la table n’inclut pas une vue de texte, mais un bouton).
Enfin, modifiez la méthode et faites-la GetViewForItem
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 plus en détail plusieurs sections de ce code. Tout d’abord, si une nouvelle NSTableViewCell
action est créée 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 nombre de lignes en cours de traitement. Ce nombre sera utilisé ultérieurement lorsque l’utilisateur demande la suppression d’une ligne dans l’événement du Activated
bouton :
// 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 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 Table View est réutilisée au lieu d’être créée, le code suivant le 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, toutes les sous-vues sont analysées jusqu’à ce qu’elles Tag
NSButton
soient trouvées, puis la propriété est mise à jour pour pointer vers la ligne actuelle.
Avec ces modifications en place, lorsque l’application est exécutée, chaque ligne aura un bouton Supprimer :
Lorsque l’utilisateur clique sur un bouton Supprimer , une alerte s’affiche pour lui demander de supprimer la ligne donnée :
Si l’utilisateur choisit de supprimer, la ligne sera supprimée et la table sera redessinée :
Vues de table de liaison de données
En utilisant des techniques de codage clé-valeur 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 bénéficiez également d’un découplage supplémentaire de vos données de stockage (modèle de données) de votre interface utilisateur frontale (modèle-vue-contrôleur), ce qui facilite la maintenance et la conception d’applications plus flexibles.
Le codage clé-valeur (KVC) est un mécanisme permettant d’accéder indirectement aux propriétés d’un objet, à l’aide de clés (chaînes spécialement mises en forme) pour identifier les propriétés au lieu de les accéder via des variables d’instance ou des méthodes d’accesseur (get/set
). En implémentant des accesseurs conformes au codage clé-valeur dans votre application Xamarin.Mac, vous accédez à d’autres fonctionnalités macOS telles que l’observation de valeur clé (KVO), la liaison de données, les données principales, les liaisons Cocoa et la scriptabilité.
Pour plus d’informations, consultez la section Table View Data Binding de notre documentation sur la liaison de données et le codage clé-valeur.
Résumé
Cet article a examiné en détail l’utilisation des vues de table 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 les vues de table dans le code C#.