Partager via


Liaison de données et codage clé-valeur dans Xamarin.Mac

Cet article traite de l’utilisation du codage clé-valeur et de l’observation clé-valeur pour permettre la liaison de données aux éléments d’interface utilisateur dans le Générateur d’interface de Xcode.

Vue d’ensemble

Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes techniques de codage clé-valeur et de liaison de données 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 lier des données avec des éléments d’interface utilisateur au lieu d’écrire du code.

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.

Exemple de l’application en cours d’exécution

Dans cet article, nous allons aborder les principes fondamentaux de l’utilisation du codage clé-valeur et de la liaison de données 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-C la section du document interne Xamarin.Mac , ainsi que les RegisterExport attributs utilisés pour connecter vos classes C# à des objets et des Objective-C éléments d’interface utilisateur.

Qu’est-ce que le codage clé-valeur ?

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 de codage clé-valeur dans votre application Xamarin.Mac, vous accédez à d’autres fonctionnalités macOS (anciennement OS X) telles que l’observation de valeur clé (KVO), la liaison de données, les données principales, les liaisons Cocoa et la scriptabilité.

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.

Par exemple, examinons la définition de classe suivante d’un objet conforme KVC :

using System;
using Foundation;

namespace MacDatabinding
{
    [Register("PersonModel")]
    public class PersonModel : NSObject
    {
        private string _name = "";

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

        public PersonModel ()
        {
        }
    }
}

Tout d’abord, l’attribut [Register("PersonModel")] inscrit la classe et l’expose à Objective-C. Ensuite, la classe doit hériter ( NSObject ou d’une sous-classe qui hérite de NSObject), cela ajoute plusieurs méthodes de base qui permettent à la classe d’être conforme KVC. Ensuite, l’attribut [Export("Name")] expose la Name propriété et définit la valeur clé qui sera utilisée ultérieurement pour accéder à la propriété via les techniques KVC et KVO.

Enfin, pour pouvoir être en mesure d’être des modifications observées par clé à la valeur de la propriété, l’accesseur doit encapsuler les modifications apportées à sa valeur et WillChangeValueDidChangeValue les appels de méthode (en spécifiant la même clé que l’attribut Export ). Par exemple :

set {
    WillChangeValue ("Name");
    _name = value;
    DidChangeValue ("Name");
}

Cette étape est très importante pour la liaison de données dans le Générateur d’interface de Xcode (comme nous le verrons plus loin dans cet article).

Pour plus d’informations, consultez le Guide de programmation de codage clé-valeur d’Apple.

Clés et chemins de clés

Une clé est une chaîne qui identifie une propriété spécifique d’un objet. En règle générale, une clé correspond au nom d’une méthode d’accesseur dans un objet conforme au codage clé-valeur. Les clés doivent utiliser l’encodage ASCII, généralement commencer par une lettre minuscule et ne pas contenir d’espace blanc. Ainsi, étant donné l’exemple ci-dessus, Name il s’agit d’une valeur clé de Name propriété de la PersonModel classe. La clé et le nom de la propriété qu’ils exposent n’ont pas besoin d’être identiques, mais dans la plupart des cas, ils sont.

Un chemin de clé est une chaîne de clés séparées par des points utilisées pour spécifier une hiérarchie de propriétés d’objet à parcourir. La propriété de la première clé de la séquence est relative au récepteur, et chaque clé suivante est évaluée par rapport à la valeur de la propriété précédente. De la même façon, vous utilisez la notation par points pour parcourir un objet et ses propriétés dans une classe C#.

Par exemple, si vous avez développé la classe et ajouté Child la PersonModel propriété :

using System;
using Foundation;

namespace MacDatabinding
{
    [Register("PersonModel")]
    public class PersonModel : NSObject
    {
        private string _name = "";
        private PersonModel _child = new PersonModel();

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

