Affichages plan dans Xamarin.Mac

Cet article traite de l’utilisation des vues hiérarchiques dans une application Xamarin.Mac. Il décrit la création et la gestion des vues hiérarchiques dans Xcode et Interface Builder, et leur utilisation par programmation.

Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes vues hiérarchiques 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 hiérarchiques (ou éventuellement les créer directement en code C#).

Un mode Plan est un type de table qui permet à l’utilisateur de développer ou de réduire des lignes de données hiérarchiques. À l’instar d’un mode Tableau, un mode Plan affiche les données d’un ensemble d’éléments associés, avec des lignes représentant des éléments individuels et des colonnes représentant les attributs de ces éléments. Contrairement à un mode Tableau, les éléments d’un mode Plan ne sont pas dans une liste plate, ils sont organisés dans une hiérarchie, comme les fichiers et les dossiers sur un disque dur.

Exemple d’exécution d’application

Dans cet article, nous allons aborder les principes de base de l’utilisation des vues hiérarchiques 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 hiérarchiques

Un mode Plan est un type de table qui permet à l’utilisateur de développer ou de réduire des lignes de données hiérarchiques. À l’instar d’un mode Tableau, un mode Plan affiche les données d’un ensemble d’éléments associés, avec des lignes représentant des éléments individuels et des colonnes représentant les attributs de ces éléments. Contrairement à un mode Tableau, les éléments d’un mode Plan ne sont pas dans une liste plate, ils sont organisés dans une hiérarchie, comme les fichiers et les dossiers sur un disque dur.

Si un élément en mode Plan contient d’autres éléments, il peut être développé ou réduit par l’utilisateur. Un élément extensible affiche un triangle de divulgation, qui pointe vers la droite lorsque l’élément est réduit et pointe vers le bas lorsque l’élément est développé. Le fait de cliquer sur le triangle de divulgation entraîne le développement ou la réduction de l’élément.

La vue Plan (NSOutlineView) est une sous-classe du mode Table (NSTableView) et, en tant que telle, hérite d’une grande partie de son comportement de sa classe parente. Par conséquent, de nombreuses opérations prises en charge par un affichage Table, telles que la sélection de lignes ou de colonnes, le repositionnement de colonnes en faisant glisser les en-têtes de colonne, etc., sont également prises en charge par un mode Plan. Une application Xamarin.Mac contrôle ces fonctionnalités et peut configurer les paramètres du mode Plan (dans le code ou le Générateur d’interface) pour autoriser ou interdire certaines opérations.

Un mode Plan ne stocke pas ses propres données, mais s’appuie sur une source de données (NSOutlineViewDataSource) pour fournir à la fois les lignes et les colonnes requises, en fonction des besoins.

Le comportement d’un mode Plan peut être personnalisé en fournissant une sous-classe du délégué en mode Plan (NSOutlineViewDelegate) pour prendre en charge la gestion des colonnes hiérarchiques, le type pour sélectionner les fonctionnalités, la sélection et la modification de ligne, le suivi personnalisé et les affichages personnalisés pour les colonnes et lignes individuelles.

Étant donné qu’un mode Plan partage une grande partie de son comportement et de ses fonctionnalités avec un affichage Table, vous pouvez consulter notre documentation vues de tableau avant de continuer avec cet article.

Création et gestion des vues hiérarchiques 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 :

Sélection du storyboard main

La conception de fenêtre s’ouvre dans le générateur d’interface de Xcode :

Modification de l’interface utilisateur dans Xcode

Tapez outline dans la zone de recherche de l’inspecteur de bibliothèque pour faciliter la recherche des contrôles Mode Plan :

Sélection d’un mode Plan dans la bibliothèque

Faites glisser un mode Plan 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 :

Modification des contraintes

Sélectionnez le mode Plan dans la hiérarchie d’interface et les propriétés suivantes sont disponibles dans l’inspecteur d’attributs :

Capture d’écran montrant les propriétés disponibles dans l’inspecteur d’attribut.

  • Colonne hiérarchique : colonne de table dans laquelle les données hiérarchiques sont affichées.
  • Colonne hiérarchique d’enregistrement automatique : si true, la colonne hiérarchique est automatiquement enregistrée et restaurée entre les exécutions de l’application.
  • Retrait : quantité à mettre en retrait les colonnes sous un élément développé.
  • Retrait suit les cellules : si true, la marque de retrait est mise en retrait avec les cellules.
  • Enregistrement automatique des éléments développés : si true, l’état développé/réduit des éléments est automatiquement enregistré et restauré entre les exécutions de l’application.
  • 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.
  • 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 hiérarchiques 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 :

Capture d’écran montrant les propriétés disponibles pour la colonne de table sélectionnée 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 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 Detailscolonne .

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 :

Capture d’écran montrant les propriétés disponibles pour la cellule de tableau sélectionnée 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 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 :

Capture d’écran montrant les propriétés disponibles pour la cellule d’affichage de tableau sélectionnée 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 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 :

Capture d’écran montrant les propriétés disponibles pour la cellule d’affichage de tableau sélectionnée.

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.
  • First Runtime Layout Width : si true, la cellule préférera la largeur définie pour elle (manuellement ou automatiquement) lorsqu’elle est affichée lors de la première exécution de l’application.
  • Action : contrôle quand l’action modifier 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 stylé.
  • Annuler : si true, la cellule assume la responsabilité de son comportement d’annulation.

Sélectionnez l’affichage cellule de table (NSTableFieldCell) en bas d’une colonne table dans la hiérarchie d’interface :

Sélection de la vue de cellule de tableau

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 mode Plan et ses colonnes et cellules au code C# à l’aide d’actions et de points de vente (en fonction des fonctionnalités requises).

Le processus est le même pour n’importe quel élément Vue de plan que nous voulons exposer :

  1. Basculez vers l’Éditeur Assistant et vérifiez que le ViewController.h fichier est sélectionné :

    Sélection du fichier .h correct

  2. Sélectionnez le mode Plan dans la hiérarchie d’interface, puis cliquez dessus, puis faites glisser vers le ViewController.h fichier.

  3. Créez un point de sortie pour le mode Plan appelé ProductOutline:

    Capture d’écran montrant un point de vente appelé ProductOutline dans l’inspecteur d’attribut.

  4. Créez des points de vente pour les colonnes de tables appelées ProductColumn et DetailsColumn:

    Capture d’écran montrant un point de vente nommé DetailsColumn dans l’inspecteur d’attribut.

  5. Enregistrez les modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Ensuite, nous allons écrire le code affichant certaines données pour le plan lors de l’exécution de l’application.

Remplissage du mode Plan

Avec notre vue plan 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, créons une classe Product pour contenir les informations des lignes individuelles et des groupes de sous-produits. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter un>nouveau fichier... Sélectionnez Général>Classe vide, entrez Product comme nom, puis cliquez sur le bouton Nouveau :

Création d’une classe vide

Faites en sorte que le Product.cs fichier ressemble à ce qui suit :

using System;
using Foundation;
using System.Collections.Generic;

namespace MacOutlines
{
    public class Product : NSObject
    {
        #region Public Variables
        public List<Product> Products = new List<Product>();
        #endregion

        #region Computed Properties
        public string Title { get; set;} = "";
        public string Description { get; set;} = "";
        public bool IsProductGroup {
            get { return (Products.Count > 0); }
        }
        #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 NSOutlineDataSource pour fournir les données de notre plan comme demandé. 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 ProductOutlineDataSource 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 MacOutlines
{
    public class ProductOutlineDataSource : NSOutlineViewDataSource
    {
        #region Public Variables
        public List<Product> Products = new List<Product>();
        #endregion

        #region Constructors
        public ProductOutlineDataSource ()
        {
        }
        #endregion

        #region Override Methods
        public override nint GetChildrenCount (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products.Count;
            } else {
                return ((Product)item).Products.Count;
            }

        }

        public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, NSObject item)
        {
            if (item == null) {
                return Products [childIndex];
            } else {
                return ((Product)item).Products [childIndex];
            }

        }

        public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products [0].IsProductGroup;
            } else {
                return ((Product)item).IsProductGroup;
            }

        }
        #endregion
    }
}

