Partager via


Vues de collection dans Xamarin.Mac

Cet article décrit l’utilisation des vues de collection dans une application Xamarin.Mac. Il couvre la création et la gestion des vues de collection dans Xcode et Interface Builder et leur utilisation par programme.

Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, le développeur a accès aux mêmes contrôles AppKit Collection View qu’un développeur travaillant dans Objective-C et Xcode . Étant donné que Xamarin.Mac s’intègre directement à Xcode, le développeur utilise le Générateur d’interface de Xcode pour créer et gérer des vues de collection.

A NSCollectionView affiche une grille de sous-vues organisées à l’aide d’un NSCollectionViewLayout. Chaque sous-vue de la grille est représentée par un NSCollectionViewItem élément qui gère le chargement du contenu de la vue à partir d’un .xib fichier.

Exemple d’exécution d’application

Cet article décrit les principes de base de l’utilisation des vues de collection 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 and Outlets and Actions , car il couvre les concepts et techniques clés utilisés dans cet article.

Vous pouvez également examiner les classes /méthodes C# exposantes dansObjective-Cla section du document interne Xamarin.Mac, ainsi que les RegisterExport instructions utilisées pour connecter vos classes C# à des objets et des Objective-C éléments d’interface utilisateur.

À propos des vues de collection

L’objectif principal d’une vue collection (NSCollectionView) est d’organiser visuellement un groupe d’objets de manière organisée à l’aide d’une disposition de vue collection (NSCollectionViewLayout), avec chaque objet individuel (NSCollectionViewItem) obtenant son propre affichage dans la collection plus grande. Les vues de collection fonctionnent via des techniques de codage de liaison de données et clé-valeur, et par conséquent, vous devez lire la documentation sur la liaison de données et le codage clé-valeur avant de continuer avec cet article.

L’affichage collection n’a pas d’élément d’affichage de collection intégré standard (comme un plan ou un affichage tableau), de sorte que le développeur est responsable de la conception et de l’implémentation d’un mode Prototype à l’aide d’autres contrôles AppKit tels que les champs d’image, les champs de texte, les étiquettes, etc. Cet affichage prototype permet d’afficher et d’utiliser chaque élément géré par l’affichage collection et est stocké dans un .xib fichier.

Étant donné que le développeur est responsable de l’apparence d’un élément d’affichage de collection, le mode Collection n’a aucune prise en charge intégrée de la mise en surbrillance d’un élément sélectionné dans la grille. L’implémentation de cette fonctionnalité sera abordée dans cet article.

Définition du modèle de données

Avant de lier une vue de collection dans le Générateur d’interface, une classe conforme KVC (Key-Value Coding)/Key-Value Observing (KVO) doit être définie dans l’application Xamarin.Mac pour agir comme modèle de données pour la liaison. Le modèle de données fournit toutes les données qui seront affichées dans la collection et reçoit toutes les modifications apportées aux données effectuées par l’utilisateur dans l’interface utilisateur lors de l’exécution de l’application.

Prenons l’exemple d’une application qui gère un groupe d’employés, la classe suivante peut être utilisée pour définir le modèle de données :

using System;
using Foundation;
using AppKit;

namespace MacDatabinding
{
    [Register("PersonModel")]
    public class PersonModel : NSObject
    {
        #region Private Variables
        private string _name = "";
        private string _occupation = "";
        private bool _isManager = false;
        private NSMutableArray _people = new NSMutableArray();
        #endregion

        #region Computed Properties
        [Export("Name")]
        public string Name {
            get { return _name; }
            set {
                WillChangeValue ("Name");
                _name = value;
                DidChangeValue ("Name");
            }
        }

        [Export("Occupation")]
        public string Occupation {
            get { return _occupation; }
            set {
                WillChangeValue ("Occupation");
                _occupation = value;
                DidChangeValue ("Occupation");
            }
        }

        [Export("isManager")]
        public bool isManager {
            get { return _isManager; }
            set {
                WillChangeValue ("isManager");
                WillChangeValue ("Icon");
                _isManager = value;
                DidChangeValue ("isManager");
                DidChangeValue ("Icon");
            }
        }

