Datenbindung und Schlüsselwertcodierung in Xamarin.Mac
In diesem Artikel wird die Verwendung von Schlüsselwertcodierung und Schlüsselwertbeachtung behandelt, um die Datenbindung an UI-Elemente im Xcode-Schnittstellen-Generator zu ermöglichen.
Überblick
Wenn Sie mit C# und .NET in einer Xamarin.Mac-Anwendung arbeiten, haben Sie Zugriff auf die gleichen Schlüsselwertcodierungs- und Datenbindungstechniken, die ein Entwickler in Objective-C und Xcode ausführt. Da Xamarin.Mac direkt mit Xcode integriert wird, können Sie den Xcode-Schnittstellen-Generator zum Datenbindung mit UI-Elementen verwenden, anstatt Code zu schreiben.
Mithilfe von Schlüsselwertcodierungs- und Datenbindungstechniken in Ihrer Xamarin.Mac-Anwendung können Sie die Menge des Codes, den Sie schreiben und verwalten müssen, erheblich verringern, um mit UI-Elementen zu füllen und zu arbeiten. Sie haben auch den Vorteil, ihre Backing-Daten (Data Model) von Ihrer Front-End-Benutzeroberfläche (Model-View-Controller) weiter zu entkoppeln, wodurch das Verwalten, flexibleres Anwendungsdesign erleichtert wird.
In diesem Artikel werden die Grundlagen der Arbeit mit Schlüsselwertcodierung und Datenbindung in einer Xamarin.Mac-Anwendung behandelt. Es wird dringend vorgeschlagen, dass Sie zuerst den Artikel "Hello" und "Mac" durchlaufen, insbesondere die Einführung in Xcode- und Interface-Generator- undAktionsabschnitte , da sie wichtige Konzepte und Techniken behandelt, die wir in diesem Artikel verwenden werden.
Möglicherweise möchten Sie sich die C#-Klassen /Methoden zum Abschnitt "Xamarin.Mac Internals" ansehen, und sie erläutert die und attribute, die verwendet werden, um Objective-CIhre C#-Klassen an Objective-C Objekte und UI-Elemente zu verkabeln.Register
Export
Was ist die Schlüsselwertcodierung
Key-Value-Codierung (KVC) ist ein Mechanismus für den Zugriff auf die Eigenschaften eines Objekts indirekt, indem Schlüssel (speziell formatierte Zeichenfolgen) verwendet werden, um Eigenschaften zu identifizieren, anstatt sie über Instanzvariablen oder Accessormethoden (get/set
) zu identifizieren. Durch Implementieren von kompatiblen Schlüsselwert-Zugriffsoren in Ihrer Xamarin.Mac-Anwendung erhalten Sie Zugriff auf andere macOS-Features (früher als OS X bezeichnet), z. B. Key-Value-Observing (KVO), Datenbindung, Core Data, Kakaobindungen und Skriptbarkeit.
Mithilfe von Schlüsselwertcodierungs- und Datenbindungstechniken in Ihrer Xamarin.Mac-Anwendung können Sie die Menge des Codes, den Sie schreiben und verwalten müssen, erheblich verringern, um mit UI-Elementen zu füllen und zu arbeiten. Sie haben auch den Vorteil, ihre Backing-Daten (Data Model) von Ihrer Front-End-Benutzeroberfläche (Model-View-Controller) weiter zu entkoppeln, wodurch das Verwalten, flexibleres Anwendungsdesign erleichtert wird.
Sehen wir uns beispielsweise die folgende Klassendefinition eines KVC-kompatiblen Objekts an:
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 ()
{
}
}
}
Zunächst registriert das Attribut die [Register("PersonModel")]
Klasse und macht es verfügbar Objective-C. Anschließend muss die Klasse von (oder einer Unterklasse, die von NSObject
erbt) erben NSObject
, mehrere Basismethoden hinzugefügt werden, die es der Klasse ermöglichen, KVC-konform zu sein. Als Nächstes stellt das [Export("Name")]
Attribut die Name
Eigenschaft bereit und definiert den Schlüsselwert, der später verwendet wird, um auf die Eigenschaft über KVC- und KVO-Techniken zuzugreifen.
Schließlich muss der Accessor Änderungen an dem Wert der Eigenschaft Key-Value beobachtet werden können. Der Accessor muss Änderungen an seinem Wert in WillChangeValue
und DidChangeValue
den Methodenaufrufen umschließen (angeben denselben Schlüssel wie das Export
Attribut). Beispiel:
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
Dieser Schritt ist sehr wichtig für die Datenbindung im Xcode-Schnittstellen-Generator (wie wir später in diesem Artikel sehen).
Weitere Informationen finden Sie im Leitfaden zur Key-Value-Programmierung von Apple.
Schlüssel und Schlüsselpfade
Ein Schlüssel ist eine Zeichenfolge, die eine bestimmte Eigenschaft eines Objekts identifiziert. In der Regel entspricht ein Schlüssel dem Namen einer Accessor-Methode in einem kompatiblen Schlüsselwertobjekt. Schlüssel müssen ASCII-Codierung verwenden, beginnen normalerweise mit einem Kleinbuchstaben und enthalten möglicherweise keine Leerzeichen. Im folgenden Beispiel Name
wäre also ein Schlüsselwert der Name
Eigenschaft der PersonModel
Klasse. Der Schlüssel und der Name der eigenschaft, die sie verfügbar machen, müssen jedoch in den meisten Fällen nicht identisch sein.
Ein Schlüsselpfad ist eine Zeichenfolge von punkttrennten Schlüsseln, die verwendet werden, um eine Hierarchie von Objekteigenschaften anzugeben, die durchlaufen werden. Die Eigenschaft des ersten Schlüssels in der Sequenz ist relativ zum Empfänger, und jeder nachfolgende Schlüssel wird relativ zum Wert der vorherigen Eigenschaft ausgewertet. Auf dieselbe Weise verwenden Sie Punktnotation, um ein Objekt und dessen Eigenschaften in einer C#-Klasse zu durchlaufen.
Wenn Sie beispielsweise die PersonModel
Klasse erweitert und eigenschaft hinzugefügt Child
haben:
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 ()
{
}
}
}
Der Schlüsselpfad zum Namen des untergeordneten Elements wäre self.Child.Name
oder einfach Child.Name
(basierend auf der Verwendung des Schlüsselwerts).
Abrufen von Werten mithilfe der Schlüsselwertcodierung
Die ValueForKey
Methode gibt den Wert für den angegebenen Schlüssel (as a NSString
) relativ zur Instanz der KVC-Klasse zurück, die die Anforderung empfängt. Wenn Person
es sich beispielsweise um eine Instanz der oben definierten PersonModel
Klasse handelt:
// Read value
var name = Person.ValueForKey (new NSString("Name"));
Dadurch wird der Wert der Name
Eigenschaft für diese Instanz zurückgegeben PersonModel
.
Festlegen von Werten mithilfe der Schlüsselwertcodierung
Ebenso legt der SetValueForKey
Wert für den angegebenen Schlüssel (as a NSString
) relativ zur Instanz der KVC-Klasse, die die Anforderung empfängt, fest. So erneut, verwenden Sie eine Instanz der PersonModel
Klasse, wie unten gezeigt:
// Write value
Person.SetValueForKey(new NSString("Jane Doe"), new NSString("Name"));
Würde den Wert der Name
Eigenschaft auf Jane Doe
ändern.
Beobachten von Wertänderungen
Mithilfe der Key-Value-Beobachtung (KVO) können Sie einen Beobachter an einen bestimmten Schlüssel einer KVC-kompatiblen Klasse anfügen und jederzeit benachrichtigt werden, wenn der Wert für diesen Schlüssel geändert wird (entweder mithilfe von KVC-Techniken oder direkt auf die angegebene Eigenschaft im C#-Code zugreifen). Beispiel:
// Watch for the name value changing
Person.AddObserver ("Name", NSKeyValueObservingOptions.New, (sender) => {
// Inform caller of selection change
Console.WriteLine("New Name: {0}", Person.Name)
});
Wenn die Eigenschaft der Person
Instanz der PersonModel
Klasse geändert wird, wird der Name
neue Wert nun in die Konsole geschrieben.
Weitere Informationen finden Sie in der Einführung in Key-Value Programmierhandbuch von Apple.
Datenbindung
In den folgenden Abschnitten wird gezeigt, wie Sie mithilfe eines Schlüsselwertcodierungs- und Schlüsselwert-Codierungs- und Schlüsselwerts konforme Klasse Daten an UI-Elemente in Xcode-Schnittstellen-Generator binden können, anstatt Werte mithilfe des C#-Codes zu lesen und zu schreiben. Auf diese Weise trennen Sie Ihr Datenmodell von den Ansichten, die verwendet werden, um sie anzuzeigen, wodurch die Xamarin.Mac-Anwendung flexibler und einfacher zu verwalten ist. Sie verringern auch die Menge des Codes, der geschrieben werden muss.
Definieren des Datenmodells
Bevor Sie ein Ui-Element im Schnittstellen-Generator binden können, müssen Sie über eine KVC/KVO-kompatible Klasse verfügen, die in Ihrer Xamarin.Mac-Anwendung als Datenmodell für die Bindung definiert ist. Das Datenmodell stellt alle Daten bereit, die in der Benutzeroberfläche angezeigt werden und alle Änderungen an den Daten empfängt, die der Benutzer in der Benutzeroberfläche während der Ausführung der Anwendung erstellt.
Wenn Sie beispielsweise eine Anwendung schreiben, die eine Gruppe von Mitarbeitern verwaltet hat, können Sie die folgende Klasse verwenden, um das Datenmodell zu definieren:
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
}
}
Die meisten Features dieser Klasse wurden im obigen Abschnitt " Schlüsselwertcodierung " behandelt. Sehen wir uns jedoch einige bestimmte Elemente und einige Ergänzungen an, die dazu gemacht wurden, diese Klasse als Datenmodell für Arraycontroller und Strukturcontroller zu handeln (was wir später verwenden werden, um Strukturansichten, Gliederungsansichten und Auflistungsansichten zu binden).
Erstens, da ein Mitarbeiter ein Manager sein kann, haben wir eine NSArray
(insbesondere so NSMutableArray
dass die Werte geändert werden können) verwendet, um den Mitarbeitern zu ermöglichen, die sie an sie angefügt haben:
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
Zwei Dinge, die hier zu beachten sind:
- Wir haben anstelle
NSMutableArray
eines standardmäßigen C#-Arrays oder einer Auflistung verwendet, da dies eine Anforderung für die Datenbindung an AppKit-Steuerelemente wie Tabellenansichten, Gliederungsansichten und Sammlungen ist. - Wir haben das Array von Mitarbeitern verfügbar gemacht, indem sie sie zu datenbindungszwecken verwerfen
NSArray
und den C#-formatierten Namen geändert haben, in einem, der die Datenbindung erwartet,People
personModelArray
in form {class_name}Array (beachten Sie, dass das erste Zeichen Kleinschreibung vorgenommen wurde).
Als Nächstes müssen wir einige spezielle öffentliche Methoden hinzufügen, um Arraycontroller und Strukturcontroller zu unterstützen:
[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");
}
Damit können die Controller die angezeigten Daten anfordern und ändern. Wie oben verfügbar NSArray
gemacht, verfügen diese über eine sehr spezifische Benennungskonvention (die sich von den typischen C#-Benennungskonventionen unterscheidet):
addObject:
- Fügt dem Array ein Objekt hinzu.insertObject:in{class_name}ArrayAtIndex:
- Wo{class_name}
ist der Name Ihrer Klasse. Diese Methode fügt ein Objekt in das Array bei einem bestimmten Index ein.removeObjectFrom{class_name}ArrayAtIndex:
- Wo{class_name}
ist der Name Ihrer Klasse. Diese Methode entfernt das Objekt im Array bei einem bestimmten Index.set{class_name}Array:
- Wo{class_name}
ist der Name Ihrer Klasse. Mit dieser Methode können Sie den vorhandenen Transport durch eine neue ersetzen.
Innerhalb dieser Methoden haben wir Änderungen an dem Array in WillChangeValue
und DidChangeValue
Nachrichten für die KVO-Compliance umgebrochen.
Schließlich, da die Icon
Eigenschaft auf den Wert der Eigenschaft basiert, werden Änderungen an der isManager
Eigenschaft möglicherweise nicht in den isManager
Icon
Für Data Bound UI-Elementen (während des KVO) angezeigt:
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
Um das zu korrigieren, verwenden wir den folgenden Code:
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
Beachten Sie, dass der isManager
Accessor zusätzlich zu seinem eigenen Schlüssel auch die WillChangeValue
Und DidChangeValue
Nachrichten für den Icon
Schlüssel sendet, sodass die Änderung ebenfalls angezeigt wird.
Wir verwenden das PersonModel
Datenmodell im gesamten Rest dieses Artikels.
Einfache Datenbindung
Mit unserem definierten Datenmodell sehen wir uns ein einfaches Beispiel für die Datenbindung im Xcode-Schnittstellen-Generator an. Lassen Sie uns beispielsweise ein Formular zu unserer Xamarin.Mac-Anwendung hinzufügen, die zum Bearbeiten des PersonModel
oben definierten Formulars verwendet werden kann. Wir fügen ein paar Textfelder und ein Kontrollkästchen hinzu, um Eigenschaften unseres Modells anzuzeigen und zu bearbeiten.
Zunächst fügen wir einen neuen Ansichtscontroller zu unserer Main.storyboard-Datei im Schnittstellen-Generator hinzu und benennen dessen Klasse SimpleViewController
:
Kehren Sie als Nächstes zur Visual Studio für Mac zurück, bearbeiten Sie die Datei SimpleViewController.cs (die automatisch zu unserem Projekt hinzugefügt wurde), und stellen Sie eine Instanz der PersonModel
Datenbindung unseres Formulars bereit. Fügen Sie den folgenden Code hinzu:
private PersonModel _person = new PersonModel();
...
[Export("Person")]
public PersonModel Person {
get {return _person; }
set {
WillChangeValue ("Person");
_person = value;
DidChangeValue ("Person");
}
}
Wenn die Ansicht geladen wird, erstellen wir eine Instanz unserer PersonModel
Und füllen sie mit diesem Code auf:
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;
}
Jetzt müssen wir unser Formular erstellen, doppelklicken Sie auf die Datei "Main.storyboard ", um sie für die Bearbeitung im Schnittstellen-Generator zu öffnen. Layout des Formulars so wie folgt:
Gehen Sie wie folgt vor, um das Formular an das PersonModel
Formular zu binden, das wir über den Person
Schlüssel verfügbar gemacht haben:
Wählen Sie das Textfeld " Mitarbeitername " aus, und wechseln Sie zum Inspektor für Bindungen.
Aktivieren Sie das Kontrollkästchen "An binden" , und wählen Sie " Einfacher Ansichtscontroller " aus der Dropdownliste aus. Geben Sie als Nächstes
self.Person.Name
den Schlüsselpfad ein:Aktivieren Sie das Feld "Besetzung " und aktivieren Sie das Kontrollkästchen " An binden", und wählen Sie "Einfacher Ansichtscontroller " aus der Dropdownliste aus. Geben Sie als Nächstes
self.Person.Occupation
den Schlüsselpfad ein:Aktivieren Sie das Kontrollkästchen "Mitarbeiter" und aktivieren Sie das Kontrollkästchen "An binden " , und wählen Sie "Einfacher Ansichtscontroller " aus der Dropdownliste aus. Geben Sie als Nächstes
self.Person.isManager
den Schlüsselpfad ein:Wählen Sie das Feld "Mitarbeiter verwalteter Text" aus, und aktivieren Sie das Kontrollkästchen " An binden" , und wählen Sie " Einfacher Ansichtscontroller " aus der Dropdownliste aus. Geben Sie als Nächstes
self.Person.NumberOfEmployees
den Schlüsselpfad ein:Wenn der Mitarbeiter kein Manager ist, möchten wir die Anzahl der verwalteten Mitarbeiter und Das Textfeld ausblenden.
Wählen Sie die Anzahl verwalteter Mitarbeiterbezeichnung aus, erweitern Sie die ausgeblendete Sperre, und aktivieren Sie das Kontrollkästchen "Binden" , und wählen Sie "Einfacher Ansichtscontroller " aus der Dropdownliste aus. Nächste Eingabetaste
self.Person.isManager
für den Schlüsselpfad:Wählen Sie
NSNegateBoolean
aus der Dropdownliste "Value Transformer " aus:Dadurch wird die Datenbindung mitgeteilt, dass die Bezeichnung ausgeblendet wird, wenn der Wert der
isManager
Eigenschaft istfalse
.Wiederholen Sie die Schritte 7 und 8 für das Feld "Anzahl der Verwalteten Mitarbeiter ".
Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.
Wenn Sie die Anwendung ausführen, füllen die Werte aus der Person
Eigenschaft automatisch unser Formular auf:
Alle Änderungen, die die Benutzer am Formular vornehmen, werden in die Person
Eigenschaft im Ansichtscontroller zurückgeschrieben. Beispielsweise wird die Auswahl des Mitarbeiters durch einen Vorgesetzten aktualisiert, Person
PersonModel
und die Anzahl der verwalteten Bezeichnungen und das Textfeld "Mitarbeiter" werden automatisch ausgeblendet (über die Datenbindung):
Datenbindung in Tabellenansicht
Nachdem wir nun über die Grundlagen der Datenbindung verfügen, sehen wir uns eine komplexere Datenbindungsaufgabe mithilfe eines Arraycontrollers und einer Datenbindung an eine Tabellenansicht an. Weitere Informationen zum Arbeiten mit Tabellenansichten finden Sie in der Dokumentation zu Tabellenansichten .
Zunächst fügen wir unserem Main.storyboard-Datei im Interface Builder einen neuen Ansichtscontroller hinzu und benennen die KlasseTableViewController
:
Als Nächstes bearbeiten wir die TableViewController.cs-Datei (die automatisch zu unserem Projekt hinzugefügt wurde) und stellen ein Array (NSArray
) von PersonModel
Klassen bereit, an die wir unser Formular binden. Fügen Sie den folgenden Code hinzu:
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");
}
Genau wie im PersonModel
Abschnitt " Definieren Ihres Datenmodells " haben wir vier speziell benannte öffentliche Methoden verfügbar gemacht, damit der Arraycontroller Daten aus unserer Sammlung PersonModels
lesen und schreiben kann.
Als Nächstes, wenn die Ansicht geladen wird, müssen wir unser Array mit diesem Code auffüllen:
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"));
}
Jetzt müssen wir unsere Tabellenansicht erstellen, doppelklicken Sie auf die Datei "Main.storyboard ", um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Layouten Sie die Tabelle so, dass sie wie folgt aussieht:
Wir müssen einen Arraycontroller hinzufügen, um gebundene Daten an unsere Tabelle bereitzustellen, gehen Sie folgendermaßen vor:
Ziehen Sie einen Arraycontroller aus dem Bibliotheksinspektor auf den Schnittstellen-Editor:
Wählen Sie arraycontroller in der Schnittstellenhierarchie aus, und wechseln Sie zum Attributinspektor:
Geben Sie
PersonModel
für den Klassennamen ein, klicken Sie auf die Schaltfläche "Plus ", und fügen Sie drei Schlüssel hinzu. Benennen Sie sieName
,Occupation
undisManager
:Dies teilt dem Arraycontroller mit, welche Eigenschaften (über Schlüssel) verfügbar gemacht werden sollen.
Wechseln Sie zum Inspektor für Bindungen, und wählen Sie unter "Inhaltsarray" die Option "Binden an" und "Tabellenansichtscontroller" aus. Geben Sie einen Modellschlüsselpfad ein:
self.personModelArray
Dadurch wird der Arraycontroller mit dem Array
PersonModels
verbunden, das wir auf unserem Ansichtscontroller verfügbar gemacht haben.
Jetzt müssen wir unsere Tabellenansicht an den Arraycontroller binden, gehen Sie wie folgt vor:
Wählen Sie die Tabellenansicht und den Bindungsinspektor aus:
Wählen Sie im Turndown " Tabelleninhalte " die Option "Binden an " und "Arraycontroller" aus. Geben Sie für das Feld "Controllerschlüssel" ein
arrangedObjects
:Wählen Sie die Zelle "Tabellenansicht " unter der Spalte "Mitarbeiter " aus. Wählen Sie im Bindungenprüfungsinspektor unter dem Wert-Turndown die Option "Binden an " und " Tabellenzellenansicht" aus. Geben Sie für den Modellschlüsselpfad ein
objectValue.Name
:objectValue
ist der AktuellePersonModel
im Array, das vom Arraycontroller verwaltet wird.Wählen Sie die Zelle "Tabellenansicht" unter der Spalte "Besetzung " aus. Wählen Sie im Bindungenprüfungsinspektor unter dem Wert-Turndown die Option "Binden an " und " Tabellenzellenansicht" aus. Geben Sie für den Modellschlüsselpfad ein
objectValue.Occupation
:Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.
Wenn wir die Anwendung ausführen, wird die Tabelle mit unserem Array von PersonModels
:
Datenbindung in der Gliederungsansicht
Die Datenbindung für eine Gliederungsansicht ähnelt der Bindung an eine Tabellenansicht. Der wichtigste Unterschied besteht darin, dass wir einen Strukturcontroller anstelle eines Arraycontrollers verwenden, um die gebundenen Daten an die Gliederungsansicht bereitzustellen. Weitere Informationen zum Arbeiten mit Gliederungsansichten finden Sie in der Dokumentation zu Gliederungsansichten .
Zunächst fügen wir unserem Main.storyboard-Datei im Interface Builder einen neuen Ansichtscontroller hinzu und benennen die KlasseOutlineViewController
:
Als Nächstes bearbeiten wir die Datei OutlineViewController.cs (die automatisch zu unserem Projekt hinzugefügt wurde) und machen ein Array (NSArray
) von PersonModel
Klassen verfügbar, an die wir unser Formular binden. Fügen Sie den folgenden Code hinzu:
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");
}
Genau wie im PersonModel
Abschnitt " Definieren Ihres Datenmodells " haben wir vier speziell benannte öffentliche Methoden verfügbar gemacht, damit der Strukturcontroller Daten aus unserer Sammlung PersonModels
lesen und schreiben kann.
Als Nächstes, wenn die Ansicht geladen wird, müssen wir unser Array mit diesem Code auffüllen:
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);
}
Jetzt müssen wir unsere Gliederungsansicht erstellen, doppelklicken Sie auf die Datei "Main.storyboard ", um sie zum Bearbeiten im Schnittstellen-Generator zu öffnen. Layouten Sie die Tabelle so, dass sie wie folgt aussieht:
Wir müssen einen Strukturverantwortlichen hinzufügen, um gebundene Daten an unsere Gliederung bereitzustellen, gehen Sie folgendermaßen vor:
Ziehen Sie einen Strukturcontroller aus dem Bibliotheksinspektor auf den Schnittstellen-Editor:
Wählen Sie den Strukturcontroller in der Schnittstellenhierarchie aus, und wechseln Sie zum Attributinspektor:
Geben Sie
PersonModel
für den Klassennamen ein, klicken Sie auf die Schaltfläche "Plus ", und fügen Sie drei Schlüssel hinzu. Benennen Sie sieName
,Occupation
undisManager
:Dies teilt dem Strukturcontroller mit, was er ein Array verwaltet, und welche Eigenschaften (über Schlüssel) verfügbar gemacht werden sollen.
Geben Sie
personModelArray
im Abschnitt "Strukturcontroller" unter "Untergeordnete Elemente" unter "Anzahl" ein, und gebenNumberOfEmployees
Sie unter "Blatt" ein:isEmployee
Dadurch wird der Strukturcontroller informiert, wo untergeordnete Knoten gefunden werden sollen, wie viele untergeordnete Knoten vorhanden sind und ob der aktuelle Knoten untergeordnete Knoten besitzt.
Wechseln Sie zum Inspektor für Bindungen, und wählen Sie unter "Inhaltsarray" die Option "Bindung an" und "Besitzer der Datei" aus. Geben Sie einen Modellschlüsselpfad ein:
self.personModelArray
Dadurch wird der Strukturcontroller mit dem Array
PersonModels
verknüpft, das wir auf unserem Ansichtscontroller verfügbar gemacht haben.
Jetzt müssen wir unsere Gliederungsansicht an den Strukturcontroller binden, gehen Sie wie folgt vor:
Wählen Sie die Gliederungsansicht aus, und wählen Sie im Bindungsinspektor :
Wählen Sie unter dem Turndown für Gliederungsansichtsinhalte die Option "Binden an " und " Strukturcontroller" aus. Geben Sie für das Feld "Controllerschlüssel" ein
arrangedObjects
:Wählen Sie die Zelle "Tabellenansicht " unter der Spalte "Mitarbeiter " aus. Wählen Sie im Bindungenprüfungsinspektor unter dem Wert-Turndown die Option "Binden an " und " Tabellenzellenansicht" aus. Geben Sie für den Modellschlüsselpfad ein
objectValue.Name
:objectValue
ist der AktuellePersonModel
im Array, das vom Strukturcontroller verwaltet wird.Wählen Sie die Zelle "Tabellenansicht" unter der Spalte "Besetzung " aus. Wählen Sie im Bindungenprüfungsinspektor unter dem Wert-Turndown die Option "Binden an " und " Tabellenzellenansicht" aus. Geben Sie für den Modellschlüsselpfad ein
objectValue.Occupation
:Speichern Sie Ihre Änderungen, und kehren Sie zu Visual Studio für Mac zurück, um mit Xcode zu synchronisieren.
Wenn wir die Anwendung ausführen, wird die Gliederung mit unserem Array von PersonModels
:
Datenbindung der Sammlungsansicht
Die Datenbindung mit einer Sammlungsansicht ist sehr ähnlich wie die Bindung mit einer Tabellenansicht, da ein Arraycontroller verwendet wird, um Daten für die Sammlung bereitzustellen. Da die Sammlungsansicht nicht über ein voreingestelltes Anzeigeformat verfügt, ist mehr Arbeit erforderlich, um Benutzerinteraktionsfeedback bereitzustellen und die Benutzerauswahl nachzuverfolgen.
Wichtig
Aufgrund eines Problems in Xcode 7 und macOS 10.11 (und höher) können Sammlungsansichten nicht innerhalb einer Storyboarddateien (Storyboard)-Dateien verwendet werden. Daher müssen Sie weiterhin XIB-Dateien verwenden, um Ihre Sammlungsansichten für Ihre Xamarin.Mac-Apps zu definieren. Weitere Informationen finden Sie in der Dokumentation zu Sammlungsansichten .
Debuggen systemeigener Abstürze
Fehler bei Ihren Datenbindungen können zu einem nativen Absturz im nicht verwalteten Code führen und dazu führen, dass Ihre Xamarin.Mac-Anwendung vollständig mit einem SIGABRT
Fehler fehlschlägt:
Bei der Datenbindung gibt es in der Regel vier Hauptursachen für systemeigene Abstürze:
- Ihr Datenmodell erbt nicht von
NSObject
oder einer Unterklasse vonNSObject
. - Sie haben Ihre Eigenschaft nicht für Objective-C die Verwendung des
[Export("key-name")]
Attributs verfügbar gemacht. - Sie haben keine Änderungen an dem Wert des Zugriffsgebers in
WillChangeValue
undDidChangeValue
Methodenaufrufen umgebrochen (angeben denselben Schlüssel wie dasExport
Attribut). - Sie haben einen falschen oder falsch eingegebenen Schlüssel im Bindungsinspektor im Schnittstellen-Generator.
Decodieren eines Absturzes
Lassen Sie uns einen systemeigenen Absturz in unserer Datenbindung verursachen, damit wir zeigen können, wie sie gefunden und behoben werden können. Im Schnittstellen-Generator ändern wir unsere Bindung der ersten Bezeichnung im Beispiel für die Sammlungsansicht von Name
:Title
Lassen Sie uns die Änderung speichern, wechseln Sie zurück zu Visual Studio für Mac, um mit Xcode zu synchronisieren und unsere Anwendung auszuführen. Wenn die Sammlungsansicht angezeigt wird, stürzt die Anwendung mit einem SIGABRT
Fehler (wie in der Anwendungsausgabe in Visual Studio für Mac dargestellt) momentariell ab, da die PersonModel
Eigenschaft nicht mit dem Schlüssel Title
verfügbar gemacht wird:
Wenn der Fehler in der Anwendungsausgabe ganz oben angezeigt wird, können wir den Schlüssel zur Lösung des Problems sehen:
Diese Zeile teilt uns mit, dass der Schlüssel Title
nicht für das Objekt vorhanden ist, an das wir binden. Wenn wir die Bindung wieder in Name
Den Schnittstellen-Generator ändern, speichern, synchronisieren, neu erstellen und ausführen, wird die Anwendung wie erwartet ohne Problem ausgeführt.
Zusammenfassung
Dieser Artikel hat einen detaillierten Blick auf die Arbeit mit Datenbindung und Schlüsselwertcodierung in einer Xamarin.Mac-Anwendung gemacht. Zunächst wurde eine C#-Klasse Objective-C mithilfe der Schlüsselwertcodierung (KVC) und der Key-Value-Observing (KVO) angezeigt. Als Nächstes wurde gezeigt, wie Sie eine KVO-kompatible Klasse und datenbindung an UI-Elemente im Xcode-Schnittstellen-Generator verwenden. Schließlich wurde die komplexe Datenbindung mithilfe von Arraycontrollern und Strukturcontrollern gezeigt.
Ähnliche Themen
- MacDatabinding Storyboard (Beispiel)
- MacDatabinding XIBs (Beispiel)
- Hello, Mac (Hallo Mac)
- Standardsteuerelemente
- Tabellenansichten
- Gliederungsansichten
- Auflistungsansichten
- Programmierhandbuch zur Schlüsselwertcodierung
- Einführung in Key-Value Beobachtungsprogrammhandbuch
- Einführung in Die Programmierungsthemen für Kakaobindungen
- Einführung in die Referenz zu Kakaobindungen
- NSCollectionView
- macOS-Eingaberichtlinien