Cette classe dispose d’un stockage pour les éléments de notre mode Plan et remplace le GetChildrenCount pour renvoyer le nombre de lignes dans la table. renvoie GetChild un élément parent ou enfant spécifique (tel que demandé par la vue Plan) et ItemExpandable définit l’élément spécifié comme parent ou enfant.

Enfin, nous devons créer une sous-classe de NSOutlineDelegate pour fournir le comportement de notre plan. 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 ProductOutlineDelegate comme nom, puis cliquez sur le bouton Nouveau.

Modifiez le ProductOutlineDelegate.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 MacOutlines
{
    public class ProductOutlineDelegate : NSOutlineViewDelegate
    {
        #region Constants
        private const string CellIdentifier = "ProdCell";
        #endregion

        #region Private Variables
        private ProductOutlineDataSource DataSource;
        #endregion

        #region Constructors
        public ProductOutlineDelegate (ProductOutlineDataSource datasource)
        {
            this.DataSource = datasource;
        }
        #endregion

        #region Override Methods

        public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
            // 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)outlineView.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;
            }

            // Cast item
            var product = item as Product;

            // Setup view based on the column selected
            switch (tableColumn.Title) {
            case "Product":
                view.StringValue = product.Title;
                break;
            case "Details":
                view.StringValue = product.Description;
                break;
            }

            return view;
        }
        #endregion
    }
}