        [Export("Child")]
        public PersonModel Child {
            get { return _child; }
            set {
                WillChangeValue ("Child");
                _child = value;
                DidChangeValue ("Child");
            }
        }

        public PersonModel ()
        {
        }
    }
}

Le chemin d’accès à la clé du nom de l’enfant serait self.Child.Name ou simplement Child.Name (en fonction de la façon dont la valeur de clé était utilisée).

Obtention de valeurs à l’aide du codage clé-valeur

La ValueForKey méthode retourne la valeur de la clé spécifiée (en tant que NSString), par rapport à l’instance de la classe KVC qui reçoit la requête. Par exemple, s’il s’agit Person d’une instance de la PersonModel classe définie ci-dessus :

// Read value
var name = Person.ValueForKey (new NSString("Name"));

Cela renvoie la valeur de la Name propriété pour cette instance de PersonModel.

Définition de valeurs à l’aide du codage clé-valeur

De même, définissez SetValueForKey la valeur de la clé spécifiée (en tant que NSString), par rapport à l’instance de la classe KVC qui reçoit la requête. Par conséquent, à l’aide d’une instance de la PersonModel classe, comme indiqué ci-dessous :

// Write value
Person.SetValueForKey(new NSString("Jane Doe"), new NSString("Name"));

Modifie la valeur de la Name propriété en Jane Doe.

Observation des modifications de valeur

À l’aide de l’observation de valeur clé (KVO), vous pouvez attacher un observateur à une clé spécifique d’une classe conforme KVC et être averti à tout moment de la modification de la valeur de cette clé (à l’aide de techniques KVC ou d’accès direct à la propriété donnée dans le code C#). Par exemple :

// Watch for the name value changing
Person.AddObserver ("Name", NSKeyValueObservingOptions.New, (sender) => {
    // Inform caller of selection change
    Console.WriteLine("New Name: {0}", Person.Name)
});

À présent, chaque fois que la Name propriété de l’instance Person de la PersonModel classe est modifiée, la nouvelle valeur est écrite dans la console.

Pour plus d’informations, consultez le Guide de programmation d’observation des valeurs clés d’Apple.

Liaison de données

Les sections suivantes montrent comment utiliser un codage clé-valeur et une classe conforme d’observation de clé-valeur pour lier des données à des éléments d’interface utilisateur dans le Générateur d’interface de Xcode, au lieu de lire et d’écrire des valeurs à l’aide du code C#. De cette façon, vous séparez votre modèle de données des vues utilisées pour les afficher, ce qui rend l’application Xamarin.Mac plus flexible et plus facile à gérer. Vous réduisez également considérablement la quantité de code qui doit être écrite.

Définition de votre modèle de données

Avant de pouvoir lier des données à un élément d’interface utilisateur dans Interface Builder, vous devez disposer d’une classe conforme KVC/KVO définie dans votre 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 l’interface utilisateur et reçoit toutes les modifications apportées aux données que l’utilisateur effectue dans l’interface utilisateur lors de l’exécution de l’application.

Par exemple, si vous écriviez une application qui gérait un groupe d’employés, vous pouvez utiliser la classe suivante 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 ("group.png");
                } else {
                    return NSImage.ImageNamed ("user.png");
                }
            }
        }

        [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
    }
}

La plupart des fonctionnalités de cette classe ont été abordées dans la section De codage clé-valeur ci-dessus. Toutefois, examinons quelques éléments spécifiques et quelques ajouts qui ont été effectués pour permettre à cette classe d’agir en tant que modèle de données pour les contrôleurs de tableau et les contrôleurs d’arborescence (que nous utiliserons ultérieurement pour lier des arborescences, des vues hiérarchiques et des vues de collection).

Tout d’abord, étant donné qu’un employé peut être un responsable, nous avons utilisé un (en particulier un NSArrayNSMutableArray pour que les valeurs puissent être modifiées) pour permettre aux employés qu’ils ont gérés d’être attachés à eux :