        [Export("isEmployee")]
        public bool isEmployee {
            get { return (NumberOfEmployees == 0); }
        }

        [Export("Icon")]
        public NSImage Icon
        {
            get
            {
                if (isManager)
                {
                    return NSImage.ImageNamed("IconGroup");
                }
                else
                {
                    return NSImage.ImageNamed("IconUser");
                }
            }
        }

        [Export("personModelArray")]
        public NSArray People {
            get { return _people; }
        }

        [Export("NumberOfEmployees")]
        public nint NumberOfEmployees {
            get { return (nint)_people.Count; }
        }
        #endregion

        #region Constructors
        public PersonModel ()
        {
        }

        public PersonModel (string name, string occupation)
        {
            // Initialize
            this.Name = name;
            this.Occupation = occupation;
        }

        public PersonModel (string name, string occupation, bool manager)
        {
            // Initialize
            this.Name = name;
            this.Occupation = occupation;
            this.isManager = manager;
        }
        #endregion

        #region Array Controller Methods
        [Export("addObject:")]
        public void AddPerson(PersonModel person) {
            WillChangeValue ("personModelArray");
            isManager = true;
            _people.Add (person);
            DidChangeValue ("personModelArray");
        }

        [Export("insertObject:inPersonModelArrayAtIndex:")]
        public void InsertPerson(PersonModel person, nint index) {
            WillChangeValue ("personModelArray");
            _people.Insert (person, index);
            DidChangeValue ("personModelArray");
        }

        [Export("removeObjectFromPersonModelArrayAtIndex:")]
        public void RemovePerson(nint index) {
            WillChangeValue ("personModelArray");
            _people.RemoveObject (index);
            DidChangeValue ("personModelArray");
        }

        [Export("setPersonModelArray:")]
        public void SetPeople(NSMutableArray array) {
            WillChangeValue ("personModelArray");
            _people = array;
            DidChangeValue ("personModelArray");
        }
        #endregion
    }
}

Le PersonModel modèle de données sera utilisé dans le reste de cet article.

Utilisation d’un affichage collection

La liaison de données avec une vue de collection est très similaire à la liaison avec un affichage table, telle qu’elle NSCollectionViewDataSource est utilisée pour fournir des données pour la collection. Étant donné que l’affichage collection n’a pas de format d’affichage prédéfini, davantage de travail est nécessaire pour fournir des commentaires d’interaction utilisateur et suivre la sélection de l’utilisateur.

Création du prototype de cellule

Étant donné que l’affichage collection n’inclut pas de prototype de cellule par défaut, le développeur doit ajouter un ou plusieurs .xib fichiers à l’application Xamarin.Mac pour définir la disposition et le contenu des cellules individuelles.

Effectuez les actions suivantes :

  1. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le nom du projet, puis sélectionnez Ajouter>un nouveau fichier...

  2. Sélectionnez Le contrôleur de vue Mac>, donnez-lui un nom (par EmployeeItem exemple, dans cet exemple) et cliquez sur le bouton Nouveau pour créer :

    Ajout d’un nouveau contrôleur d’affichage

    Cela ajoute un fichier et EmployeeItemController.xib un EmployeeItem.csEmployeeItemController.cs fichier à la solution du projet.

  3. Double-cliquez sur le EmployeeItemController.xib fichier pour l’ouvrir pour modification dans le Générateur d’interface de Xcode.

  4. Ajoutez un NSBoxcontrôle et NSImageView deux NSLabel contrôles à l’affichage et placez-les comme suit :

    Conception de la disposition du prototype de cellule

  5. Ouvrez l’ÉditeurAssistant et créez un point de sortie pour NSBox qu’il puisse être utilisé pour indiquer l’état de sélection d’une cellule :

    Exposition du NSBox dans une sortie

  6. Revenez à l’éditeur standard et sélectionnez l’affichage d’image.

  7. Dans l’inspecteur de liaison, sélectionnez Lier au>propriétaire du fichier et entrez un chemin de clé de modèle de :self.Person.Icon

    Liaison de l’icône

  8. Sélectionnez la première étiquette et, dans l’inspecteur de liaison, sélectionnez Lier au>propriétaire du fichier et entrez un chemin de clé de modèle de self.Person.Name:

    Liaison du nom

  9. Sélectionnez la deuxième étiquette et, dans l’inspecteur de liaison, sélectionnez Lier au>propriétaire du fichier et entrez un chemin de clé de modèle :self.Person.Occupation

    Liaison de l’occupation

  10. Enregistrez les modifications dans le .xib fichier et revenez à Visual Studio pour synchroniser les modifications.