Lorsque nous créons une instance du ProductOutlineDelegate, nous transmettons également un instance de qui ProductOutlineDataSource fournit les données pour le plan. La GetView méthode est chargée de renvoyer une vue (données) pour afficher la cellule d’une colonne et d’une ligne de données. Si possible, une vue existante est réutilisée pour afficher la cellule, si ce n’est pas une vue qui doit être créée.

Pour remplir le plan, nous allons modifier le MainWindow.cs fichier et faire en sorte que la AwakeFromNib méthode ressemble à ce qui suit :

public override void AwakeFromNib ()
{
    base.AwakeFromNib ();

    // Create data source and populate
    var DataSource = new ProductOutlineDataSource ();

    var Vegetables = new Product ("Vegetables", "Greens and Other Produce");
    Vegetables.Products.Add (new Product ("Cabbage", "Brassica oleracea - Leaves, axillary buds, stems, flowerheads"));
    Vegetables.Products.Add (new Product ("Turnip", "Brassica rapa - Tubers, leaves"));
    Vegetables.Products.Add (new Product ("Radish", "Raphanus sativus - Roots, leaves, seed pods, seed oil, sprouting"));
    Vegetables.Products.Add (new Product ("Carrot", "Daucus carota - Root tubers"));
    DataSource.Products.Add (Vegetables);

    var Fruits = new Product ("Fruits", "Fruit is a part of a flowering plant that derives from specific tissues of the flower");
    Fruits.Products.Add (new Product ("Grape", "True Berry"));
    Fruits.Products.Add (new Product ("Cucumber", "Pepo"));
    Fruits.Products.Add (new Product ("Orange", "Hesperidium"));
    Fruits.Products.Add (new Product ("Blackberry", "Aggregate fruit"));
    DataSource.Products.Add (Fruits);

    var Meats = new Product ("Meats", "Lean Cuts");
    Meats.Products.Add (new Product ("Beef", "Cow"));
    Meats.Products.Add (new Product ("Pork", "Pig"));
    Meats.Products.Add (new Product ("Veal", "Young Cow"));
    DataSource.Products.Add (Meats);

    // Populate the outline
    ProductOutline.DataSource = DataSource;
    ProductOutline.Delegate = new ProductOutlineDelegate (DataSource);

}

Si nous exécutons l’application, les éléments suivants s’affichent :

Vue réduite

Si nous développons un nœud en mode Plan, il se présente comme suit :

Vue développée

Tri par colonne

Nous allons autoriser l’utilisateur à trier les données dans le plan en cliquant sur un en-tête de colonne. Tout d’abord, double-cliquez sur le fichier pour l’ouvrir Main.storyboard pour le modifier dans Le Générateur d’interface. Sélectionnez la Product colonne, entrez Title pour la clé de tri, compare: pour le sélecteur et sélectionnez Ascendingpour la commande :

Définition de l’ordre de la clé de tri

Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Nous allons maintenant modifier le ProductOutlineDataSource.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;
    }
}