private NSMutableArray _people = new NSMutableArray();
...

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

Deux points à noter ici :

  1. Nous avons utilisé un NSMutableArray tableau ou une collection C# standard, car il s’agit d’une exigence de liaison de données à des contrôles AppKit tels que les vues de table, les vues hiérarchiques et les collections.
  2. Nous avons exposé le tableau des employés en le castant à des NSArray fins de liaison de données et modifié son nom mis en forme C#, Peopleen un nom attendu par la liaison de données, personModelArray sous la forme {class_name}Array (notez que le premier caractère a été mis en minuscules).

Ensuite, nous devons ajouter des méthodes publiques spécialement nommées pour prendre en charge les contrôleurs de tableau et les contrôleurs d’arborescence :

[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");
}

Ils permettent aux contrôleurs de demander et de modifier les données qu’ils affichent. Comme l’exposé NSArray ci-dessus, ceux-ci ont une convention d’affectation de noms très spécifique (qui diffère des conventions d’affectation de noms C# classiques) :

  • addObject: - Ajoute un objet au tableau.
  • insertObject:in{class_name}ArrayAtIndex: - Où {class_name} est le nom de votre classe. Cette méthode insère un objet dans le tableau à un index donné.
  • removeObjectFrom{class_name}ArrayAtIndex: - Où {class_name} est le nom de votre classe. Cette méthode supprime l’objet du tableau à un index donné.
  • set{class_name}Array: - Où {class_name} est le nom de votre classe. Cette méthode vous permet de remplacer le transport existant par un nouveau.

À l’intérieur de ces méthodes, nous avons encapsulé les modifications apportées au tableau WillChangeValue et DidChangeValue aux messages pour la conformité KVO.

Enfin, étant donné que la Icon propriété s’appuie sur la valeur de la isManager propriété, les modifications apportées à la isManager propriété peuvent ne pas être reflétées dans les Icon éléments d’interface utilisateur liés aux données (pendant KVO) :

[Export("Icon")]
public NSImage Icon {
    get {
        if (isManager) {
            return NSImage.ImageNamed ("group.png");
        } else {
            return NSImage.ImageNamed ("user.png");
        }
    }
}

Pour corriger cela, nous utilisons le code suivant :

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

Notez qu’en plus de sa propre clé, l’accesseur isManager envoie également les messages et DidChangeValue les WillChangeValue messages de la Icon clé afin qu’il voit également la modification.

Nous allons utiliser le PersonModel modèle de données dans le reste de cet article.

Liaison de données simple

Avec notre modèle de données défini, examinons un exemple simple de liaison de données dans le Générateur d’interface de Xcode. Par exemple, nous allons ajouter un formulaire à notre application Xamarin.Mac qui peut être utilisée pour modifier le PersonModel formulaire que nous avons défini ci-dessus. Nous allons ajouter quelques champs de texte et une case à cocher pour afficher et modifier les propriétés de notre modèle.

Tout d’abord, nous allons ajouter un nouveau contrôleur de vue à notre fichier Main.storyboard dans Interface Builder et nommer sa classe SimpleViewController:

Ajout d’un nouveau contrôleur d’affichage avec une classe nommée SimpleViewController.

Ensuite, revenez à Visual Studio pour Mac, modifiez le fichier SimpleViewController.cs (qui a été ajouté automatiquement à notre projet) et exposez une instance du PersonModel formulaire auquel nous allons lier les données. Ajoutez le code suivant :

private PersonModel _person = new PersonModel();
...

[Export("Person")]
public PersonModel Person {
    get {return _person; }
    set {
        WillChangeValue ("Person");
        _person = value;
        DidChangeValue ("Person");
    }
}

Ensuite, lorsque la vue est chargée, nous allons créer une instance de notre PersonModel instance et la remplir avec ce code :

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

    // Set a default person
    var Craig = new PersonModel ("Craig Dunn", "Documentation Manager");
    Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
    Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
    Person = Craig;

}