Modifiez le EmployeeItemController.cs fichier et faites-le ressembler à ce qui suit :

using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using AppKit;

namespace MacCollectionNew
{
    /// <summary>
    /// The Employee item controller handles the display of the individual items that will
    /// be displayed in the collection view as defined in the associated .XIB file.
    /// </summary>
    public partial class EmployeeItemController : NSCollectionViewItem
    {
        #region Private Variables
        /// <summary>
        /// The person that will be displayed.
        /// </summary>
        private PersonModel _person;
        #endregion

        #region Computed Properties
        // strongly typed view accessor
        public new EmployeeItem View
        {
            get
            {
                return (EmployeeItem)base.View;
            }
        }

        /// <summary>
        /// Gets or sets the person.
        /// </summary>
        /// <value>The person that this item belongs to.</value>
        [Export("Person")]
        public PersonModel Person
        {
            get { return _person; }
            set
            {
                WillChangeValue("Person");
                _person = value;
                DidChangeValue("Person");
            }
        }

        /// <summary>
        /// Gets or sets the color of the background for the item.
        /// </summary>
        /// <value>The color of the background.</value>
        public NSColor BackgroundColor {
            get { return Background.FillColor; }
            set { Background.FillColor = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="T:MacCollectionNew.EmployeeItemController"/> is selected.
        /// </summary>
        /// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
        /// <remarks>This also changes the background color based on the selected state
        /// of the item.</remarks>
        public override bool Selected
        {
            get
            {
                return base.Selected;
            }
            set
            {
                base.Selected = value;

                // Set background color based on the selection state
                if (value) {
                    BackgroundColor = NSColor.DarkGray;
                } else {
                    BackgroundColor = NSColor.LightGray;
                }
            }
        }
        #endregion

        #region Constructors
        // Called when created from unmanaged code
        public EmployeeItemController(IntPtr handle) : base(handle)
        {
            Initialize();
        }

        // Called when created directly from a XIB file
        [Export("initWithCoder:")]
        public EmployeeItemController(NSCoder coder) : base(coder)
        {
            Initialize();
        }

        // Call to load from the XIB/NIB file
        public EmployeeItemController() : base("EmployeeItem", NSBundle.MainBundle)
        {
            Initialize();
        }

        // Added to support loading from XIB/NIB
        public EmployeeItemController(string nibName, NSBundle nibBundle) : base(nibName, nibBundle) {

            Initialize();
        }

        // Shared initialization code
        void Initialize()
        {
        }
        #endregion
    }
}

En examinant ce code en détail, la classe hérite de ce qui lui permet NSCollectionViewItem d’agir en tant que prototype pour une cellule d’affichage de collection. La Person propriété expose la classe utilisée pour la liaison de données à la vue d’image et aux étiquettes dans Xcode. Il s’agit d’une instance du PersonModel fichier créé ci-dessus.

La BackgroundColor propriété est un raccourci vers les NSBox contrôles qui seront utilisés pour afficher l’état de sélection d’une FillColor cellule. En substituant la Selected propriété du NSCollectionViewItemcode suivant, le code suivant définit ou efface cet état de sélection :

public override bool Selected
{
    get
    {
        return base.Selected;
    }
    set
    {
        base.Selected = value;

        // Set background color based on the selection state
        if (value) {
            BackgroundColor = NSColor.DarkGray;
        } else {
            BackgroundColor = NSColor.LightGray;
        }
    }
}

Création de la source de données de vue de collecte

Une source de données de vue de collection (NSCollectionViewDataSource) fournit toutes les données d’une vue de collection et crée et remplit une cellule de vue de collection (à l’aide du .xib prototype) comme requis pour chaque élément de la collection.

Ajoutez une nouvelle classe au projet, appelez-le CollectionViewDataSource et faites-le ressembler à ce qui suit :

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

namespace MacCollectionNew
{
    /// <summary>
    /// Collection view data source provides the data for the collection view.
    /// </summary>
    public class CollectionViewDataSource : NSCollectionViewDataSource
    {
        #region Computed Properties
        /// <summary>
        /// Gets or sets the parent collection view.
        /// </summary>
        /// <value>The parent collection view.</value>
        public NSCollectionView ParentCollectionView { get; set; }