public override void SortDescriptorsChanged (NSOutlineView outlineView, NSSortDescriptor[] oldDescriptors)
{
    // Sort the data
    Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
    outlineView.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 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 :

Exemple de sortie triée

Sélection de lignes

Si vous souhaitez autoriser l’utilisateur à sélectionner une seule ligne, double-cliquez sur le fichier pour l’ouvrir Main.storyboard pour le modifier dans Le Générateur d’interface. Sélectionnez le mode Plan dans la hiérarchie d’interface et décochez la case à cocher Multiples dans l’inspecteur d’attribut :

Capture d’écran montrant l’inspecteur d’attribut dans lequel vous pouvez modifier le paramètre Multiple.

Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Ensuite, modifiez le ProductOutlineDelegate.cs fichier et ajoutez la méthode suivante :

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

Cela permet à l’utilisateur de sélectionner une seule ligne en mode Plan. Retournez false pour pour ShouldSelectItem pour tout élément que vous ne souhaitez pas que l’utilisateur soit en mesure de sélectionner ou false pour chaque élément si vous ne souhaitez pas que l’utilisateur puisse sélectionner des éléments.

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 pour le modifier dans Le Générateur d’interface. Sélectionnez le mode Plan dans la hiérarchie d’interface et case activée la case à cocher Multiples de l’inspecteur d’attribut :

Capture d’écran montrant l’inspecteur d’attribut dans lequel vous pouvez sélectionner Multiple.

Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Ensuite, modifiez le ProductOutlineDelegate.cs fichier et ajoutez la méthode suivante :

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

Cela permet à l’utilisateur de sélectionner une seule ligne en mode Plan. Retournez false pour pour ShouldSelectRow pour tout élément que vous ne souhaitez pas que l’utilisateur soit en mesure de sélectionner ou false pour chaque élément si vous ne souhaitez pas que l’utilisateur puisse sélectionner des éléments.

Tapez pour sélectionner une ligne

Si vous souhaitez autoriser l’utilisateur à taper un caractère avec le mode Plan sélectionné et à sélectionner la première ligne contenant ce caractère, double-cliquez sur le fichier pour l’ouvrir Main.storyboard pour le modifier dans le Générateur d’interface. Sélectionnez le mode Plan dans la hiérarchie d’interface et case activée la case à cocher Sélectionner le type dans l’inspecteur d’attribut :

Modification du type de ligne

Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Nous allons maintenant modifier le ProductOutlineDelegate.cs fichier et ajouter la méthode suivante :

public override NSObject GetNextTypeSelectMatch (NSOutlineView outlineView, NSObject startItem, NSObject endItem, string searchString)
{
    foreach(Product product in DataSource.Products) {
        if (product.Title.Contains (searchString)) {
            return product;
        }
    }

    // Not found
    return null;
}

La GetNextTypeSelectMatch méthode prend le donné searchString et retourne l’élément du premier Product qui a cette chaîne dans .Title

Réorganisation des colonnes

Si vous souhaitez autoriser l’utilisateur à faire glisser des colonnes dans le mode Plan, double-cliquez sur le fichier pour l’ouvrir Main.storyboard pour le modifier dans le Générateur d’interface. Sélectionnez le mode Plan dans la hiérarchie d’interface et case activée la case à cocher Réorganiser dans l’inspecteur d’attribut :

Capture d’écran montrant l’inspecteur d’attribut dans lequel vous pouvez sélectionner Réorganiser.

Si nous donnons une valeur pour la propriété Enregistrement automatique et case activée 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 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 ProductOutlineDelegate.cs fichier et ajouter la méthode suivante :

public override bool ShouldReorder (NSOutlineView outlineView, 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 , newColumnIndexsinon, retourner false;

Si nous exécutons l’application, nous pouvons faire glisser les en-têtes de colonne autour pour réorganiser nos colonnes :

Exemple de réorganisation des colonnes

Modification des cellules

Si vous souhaitez autoriser l’utilisateur à modifier les valeurs d’une cellule donnée, modifiez le ProductOutlineDelegate.cs fichier et modifiez la GetViewForItem méthode comme suit :

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // 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)outlineView.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 = !product.IsProductGroup;
    }

    // Tag view
    view.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.StringValue;
            break;
        case "Details":
            prod.Description = view.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.StringValue = product.Title;
        break;
    case "Details":
        view.StringValue = product.Description;
        break;
    }

    return view;
}

Maintenant, si nous exécutons l’application, l’utilisateur peut modifier les cellules dans la vue Table :

Exemple de modification de cellules

Utilisation d’images dans les vues Plan

Pour inclure une image dans la cellule d’un NSOutlineView, vous devez modifier la façon dont les données sont retournées par la méthode duGetViewNSTableViewDelegate'smode Plan afin d’utiliser un NSTableCellView au lieu du classique NSTextField. Par exemple :

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // 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)outlineView.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 = !product.IsProductGroup;
    }

    // Tag view
    view.TextField.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.TextField.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.TextField.StringValue;
            break;
        case "Details":
            prod.Description = view.TextField.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.ImageView.Image = NSImage.ImageNamed (product.IsProductGroup ? "tags.png" : "tag.png");
        view.TextField.StringValue = product.Title;
        break;
    case "Details":
        view.TextField.StringValue = product.Description;
        break;
    }

    return view;
}

Pour plus d’informations, consultez la section Utilisation d’images avec des vues de plan de notre documentation Utilisation des images .

Affichages hiérarchiques 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 considérablement réduire 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 avez 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 vue plan 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 hiérarchiques dans une application Xamarin.Mac. Nous avons vu les différents types et utilisations des vues hiérarchiques, comment créer et gérer des vues hiérarchiques dans le générateur d’interface de Xcode et comment utiliser les vues hiérarchiques en code C#.