Maintenant, nous devons créer notre formulaire, double-cliquez sur le fichier Main.storyboard pour l’ouvrir pour modification dans Interface Builder. Disposition du formulaire pour qu’il ressemble à ce qui suit :

Modification du storyboard dans Xcode

Pour lier le formulaire au PersonModel formulaire que nous avons exposé via la Person clé, procédez comme suit :

  1. Sélectionnez le champ texte nom de l’employé et basculez vers l’inspecteur liaisons.

  2. Cochez la case Lier à et sélectionnez Contrôleur d’affichage simple dans la liste déroulante. Entrez self.Person.Name ensuite le chemin d’accès à la clé :

    Saisie du nom du point de la personne à point automatique pour le chemin d’accès de la clé.

  3. Sélectionnez le champ Texte d’occupation et case activée la zone Lier à la zone, puis sélectionnez Contrôleur d’affichage simple dans la liste déroulante. Entrez self.Person.Occupation ensuite le chemin d’accès à la clé :

    Saisie d’un point de personne d’auto-point occupation pour le chemin d’accès de la clé.

  4. Sélectionnez l’employé comme case à cocher Gestionnaire et case activée la case Lier à la zone, puis sélectionnez Contrôleur d’affichage simple dans la liste déroulante. Entrez self.Person.isManager ensuite le chemin d’accès à la clé :

    Saisie d’un point de personne à point d’auto-point isManager pour le chemin d’accès de clé.

  5. Sélectionnez le champ Texte managé du nombre d’employés et case activée la zone Lier à, puis sélectionnez Contrôleur d’affichage simple dans la liste déroulante. Entrez self.Person.NumberOfEmployees ensuite le chemin d’accès à la clé :

    Saisie d’un point de personne d’auto-point NumberOfEmployees pour le chemin d’accès de la clé.

  6. Si l’employé n’est pas un responsable, nous voulons masquer le nombre d’employés gérés étiquette et champ texte.

  7. Sélectionnez le nombre d’employés gérés label, développez la désactivation masquée et case activée la zone Lier à, puis sélectionnez Contrôleur d’affichage simple dans la liste déroulante. Entrez self.Person.isManager ensuite le chemin d’accès à la clé :

    La saisie d’un point de personne libre estManager pour le chemin d’accès de clé pour les non-gestionnaires.

  8. Sélectionnez NSNegateBoolean dans la liste déroulante Transformateur de valeur :

    Sélection de la transformation de clé NSNegateBoolean

  9. Cela indique à la liaison de données que l’étiquette sera masquée si la valeur de la isManager propriété est false.

  10. Répétez les étapes 7 et 8 pour le champ Texte managé du nombre d’employés.

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

Si vous exécutez l’application, les valeurs de la Person propriété remplissent automatiquement notre formulaire :

Affichage d’un formulaire renseigné automatiquement

Toutes les modifications apportées par les utilisateurs au formulaire sont réécrites dans la Person propriété dans le contrôleur de vue. Par exemple, la désélection de l’employé est un responsable met à jour l’instance Person de notre PersonModel et le champ d’étiquette managée du nombre d’employés et de champ de texte sont masqués automatiquement (via la liaison de données) :

Masquage du nombre d’employés pour les non-gestionnaires

Liaison de données d’affichage de table

Maintenant que nous disposons des principes de base de la liaison de données, examinons une tâche de liaison de données plus complexe à l’aide d’un contrôleur de tableau et d’une liaison de données vers une vue table. Pour plus d’informations sur l’utilisation des vues de table, consultez notre documentation sur les vues de table.

Tout d’abord, nous allons ajouter un nouveau contrôleur de vue à notre fichier Main.storyboard dans Interface Builder et nommer sa classe TableViewController:

Ajout d’un nouveau contrôleur d’affichage avec une classe nommée TableViewController.