        /// <summary>
        /// Gets or sets the data that will be displayed in the collection.
        /// </summary>
        /// <value>A collection of PersonModel objects.</value>
        public List<PersonModel> Data { get; set; } = new List<PersonModel>();
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="T:MacCollectionNew.CollectionViewDataSource"/> class.
        /// </summary>
        /// <param name="parent">The parent collection that this datasource will provide data for.</param>
        public CollectionViewDataSource(NSCollectionView parent)
        {
            // Initialize
            ParentCollectionView = parent;

            // Attach to collection view
            parent.DataSource = this;

        }
        #endregion

        #region Override Methods
        /// <summary>
        /// Gets the number of sections.
        /// </summary>
        /// <returns>The number of sections.</returns>
        /// <param name="collectionView">The parent Collection view.</param>
        public override nint GetNumberOfSections(NSCollectionView collectionView)
        {
            // There is only one section in this view
            return 1;
        }

        /// <summary>
        /// Gets the number of items in the given section.
        /// </summary>
        /// <returns>The number of items.</returns>
        /// <param name="collectionView">The parent Collection view.</param>
        /// <param name="section">The Section number to count items for.</param>
        public override nint GetNumberofItems(NSCollectionView collectionView, nint section)
        {
            // Return the number of items
            return Data.Count;
        }

        /// <summary>
        /// Gets the item for the give section and item index.
        /// </summary>
        /// <returns>The item.</returns>
        /// <param name="collectionView">The parent Collection view.</param>
        /// <param name="indexPath">Index path specifying the section and index.</param>
        public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
        {
            var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
            item.Person = Data[(int)indexPath.Item];

            return item;
        }
        #endregion
    }
}

En examinant ce code en détail, la classe hérite NSCollectionViewDataSource et expose une liste d’instances par le biais de PersonModel sa Data propriété.

Étant donné que cette collection n’a qu’une seule section, le code remplace la GetNumberOfSections méthode et retourne 1toujours . En outre, la GetNumberofItems méthode est substituée à elle retourne le nombre d’éléments dans la Data liste des propriétés.

La GetItem méthode est appelée chaque fois qu’une nouvelle cellule est requise et ressemble à ce qui suit :

public override NSCollectionViewItem GetItem(NSCollectionView collectionView, NSIndexPath indexPath)
{
    var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
    item.Person = Data[(int)indexPath.Item];

    return item;
}

La MakeItem méthode de l’affichage collection est appelée pour créer ou retourner une instance réutilisable de l’élément EmployeeItemController et sa Person propriété est définie sur l’élément affiché dans la cellule demandée.

Le EmployeeItemController contrôleur de vue de collection doit être inscrit au préalable à l’aide du code suivant :

EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");

L’identificateur (EmployeeCell) utilisé dans l’appel MakeItem doit correspondre au nom du contrôleur de vue inscrit auprès de l’affichage de collection. Cette étape sera décrite en détail ci-dessous.

Gestion de la sélection d’éléments

Pour gérer la sélection et la désélection d’éléments dans la collection, une NSCollectionViewDelegate option est requise. Dans la mesure où cet exemple utilise le type de disposition intégré NSCollectionViewFlowLayout , une NSCollectionViewDelegateFlowLayout version spécifique de ce délégué sera requise.

Ajoutez une nouvelle classe au projet, appelez-la CollectionViewDelegate et faites-la ressembler à ce qui suit :

using System;
using Foundation;
using AppKit;

namespace MacCollectionNew
{
    /// <summary>
    /// Collection view delegate handles user interaction with the elements of the
    /// collection view for the Flow-Based layout type.
    /// </summary>
    public class CollectionViewDelegate : NSCollectionViewDelegateFlowLayout
    {
        #region Computed Properties
        /// <summary>
        /// Gets or sets the parent view controller.
        /// </summary>
        /// <value>The parent view controller.</value>
        public ViewController ParentViewController { get; set; }
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="T:MacCollectionNew.CollectionViewDelegate"/> class.
        /// </summary>
        /// <param name="parentViewController">Parent view controller.</param>
        public CollectionViewDelegate(ViewController parentViewController)
        {
            // Initialize
            ParentViewController = parentViewController;
        }
        #endregion