Ensuite, nous allons modifier le fichier TableViewController.cs (qui a été automatiquement ajouté à notre projet) et exposer un tableau (NSArray) de PersonModel classes auxquelles nous allons lier nos données. Ajoutez le code suivant :

private NSMutableArray _people = new NSMutableArray();
...

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

[Export("addObject:")]
public void AddPerson(PersonModel person) {
    WillChangeValue ("personModelArray");
    _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");
}

Comme nous l’avons fait sur la PersonModel classe ci-dessus dans la section Définition de votre modèle de données, nous avons exposé quatre méthodes publiques spécialement nommées afin que le contrôleur de tableau et lisent et écrivent des données à partir de notre collection de PersonModels.

Ensuite, lorsque la vue est chargée, nous devons remplir notre tableau avec ce code :

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

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

}

Maintenant, nous devons créer notre affichage table, double-cliquez sur le fichier Main.storyboard pour l’ouvrir pour modification dans le Générateur d’interface. Disposition du tableau pour qu’elle ressemble à ce qui suit :

Disposition d’une nouvelle vue de tableau

Nous devons ajouter un contrôleur de tableau pour fournir des données liées à notre table, procédez comme suit :

  1. Faites glisser un contrôleur de tableau à partir de l’inspecteur de bibliothèque vers l’éditeur d’interface :

    Sélection d’un contrôleur de tableau dans la bibliothèque

  2. Sélectionnez Le contrôleur de tableau dans la hiérarchie d’interface et basculez vers l’inspecteur d’attribut :

    Sélection de l’inspecteur d’attributs

  3. Entrez PersonModel le nom de la classe, cliquez sur le bouton Plus et ajoutez trois clés. Nommez-les Name, Occupation et isManager:

    Ajout des chemins de clé requis au contrôleur d’objet.

  4. Cela indique au contrôleur de tableau ce qu’il gère un tableau et les propriétés qu’il doit exposer (via les clés).

  5. Basculez vers l’inspecteur liaisons et, sous Le tableau de contenu, sélectionnez Lier au contrôleur de vue table et liaison. Entrez un chemin de clé de modèle de self.personModelArray:

    Entrée d’un chemin de clé

  6. Cela lie le contrôleur de tableau au tableau de celui que PersonModels nous avons exposé sur notre contrôleur de vue.

Nous devons maintenant lier notre vue table au contrôleur de tableau, procédez comme suit :

  1. Sélectionnez l’affichage table et l’inspecteur de liaison :

    Sélection de la vue table et de l’inspecteur de liaison.

  2. Sous la liste déroulante Contenu de la table, sélectionnez Lier à et Contrôleur de tableau. Entrez arrangedObjects le champ Clé du contrôleur :

    Définition de la clé de contrôleur

  3. Sélectionnez la cellule Table View sous la colonne Employee . Dans l’inspecteur liaisons, sous la valeur de la valeur, sélectionnez Lier à et Table Cell View. Entrez objectValue.Name le chemin de la clé de modèle :

    Définition du chemin de clé de modèle pour la colonne Employee.

  4. objectValue est le courant PersonModel dans le tableau géré par le contrôleur de tableau.

  5. Sélectionnez la cellule Table View sous la colonne Occupation . Dans l’inspecteur liaisons, sous la valeur de la valeur, sélectionnez Lier à et Table Cell View. Entrez objectValue.Occupation le chemin de la clé de modèle :

    Définition du chemin de clé de modèle pour la colonne Occupation.

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

Si nous exécutons l’application, la table est remplie avec notre tableau de PersonModels:

Exécution de l’application, qui remplit le tableau de PersonModels.

Liaison de données d’affichage hiérarchique

la liaison de données par rapport à un mode Plan est très similaire à la liaison à un affichage table. La principale différence est que nous allons utiliser un contrôleur d’arborescence au lieu d’un contrôleur de tableau pour fournir les données liées à la vue hiérarchique. Pour plus d’informations sur l’utilisation des vues hiérarchiques, consultez notre documentation sur les vues hiérarchiques .