        #region Override Methods
        /// <summary>
        /// Handles one or more items being selected.
        /// </summary>
        /// <param name="collectionView">The parent Collection view.</param>
        /// <param name="indexPaths">The Index paths of the items being selected.</param>
        public override void ItemsSelected(NSCollectionView collectionView, NSSet indexPaths)
        {
            // Dereference path
            var paths = indexPaths.ToArray<NSIndexPath>();
            var index = (int)paths[0].Item;

            // Save the selected item
            ParentViewController.PersonSelected = ParentViewController.Datasource.Data[index];

        }

        /// <summary>
        /// Handles one or more items being deselected.
        /// </summary>
        /// <param name="collectionView">The parent Collection view.</param>
        /// <param name="indexPaths">The Index paths of the items being deselected.</param>
        public override void ItemsDeselected(NSCollectionView collectionView, NSSet indexPaths)
        {
            // Dereference path
            var paths = indexPaths.ToArray<NSIndexPath>();
            var index = paths[0].Item;

            // Clear selection
            ParentViewController.PersonSelected = null;
        }
        #endregion
    }
}

Les ItemsSelected méthodes et ItemsDeselected les méthodes sont remplacées et utilisées pour définir ou effacer la PersonSelected propriété du contrôleur de vue qui gère l’affichage collection lorsque l’utilisateur sélectionne ou désélectionne un élément. Cela sera présenté en détail ci-dessous.

Création de l’affichage collection dans le Générateur d’interface

Avec toutes les pièces de prise en charge requises en place, le storyboard principal peut être modifié et un affichage collection ajouté à celui-ci.

Effectuez les actions suivantes :

  1. Double-cliquez sur le Main.Storyboard fichier dans le Explorateur de solutions pour l’ouvrir pour modification dans le Générateur d’interface de Xcode.

  2. Faites glisser un affichage de collection dans l’affichage principal et redimensionnez-le pour remplir l’affichage :

    Ajout d’un affichage collection à la disposition

  3. Une fois l’affichage de collection sélectionné, utilisez l’Éditeur de contraintes pour l’épingler à l’affichage lorsqu’il est redimensionné :

    Capture d’écran montrant Ajouter de nouvelles contraintes.

  4. Vérifiez que l’affichage collection est sélectionné dans l’aire de conception (et non dans la vue de défilement délimitée ou le mode Clip qui le contient), basculez vers l’Éditeur Assistant et créez un point de sortie pour l’affichage collection :

    Capture d’écran montrant l’Éditeur Assistant dans lequel vous pouvez créer un point de vente.

  5. Enregistrez les modifications et revenez à Visual Studio pour la synchronisation.

Rassembler tous les ensembles

Tous les éléments de prise en charge ont été mis en place avec une classe pour agir en tant que modèle de données (PersonModel), un NSCollectionViewDataSource a été ajouté pour fournir des données, un NSCollectionViewDelegateFlowLayout a été créé pour gérer la sélection d’éléments et un a NSCollectionView été ajouté au Storyboard principal et exposé en tant que sortie (EmployeeCollection).

La dernière étape consiste à modifier le contrôleur de vue qui contient l’affichage collection et à rassembler toutes les pièces pour remplir la collection et gérer la sélection d’éléments.

Modifiez le ViewController.cs fichier et faites-le ressembler à ce qui suit :

using System;
using AppKit;
using Foundation;
using CoreGraphics;

namespace MacCollectionNew
{
    /// <summary>
    /// The View controller controls the main view that houses the Collection View.
    /// </summary>
    public partial class ViewController : NSViewController
    {
        #region Private Variables
        private PersonModel _personSelected;
        private bool shouldEdit = true;
        #endregion

        #region Computed Properties
        /// <summary>
        /// Gets or sets the datasource that provides the data to display in the
        /// Collection View.
        /// </summary>
        /// <value>The datasource.</value>
        public CollectionViewDataSource Datasource { get; set; }