Tout d’abord, nous allons ajouter un nouveau contrôleur de vue à notre fichier Main.storyboard dans Interface Builder et nommer sa classe OutlineViewController:

Ajout d’un nouveau contrôleur d’affichage avec une classe nommée OutlineViewController.

Ensuite, nous allons modifier le fichier OutlineViewController.cs (qui a été automatiquement ajouté à notre projet) et exposer un tableau (NSArray) de PersonModel classes auxquelles nous allons lier nos données. Ajoutez le code suivant :

private NSMutableArray _people = new NSMutableArray();
...

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

[Export("addObject:")]
public void AddPerson(PersonModel person) {
    WillChangeValue ("personModelArray");
    _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");
}

Comme nous l’avons fait sur la PersonModel classe ci-dessus dans la section Définition de votre modèle de données, nous avons exposé quatre méthodes publiques spécialement nommées afin que le contrôleur d’arborescence et lisent et écrivent des données à partir de notre collection de PersonModels.

Ensuite, lorsque la vue est chargée, nous devons remplir notre tableau avec ce code :

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

    // Build list of employees
    var Craig = new PersonModel ("Craig Dunn", "Documentation Manager");
    Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
    Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
    Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
    AddPerson (Craig);

    var Larry = new PersonModel ("Larry O'Brien", "API Documentation Manager");
    Larry.AddPerson (new PersonModel ("Mike Norman", "API Documenter"));
    AddPerson (Larry);

}

Maintenant, nous devons créer notre mode Plan, double-cliquez sur le fichier Main.storyboard pour l’ouvrir pour modification dans Interface Builder. Disposition du tableau pour qu’elle ressemble à ce qui suit :

Création de l’affichage plan

Nous devons ajouter un contrôleur d’arborescence pour fournir des données liées à notre plan, procédez comme suit :

  1. Faites glisser un contrôleur d’arborescence de l’inspecteurde bibliothèque vers l’éditeur d’interface :

    Sélection d’un contrôleur d’arborescence dans la bibliothèque

  2. Sélectionnez Le contrôleur d’arborescence dans la hiérarchie d’interface et basculez vers l’inspecteur d’attribut :

    Sélection de l’inspecteur d’attribut

  3. Entrez PersonModel le nom de la classe, cliquez sur le bouton Plus et ajoutez trois clés. Nommez-les Name, Occupation et isManager:

    Ajout des chemins de clé requis pour PersonModel.

  4. Cela indique au contrôleur d’arborescence ce qu’il gère un tableau et les propriétés qu’il doit exposer (via les clés).

  5. Sous la section Du contrôleur d’arborescence, entrez pour enfants, entrez NumberOfEmployeespersonModelArray sous le nombre et entrez isEmployee sous Feuille :

    Définition des chemins de clé du contrôleur d’arborescence

  6. Cela indique au contrôleur d’arborescence où trouver les nœuds enfants, le nombre de nœuds enfants présents et si le nœud actuel possède des nœuds enfants.

  7. Basculez vers l’inspecteurde liaisons et, sous Tableau de contenu, sélectionnez Lier au propriétaire du fichier et à celui du fichier. Entrez un chemin de clé de modèle de self.personModelArray:

    Modification du chemin d’accès à la clé

  8. Cela lie le contrôleur d’arborescence au tableau de PersonModels celui que nous avons exposé sur notre contrôleur de vue.

Nous devons maintenant lier notre mode Plan au contrôleur d’arborescence, procédez comme suit :

  1. Sélectionnez le mode Plan et, dans l’inspecteur de liaison, sélectionnez :

    Sélection de l’affichage hiérarchique et de l’inspecteur de liaison.

  2. Sous la liste déroulante Du contenu de l’affichage hiérarchique, sélectionnez Lier à et Tree Controller. Entrez arrangedObjects le champ Clé du contrôleur :

    Définition de la clé de contrôleur

  3. Sélectionnez la cellule Table View sous la colonne Employee . Dans l’inspecteur liaisons, sous la valeur de la valeur, sélectionnez Lier à et Table Cell View. Entrez objectValue.Name le chemin de la clé de modèle :

    Entrée de la valeur de chemin d’accès de clé du modèle objectValue dot Name.

  4. objectValue est le courant PersonModel dans le tableau géré par le contrôleur d’arborescence.

  5. Sélectionnez la cellule Table View sous la colonne Occupation . Dans l’inspecteur liaisons, sous la valeur de la valeur, sélectionnez Lier à et Table Cell View. Entrez objectValue.Occupation le chemin de la clé de modèle :

    Entrée de la valeur de chemin d’accès de clé du modèle objectValue dot Occupation.

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

Si nous exécutons l’application, le plan est rempli avec notre tableau de PersonModels:

Exécution de l’application, qui remplit notre tableau de PersonModels.

Liaison de données de vue de collecte

La liaison de données avec une vue collection est très similaire à la liaison avec un affichage table, car un contrôleur de tableau est utilisé 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.

Important

En raison d’un problème dans Xcode 7 et macOS 10.11 (et ultérieur), les vues de collection ne peuvent pas être utilisées à l’intérieur d’un fichier Storyboard (.storyboard). Par conséquent, vous devez continuer à utiliser des fichiers .xib pour définir vos vues de collection pour vos applications Xamarin.Mac. Pour plus d’informations, consultez notre documentation Vues de collection.

Débogage des incidents natifs

Une erreur dans vos liaisons de données peut entraîner un plantage natif dans du code non managé et provoquer l’échec complet de votre application Xamarin.Mac avec une SIGABRT erreur :

Exemple de boîte de dialogue d’incident natif

Il existe généralement quatre causes principales pour les blocages natifs lors de la liaison de données :

  1. Votre modèle de données n’hérite pas ou d’une NSObject sous-classe de NSObject.
  2. Vous n’avez pas exposé votre propriété à Objective-C l’utilisation de l’attribut [Export("key-name")] .
  3. Vous n’avez pas inclus les modifications apportées à la valeur WillChangeValue de l’accesseur et DidChangeValue les appels de méthode (en spécifiant la même clé que l’attribut Export ).
  4. Vous avez une clé incorrecte ou mal typée dans l’inspecteur de liaison dans le Générateur d’interface.

Décodage d’un incident

Nous allons provoquer un blocage natif dans notre liaison de données afin de pouvoir montrer comment le localiser et le corriger. Dans le Générateur d’interface, nous allons modifier notre liaison de première étiquette dans l’exemple De vue Collection de Name :Title

Modification de la clé de liaison

Nous allons enregistrer la modification, revenir à Visual Studio pour Mac pour synchroniser avec Xcode et exécuter notre application. Lorsque l’affichage collection s’affiche, l’application se bloque momentanément avec une SIGABRT erreur (comme indiqué dans la sortie de l’application dans Visual Studio pour Mac), car elle PersonModel n’expose pas de propriété avec la clé Title:

Exemple d’erreur de liaison

Si nous défilons vers le haut de l’erreur dans la sortie de l’application, nous pouvons voir la clé pour résoudre le problème :

Recherche du problème dans le journal des erreurs

Cette ligne nous indique que la clé Title n’existe pas sur l’objet auquel nous nous liez. Si nous revenons à la liaison Name dans Interface Builder, enregistrez, synchronisez, régénérez et exécutez, l’application s’exécute comme prévu sans problème.

Résumé

Cet article a examiné en détail l’utilisation de la liaison de données et du codage clé-valeur 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 à des éléments d’interface utilisateur dans le Générateur d’interface de Xcode. Enfin, il a montré une liaison de données complexe à l’aide de contrôleurs de tableau et de contrôleurs d’arborescence.