        /// <summary>
        /// Gets or sets the person currently selected in the collection view.
        /// </summary>
        /// <value>The person selected or <c>null</c> if no person is selected.</value>
        [Export("PersonSelected")]
        public PersonModel PersonSelected
        {
            get { return _personSelected; }
            set
            {
                WillChangeValue("PersonSelected");
                _personSelected = value;
                DidChangeValue("PersonSelected");
                RaiseSelectionChanged();
            }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="T:MacCollectionNew.ViewController"/> class.
        /// </summary>
        /// <param name="handle">Handle.</param>
        public ViewController(IntPtr handle) : base(handle)
        {
        }
        #endregion

        #region Override Methods
        /// <summary>
        /// Called after the view has finished loading from the Storyboard to allow it to
        /// be configured before displaying to the user.
        /// </summary>
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Initialize Collection View
            ConfigureCollectionView();
            PopulateWithData();
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Configures the collection view.
        /// </summary>
        private void ConfigureCollectionView()
        {
            EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");

            // Create a flow layout
            var flowLayout = new NSCollectionViewFlowLayout()
            {
                ItemSize = new CGSize(150, 150),
                SectionInset = new NSEdgeInsets(10, 10, 10, 20),
                MinimumInteritemSpacing = 10,
                MinimumLineSpacing = 10
            };
            EmployeeCollection.WantsLayer = true;

            // Setup collection view
            EmployeeCollection.CollectionViewLayout = flowLayout;
            EmployeeCollection.Delegate = new CollectionViewDelegate(this);

        }

        /// <summary>
        /// Populates the Datasource with data and attaches it to the collection view.
        /// </summary>
        private void PopulateWithData()
        {
            // Make datasource
            Datasource = new CollectionViewDataSource(EmployeeCollection);

            // Build list of employees
            Datasource.Data.Add(new PersonModel("Craig Dunn", "Documentation Manager", true));
            Datasource.Data.Add(new PersonModel("Amy Burns", "Technical Writer"));
            Datasource.Data.Add(new PersonModel("Joel Martinez", "Web & Infrastructure"));
            Datasource.Data.Add(new PersonModel("Kevin Mullins", "Technical Writer"));
            Datasource.Data.Add(new PersonModel("Mark McLemore", "Technical Writer"));
            Datasource.Data.Add(new PersonModel("Tom Opgenorth", "Technical Writer"));
            Datasource.Data.Add(new PersonModel("Larry O'Brien", "API Docs Manager", true));
            Datasource.Data.Add(new PersonModel("Mike Norman", "API Documentor"));

            // Populate collection view
            EmployeeCollection.ReloadData();
        }
        #endregion

        #region Events
        /// <summary>
        /// Selection changed delegate.
        /// </summary>
        public delegate void SelectionChangedDelegate();

        /// <summary>
        /// Occurs when selection changed.
        /// </summary>
        public event SelectionChangedDelegate SelectionChanged;

        /// <summary>
        /// Raises the selection changed event.
        /// </summary>
        internal void RaiseSelectionChanged() {
            // Inform caller
            if (this.SelectionChanged != null) SelectionChanged();
        }
        #endregion
    }
}

En examinant ce code en détail, une Datasource propriété est définie pour contenir une instance du CollectionViewDataSource mode Collection. Une PersonSelected propriété est définie pour contenir la représentation de PersonModel l’élément actuellement sélectionné dans l’affichage collection. Cette propriété déclenche également l’événement SelectionChanged lorsque la sélection change.

La ConfigureCollectionView classe est utilisée pour inscrire le contrôleur de vue qui agit comme prototype de cellule avec la vue collection à l’aide de la ligne suivante :

EmployeeCollection.RegisterClassForItem(typeof(EmployeeItemController), "EmployeeCell");

Notez que l’identificateur (EmployeeCell) utilisé pour inscrire le prototype correspond à celui appelé dans la GetItem méthode définie CollectionViewDataSource ci-dessus :

var item = collectionView.MakeItem("EmployeeCell", indexPath) as EmployeeItemController;
...

En outre, le type du contrôleur de vue doit correspondre au nom du .xib fichier qui définit le prototype exactement. Dans le cas de cet exemple, EmployeeItemController et EmployeeItemController.xib.

La disposition réelle des éléments de l’affichage collection est contrôlée par une classe Collection View Layout et peut être modifiée dynamiquement au moment de l’exécution en affectant une nouvelle instance à la CollectionViewLayout propriété. La modification de cette propriété met à jour l’apparence de la vue collection sans animer la modification.

Apple fournit deux types de disposition intégrés avec la vue collection qui gère les utilisations les plus courantes : NSCollectionViewFlowLayout et NSCollectionViewGridLayout. Si le développeur a besoin d’un format personnalisé, tel que la disposition des éléments dans un cercle, il peut créer une instance personnalisée et NSCollectionViewLayout remplacer les méthodes requises pour obtenir l’effet souhaité.

Cet exemple utilise la disposition de flux par défaut pour qu’elle crée une instance de la NSCollectionViewFlowLayout classe et la configure comme suit :

var flowLayout = new NSCollectionViewFlowLayout()
{
    ItemSize = new CGSize(150, 150),
    SectionInset = new NSEdgeInsets(10, 10, 10, 20),
    MinimumInteritemSpacing = 10,
    MinimumLineSpacing = 10
};

La ItemSize propriété définit la taille de chaque cellule individuelle de la collection. La SectionInset propriété définit les ensembles à partir du bord de la collection dans laquelle les cellules seront disposées. MinimumInteritemSpacing définit l’espacement minimal entre les éléments et MinimumLineSpacing définit l’espacement minimal entre les lignes de la collection.

La disposition est affectée à l’affichage collection et une instance de celle-ci CollectionViewDelegate est attachée pour gérer la sélection d’éléments :

// Setup collection view
EmployeeCollection.CollectionViewLayout = flowLayout;
EmployeeCollection.Delegate = new CollectionViewDelegate(this);

La PopulateWithData méthode crée une nouvelle instance du CollectionViewDataSource, la remplit avec des données, l’attache à la vue collection et appelle la ReloadData méthode pour afficher les éléments :

private void PopulateWithData()
{
    // Make datasource
    Datasource = new CollectionViewDataSource(EmployeeCollection);

    // Build list of employees
    Datasource.Data.Add(new PersonModel("Craig Dunn", "Documentation Manager", true));
    ...

    // Populate collection view
    EmployeeCollection.ReloadData();
}

La ViewDidLoad méthode est substituée et appelle les méthodes et PopulateWithData les ConfigureCollectionView méthodes pour afficher la vue de collection finale à l’utilisateur :

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

    // Initialize Collection View
    ConfigureCollectionView();
    PopulateWithData();
}

Résumé

Cet article a examiné en détail l’utilisation des vues de collection dans une application Xamarin.Mac. Tout d’abord, il a examiné l’exposition d’une classe C# à l’aide Objective-C du codage clé-valeur (KVC) et de l’observation de clé-valeur (KVO). Ensuite, il a montré comment utiliser une classe conforme KVO et Data Bind it to Collection Views in Xcode’s Interface Builder. Enfin, il a montré comment interagir avec les vues de collection dans le code C#.