Powiązanie danych i kodowanie klucz-wartość na platformie Xamarin.Mac
W tym artykule opisano używanie kodowania klucz-wartość i obserwowania wartości klucza w celu umożliwienia powiązania danych z elementami interfejsu użytkownika w narzędziu Interface Builder programu Xcode.
Omówienie
Podczas pracy z językami C# i .NET w aplikacji platformy Xamarin.Mac masz dostęp do tych samych technik kodowania klucz-wartość i powiązania danych, które wykonuje deweloper pracujący w Objective-C środowisku Xcode. Ponieważ platforma Xamarin.Mac integruje się bezpośrednio z programem Xcode, możesz użyć narzędzia Interface Builder Xcode do powiązania danych z elementami interfejsu użytkownika zamiast pisania kodu.
Korzystając z technik kodowania klucz-wartość i powiązania danych w aplikacji Xamarin.Mac, możesz znacznie zmniejszyć ilość kodu, który trzeba napisać i obsługiwać, aby wypełnić elementy interfejsu użytkownika i pracować z elementami interfejsu użytkownika. Masz również korzyść z dalszego oddzielenia danych zapasowych (modelu danych) od interfejsu użytkownika frontonu (Model-View-Controller), co prowadzi do łatwiejszego utrzymania, bardziej elastycznego projektowania aplikacji.
W tym artykule omówimy podstawy pracy z kodowaniem klucz-wartość i powiązaniem danych w aplikacji platformy Xamarin.Mac. Zdecydowanie zaleca się, aby najpierw zapoznać się z artykułem Hello, Mac , w szczególności wprowadzenie do narzędzi Xcode i Interface Builder i Outlet and Actions , ponieważ obejmuje ona kluczowe pojęcia i techniki, których będziemy używać w tym artykule.
Warto zapoznać się z sekcją Uwidacznianie klas/metod Objective-C języka C# w sekcji dokumentu Xamarin.Mac Internals , a także objaśnienie Register
atrybutów i Export
używanych do podłączania klas języka C# do Objective-C obiektów i elementów interfejsu użytkownika.
Co to jest kodowanie klucz-wartość
Kodowanie klucz-wartość (KVC) jest mechanizmem uzyskiwania dostępu do właściwości obiektu pośrednio przy użyciu kluczy (specjalnie sformatowanych ciągów) do identyfikowania właściwości zamiast uzyskiwania do nich dostępu za pośrednictwem zmiennych wystąpienia lub metod dostępu (get/set
). Implementując zgodne metody kodowania klucz-wartość w aplikacji Xamarin.Mac, uzyskujesz dostęp do innych funkcji systemu macOS (wcześniej znanych jako OS X), takich jak obserwowanie wartości klucza (KVO), powiązanie danych, dane podstawowe, powiązania cocoa i możliwość tworzenia skryptów.
Korzystając z technik kodowania klucz-wartość i powiązania danych w aplikacji Xamarin.Mac, możesz znacznie zmniejszyć ilość kodu, który trzeba napisać i obsługiwać, aby wypełnić elementy interfejsu użytkownika i pracować z elementami interfejsu użytkownika. Masz również korzyść z dalszego oddzielenia danych zapasowych (modelu danych) od interfejsu użytkownika frontonu (Model-View-Controller), co prowadzi do łatwiejszego utrzymania, bardziej elastycznego projektowania aplikacji.
Przyjrzyjmy się na przykład następującej definicji klasy obiektu zgodnego z 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 ()
{
}
}
}
[Register("PersonModel")]
Najpierw atrybut rejestruje klasę i uwidacznia ją w pliku Objective-C. Następnie klasa musi dziedziczyć z NSObject
(lub podklasy dziedziczonej z NSObject
), spowoduje to dodanie kilku metod bazowych, które umożliwiają klasę zgodności KVC. Następnie atrybut uwidacznia Name
właściwość i definiuje wartość Klucza, [Export("Name")]
która będzie później używana do uzyskiwania dostępu do właściwości za pośrednictwem technik KVC i KVO.
Na koniec, aby można było zmienić wartość klucza obserwowanego na wartość właściwości, metoda dostępu musi opakowować zmiany w jego wartości w WillChangeValue
wywołaniach metody i DidChangeValue
(określając ten sam klucz co Export
atrybut). Na przykład:
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
Ten krok jest bardzo ważny w przypadku powiązania danych w narzędziu Interface Builder programu Xcode (jak zobaczymy w dalszej części tego artykułu).
Aby uzyskać więcej informacji, zobacz Przewodnik programowania kodowania klucz-wartość firmy Apple.
Klucze i ścieżki kluczy
Klucz to ciąg, który identyfikuje określoną właściwość obiektu. Zazwyczaj klucz odpowiada nazwie metody dostępu w obiekcie zgodnym z kodowaniem klucz-wartość. Klucze muszą używać kodowania ASCII, zwykle zaczyna się od małej litery i mogą nie zawierać białych znaków. W związku z tym, biorąc pod uwagę powyższy przykład, Name
byłaby wartością Name
klucza właściwości PersonModel
klasy. Klucz i nazwa właściwości, którą uwidaczniają, nie muszą być takie same, jednak w większości przypadków są.
Ścieżka klucza to ciąg kluczy rozdzielonych kropkami używany do określania hierarchii właściwości obiektu do przechodzenia. Właściwość pierwszego klucza w sekwencji jest względna względem odbiornika, a każdy kolejny klucz jest oceniany względem wartości poprzedniej właściwości. W ten sam sposób używasz notacji kropkowej do przechodzenia przez obiekt i jego właściwości w klasie C#.
Jeśli na przykład rozszerzono klasę PersonModel
i dodano Child
właściwość:
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 ()
{
}
}
}
Ścieżka klucza do nazwy elementu podrzędnego to self.Child.Name
lub po prostu Child.Name
(na podstawie sposobu użycia wartości klucza).
Pobieranie wartości przy użyciu kodowania klucz-wartość
Metoda ValueForKey
zwraca wartość określonego klucza (jako NSString
), względem wystąpienia klasy KVC odbierającego żądanie. Jeśli na przykład Person
jest wystąpieniem klasy zdefiniowanej PersonModel
powyżej:
// Read value
var name = Person.ValueForKey (new NSString("Name"));
Spowoduje to zwrócenie wartości Name
właściwości dla tego wystąpienia klasy PersonModel
.
Ustawianie wartości przy użyciu kodowania klucz-wartość
SetValueForKey
Podobnie ustaw wartość określonego klucza (jako NSString
), względem wystąpienia klasy KVC odbierającego żądanie. Ponownie, używając wystąpienia PersonModel
klasy, jak pokazano poniżej:
// Write value
Person.SetValueForKey(new NSString("Jane Doe"), new NSString("Name"));
Spowoduje zmianę wartości Name
właściwości na Jane Doe
.
Obserwowanie zmian wartości
Korzystając z funkcji obserwowania wartości klucza (KVO), można dołączyć obserwatora do określonego klucza zgodnej klasy KVC i otrzymywać powiadomienia o każdej zmianie wartości dla tego klucza (przy użyciu technik KVC lub bezpośredniego uzyskiwania dostępu do danej właściwości w kodzie języka C#). Na przykład:
// Watch for the name value changing
Person.AddObserver ("Name", NSKeyValueObservingOptions.New, (sender) => {
// Inform caller of selection change
Console.WriteLine("New Name: {0}", Person.Name)
});
Teraz za każdym razem, gdy Name
właściwość Person
wystąpienia PersonModel
klasy zostanie zmodyfikowana, nowa wartość zostanie zapisana w konsoli.
Aby uzyskać więcej informacji, zobacz Wprowadzenie firmy Apple do podręcznika programowania z obserwacją wartości klucz-wartość.
Powiązanie danych
W poniższych sekcjach pokazano, jak można używać kodowania klucz-wartość i wartości klucz-wartość obserwowania zgodnej klasy w celu powiązania danych z elementami interfejsu użytkownika w konstruktorze interfejsu Xcode, zamiast odczytywać i zapisywać wartości przy użyciu kodu języka C#. W ten sposób oddzielisz model danych od widoków używanych do ich wyświetlania, dzięki czemu aplikacja Xamarin.Mac będzie bardziej elastyczna i łatwiejsza w obsłudze. Znacznie zmniejszasz również ilość kodu, który musi być napisany.
Definiowanie modelu danych
Aby można było powiązać element interfejsu użytkownika w narzędziu Interface Builder, musisz mieć klasę zgodną z KVC/KVO zdefiniowaną w aplikacji Xamarin.Mac, aby działać jako model danych dla powiązania. Model danych udostępnia wszystkie dane, które będą wyświetlane w interfejsie użytkownika i odbiera wszelkie modyfikacje danych, które użytkownik wprowadza w interfejsie użytkownika podczas uruchamiania aplikacji.
Jeśli na przykład tworzysz aplikację zarządzającą grupą pracowników, możesz użyć następującej klasy do zdefiniowania modelu danych:
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
}
}
Większość funkcji tej klasy została omówiona w sekcji Co to jest kodowanie klucz-wartość powyżej. Przyjrzyjmy się jednak kilku konkretnym elementom i dodaniu, które zostały wprowadzone, aby umożliwić tej klasie działanie jako model danych dla kontrolerów tablicy i kontrolerów drzewa (które będziemy później używać do tworzenia powiązań widoków drzewa, widoków konspektu i widoków kolekcji).
Po pierwsze, ponieważ pracownik może być menedżerem, użyliśmy NSArray
elementu (w szczególności NSMutableArray
wartości, dzięki czemu można modyfikować wartości), aby umożliwić pracownikom, którym udało się dołączyć do nich:
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
W tym miejscu należy zwrócić uwagę na dwie kwestie:
- Użyliśmy
NSMutableArray
elementu zamiast standardowej tablicy lub kolekcji języka C#, ponieważ jest to wymagane powiązanie danych z kontrolkami AppKit, takimi jak widoki tabel, widoki konspektu i kolekcje. - Ujawniliśmy tablicę pracowników, odrzucając ją do
NSArray
elementu na potrzeby powiązania danych i zmieniliśmy jego nazwę sformatowaną w języku C#,People
na oczekiwaną przez powiązanie danych w postaci {class_name}Tablica (zwróć uwagę,personModelArray
że pierwszy znak został złożony w małym przypadku).
Następnie musimy dodać kilka specjalnie nazwanych metod publicznych, aby obsługiwać kontrolery tablic i kontrolery drzewa:
[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");
}
Umożliwiają one kontrolerom żądanie i zmodyfikowanie wyświetlanych danych. Podobnie jak powyżej, NSArray
mają one bardzo konkretną konwencję nazewnictwa (która różni się od typowych konwencji nazewnictwa języka C#):
addObject:
- Dodaje obiekt do tablicy.insertObject:in{class_name}ArrayAtIndex:
- Gdzie{class_name}
jest nazwą klasy. Ta metoda wstawia obiekt do tablicy w danym indeksie.removeObjectFrom{class_name}ArrayAtIndex:
- Gdzie{class_name}
jest nazwą klasy. Ta metoda usuwa obiekt w tablicy w danym indeksie.set{class_name}Array:
- Gdzie{class_name}
jest nazwą klasy. Ta metoda umożliwia zastąpienie istniejącego przenoszenia nowym.
Wewnątrz tych metod opakowaliśmy zmiany w tablicy i WillChangeValue
DidChangeValue
komunikaty dotyczące zgodności Z usługą KVO.
Na koniec, ponieważ Icon
właściwość opiera się na wartości isManager
właściwości, zmiany isManager
właściwości mogą nie zostać odzwierciedlone w Icon
elementach interfejsu użytkownika powiązanego z danymi (podczas KVO):
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
Aby rozwiązać ten błąd, użyjemy następującego kodu:
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
Należy pamiętać, isManager
że oprócz własnego klucza, akcesorium wysyła WillChangeValue
również komunikaty i DidChangeValue
dla Icon
klucza, aby zobaczyć również zmianę.
W pozostałej części tego artykułu będziemy używać PersonModel
modelu danych.
Proste powiązanie danych
Po zdefiniowaniu modelu danych przyjrzyjmy się prostemu przykładowi powiązania danych w narzędziu Xcode Interface Builder. Na przykład dodajmy formularz do naszej aplikacji Xamarin.Mac, która może służyć do edytowania zdefiniowanego PersonModel
powyżej elementu. Dodamy kilka pól tekstowych i pole wyboru, aby wyświetlić i edytować właściwości naszego modelu.
Najpierw dodajmy nowy kontroler widoku do naszego pliku Main.storyboard w narzędziu Interface Builder i nadajmy jej klasie SimpleViewController
nazwę :
Następnie wróć do Visual Studio dla komputerów Mac, zmodyfikuj plik SimpleViewController.cs (automatycznie dodany do naszego projektu) i uwidocznij wystąpieniePersonModel
, z którego będziemy wiązać formularz. Dodaj następujący kod:
private PersonModel _person = new PersonModel();
...
[Export("Person")]
public PersonModel Person {
get {return _person; }
set {
WillChangeValue ("Person");
_person = value;
DidChangeValue ("Person");
}
}
Następnie po załadowaniu widoku utwórzmy wystąpienie naszego PersonModel
obiektu i wypełnimy go następującym kodem:
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;
}
Teraz musimy utworzyć formularz, kliknij dwukrotnie plik Main.storyboard, aby otworzyć go do edycji w narzędziu Interface Builder. Układ formularza w taki sposób, aby wyglądał podobnie do następującego:
Aby powiązać PersonModel
formularz z udostępnionym formularzem Person
za pośrednictwem klucza, wykonaj następujące czynności:
Wybierz pole tekstowe Nazwy pracownika i przejdź do inspektora powiązań.
Zaznacz pole Bind to (Powiąż z) i wybierz pozycję Simple View Controller (Prosty kontroler widoku) z listy rozwijanej. Następnie wprowadź wartość
self.Person.Name
dla ścieżki klucza:Zaznacz pole Tekst zawodu i zaznacz pole Bind to (Powiąż z) i wybierz z listy rozwijanej pozycję Simple View Controller (Prosty kontroler widoku). Następnie wprowadź wartość
self.Person.Occupation
dla ścieżki klucza:Zaznacz pole wyboru Employee is a Manager (Pracownik jest menedżerem) i zaznacz pole Bind to (Powiąż z) i wybierz pozycję Simple View Controller (Prosty kontroler widoku) z listy rozwijanej. Następnie wprowadź wartość
self.Person.isManager
dla ścieżki klucza:Wybierz pole Tekstowe Liczba pracowników zarządzanych, a następnie zaznacz pole Bind to (Powiąż z) i wybierz z listy rozwijanej pozycję Simple View Controller (Prosty kontroler widoku). Następnie wprowadź wartość
self.Person.NumberOfEmployees
dla ścieżki klucza:Jeśli pracownik nie jest menedżerem, chcemy ukryć etykietę zarządzaną liczba pracowników i pole tekstowe.
Wybierz etykietę zarządzaną liczba pracowników, rozwiń opcję Ukryte, a następnie zaznacz pole Bind to (Powiąż z) i wybierz pozycję Simple View Controller (Prosty kontroler widoku) z listy rozwijanej. Następnie wprowadź wartość
self.Person.isManager
dla ścieżki klucza:Wybierz
NSNegateBoolean
z listy rozwijanej Przekształcanie wartości:Informuje to powiązanie danych, że etykieta będzie ukryta, jeśli wartość
isManager
właściwości tofalse
.Powtórz kroki 7 i 8 dla pola Tekstowego Liczba pracowników zarządzanych .
Zapisz zmiany i wróć do Visual Studio dla komputerów Mac, aby przeprowadzić synchronizację z programem Xcode.
Jeśli uruchomisz aplikację, wartości z Person
właściwości automatycznie wypełnią formularz:
Wszelkie zmiany wprowadzone przez użytkowników do formularza zostaną zapisane z powrotem do Person
właściwości w kontrolerze widoku. Na przykład usunięcie zaznaczenia pracownik jest menedżerem aktualizuje Person
wystąpienie naszego PersonModel
, a pole tekstowe liczba pracowników zarządzanych etykiet i pól tekstowych są automatycznie ukryte (za pośrednictwem powiązania danych):
Powiązanie danych widoku tabeli
Teraz, gdy mamy już podstawowe informacje o powiązaniu danych, przyjrzyjmy się bardziej złożonemu zadaniu powiązania danych przy użyciu kontrolera tablicy i powiązania danych z widokiem tabeli. Aby uzyskać więcej informacji na temat pracy z widokami tabel, zobacz dokumentację widoków tabel.
Najpierw dodajmy nowy kontroler widoku do naszego pliku Main.storyboard w narzędziu Interface Builder i nadajmy jej klasie TableViewController
nazwę :
Następnie zmodyfikujmy plik TableViewController.cs (automatycznie dodany do naszego projektu) i uwidaczniamy tablicę (NSArray
) PersonModel
klas, z którymi będziemy wiązać formularz. Dodaj następujący kod:
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");
}
Podobnie jak w przypadku powyższej PersonModel
klasy w sekcji Definiowanie modelu danych udostępniliśmy cztery specjalnie nazwane metody publiczne, tak aby kontroler tablicy i odczytywał i zapisywał dane z naszej kolekcji PersonModels
.
Następnie po załadowaniu widoku musimy wypełnić tablicę następującym kodem:
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"));
}
Teraz musimy utworzyć widok tabeli, kliknij dwukrotnie plik Main.storyboard, aby otworzyć go do edycji w narzędziu Interface Builder. Układ tabeli w taki sposób, aby wyglądała następująco:
Musimy dodać kontroler tablicy, aby zapewnić powiązane dane do naszej tabeli, wykonaj następujące czynności:
Przeciągnij kontroler tablicy z inspektora biblioteki do edytora interfejsu:
Wybierz pozycję Kontroler tablicy w hierarchii interfejsu i przejdź do inspektora atrybutów:
Wprowadź
PersonModel
nazwę klasy, kliknij przycisk Plus i dodaj trzy klucze. Nazwij jeName
,Occupation
iisManager
:Informuje to kontroler tablicy, o czym zarządza tablicą i jakie właściwości powinien uwidocznić (za pośrednictwem kluczy).
Przejdź do inspektora powiązań i w obszarze Tablica zawartości wybierz pozycję Powiąż z i Kontroler widoku tabeli. Wprowadź ścieżkę klucza modelu :
self.personModelArray
Spowoduje to powiązania kontrolera tablicy z tablicą
PersonModels
, która została uwidoczniona na kontrolerze widoku.
Teraz musimy powiązać widok tabeli z kontrolerem tablicy, wykonaj następujące czynności:
Wybierz widok tabeli i inspektora powiązań:
W obszarze wyłączenia spisu treści wybierz pozycję Powiąż z i Kontroler tablicy. Wprowadź
arrangedObjects
wartość dla pola Klucz kontrolera:Wybierz komórkę Widok tabeli w kolumnie Pracownik. W Inspektorze powiązań w obszarze ściągnięć wybierz pozycję Powiąż z i Widok komórki tabeli. Wprowadź
objectValue.Name
wartość dla ścieżki klucza modelu:objectValue
jest bieżącą wartościąPersonModel
w tablicy zarządzanej przez kontroler tablicy.Wybierz komórkę Widoku tabeli w kolumnie Zawód. W Inspektorze powiązań w obszarze ściągnięć wybierz pozycję Powiąż z i Widok komórki tabeli. Wprowadź
objectValue.Occupation
wartość dla ścieżki klucza modelu:Zapisz zmiany i wróć do Visual Studio dla komputerów Mac, aby przeprowadzić synchronizację z programem Xcode.
Jeśli uruchomimy aplikację, tabela zostanie wypełniona naszą tablicą PersonModels
:
Powiązanie danych widoku konspektu
powiązanie danych z widokiem konspektu jest bardzo podobne do powiązania z widokiem tabeli. Kluczową różnicą jest to, że będziemy używać kontrolera drzewa zamiast kontrolera tablicy w celu udostępnienia powiązanych danych do widoku konspektu. Aby uzyskać więcej informacji na temat pracy z widokami konspektu, zobacz dokumentację widoków konspektu.
Najpierw dodajmy nowy kontroler widoku do naszego pliku Main.storyboard w narzędziu Interface Builder i nadajmy jej klasie OutlineViewController
nazwę :
Następnie zmodyfikujmy plik OutlineViewController.cs (który został automatycznie dodany do naszego projektu) i uwidaczniamy tablicę (NSArray
) PersonModel
klas, z którymi będziemy wiązać formularz. Dodaj następujący kod:
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");
}
Podobnie jak w przypadku powyższej PersonModel
klasy w sekcji Definiowanie modelu danych udostępniliśmy cztery specjalnie nazwane metody publiczne, tak aby kontroler drzewa i odczytywał i zapisywał dane z naszej kolekcji PersonModels
.
Następnie po załadowaniu widoku musimy wypełnić tablicę następującym kodem:
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);
}
Teraz musimy utworzyć widok konspektu, kliknij dwukrotnie plik Main.storyboard, aby otworzyć go do edycji w narzędziu Interface Builder. Układ tabeli w taki sposób, aby wyglądała następująco:
Musimy dodać kontroler drzewa, aby podać powiązane dane do naszego konspektu, wykonaj następujące czynności:
Przeciągnij kontroler drzewa z inspektora biblioteki do edytora interfejsu:
Wybierz pozycję Kontroler drzewa w hierarchii interfejsu i przejdź do inspektora atrybutów:
Wprowadź
PersonModel
nazwę klasy, kliknij przycisk Plus i dodaj trzy klucze. Nazwij jeName
,Occupation
iisManager
:Informuje to kontroler drzewa o zarządzaniu tablicą i właściwości, które powinny uwidocznić (za pośrednictwem kluczy).
W sekcji Kontroler drzewa wprowadź
personModelArray
wartość Dla elementów podrzędnych, wprowadźNumberOfEmployees
wartość w obszarze Liczba i wprowadź wartośćisEmployee
w obszarze Liść:Informuje to kontroler drzewa, gdzie można znaleźć wszystkie węzły podrzędne, ile węzłów podrzędnych istnieje i czy bieżący węzeł ma węzły podrzędne.
Przejdź do Inspektora powiązań i w obszarze Tablica zawartości wybierz pozycję Powiąż z i Właściciel pliku. Wprowadź ścieżkę klucza modelu :
self.personModelArray
Spowoduje to powiązania kontrolera drzewa z tablicą
PersonModels
, którą uwidoczniliśmy na kontrolerze widoku.
Teraz musimy powiązać widok konspektu z kontrolerem drzewa, wykonaj następujące czynności:
Wybierz widok konspektu, a następnie w inspektorze powiązań wybierz pozycję :
W obszarze wyłączenia zawartości widoku konspektu wybierz pozycję Powiąż z i Kontroler drzewa. Wprowadź
arrangedObjects
wartość dla pola Klucz kontrolera:Wybierz komórkę Widok tabeli w kolumnie Pracownik. W Inspektorze powiązań w obszarze ściągnięć wybierz pozycję Powiąż z i Widok komórki tabeli. Wprowadź
objectValue.Name
wartość dla ścieżki klucza modelu:objectValue
jest bieżącąPersonModel
wartością w tablicy zarządzanej przez kontroler drzewa.Wybierz komórkę Widoku tabeli w kolumnie Zawód. W Inspektorze powiązań w obszarze ściągnięć wybierz pozycję Powiąż z i Widok komórki tabeli. Wprowadź
objectValue.Occupation
wartość dla ścieżki klucza modelu:Zapisz zmiany i wróć do Visual Studio dla komputerów Mac, aby przeprowadzić synchronizację z programem Xcode.
Jeśli uruchomimy aplikację, konspekt zostanie wypełniony naszą tablicą PersonModels
:
Powiązanie danych widoku kolekcji
Powiązanie danych z widokiem kolekcji jest bardzo podobne do powiązania z widokiem tabeli, ponieważ kontroler tablicy służy do udostępniania danych dla kolekcji. Ponieważ widok kolekcji nie ma wstępnie ustawionego formatu wyświetlania, wymagana jest większa praca w celu przekazywania opinii o interakcji użytkownika i śledzenia wyboru użytkownika.
Ważne
Ze względu na problem w programach Xcode 7 i macOS 10.11 (i nowszych) widoki kolekcji nie mogą być używane wewnątrz plików scenorysu (scenorysu). W związku z tym należy nadal używać plików xib w celu zdefiniowania widoków kolekcji dla aplikacji platformy Xamarin.Mac. Aby uzyskać więcej informacji, zobacz dokumentację widoków kolekcji.
Debugowanie awarii natywnych
Pomyłka w powiązaniach danych może spowodować awarię natywną w kodzie niezarządzanym i spowodować całkowite niepowodzenie aplikacji Xamarin.Mac z SIGABRT
powodu błędu:
Zazwyczaj istnieją cztery główne przyczyny awarii natywnych podczas tworzenia powiązania danych:
- Model danych nie dziedziczy z
NSObject
ani podklasy klasyNSObject
. - Nie uwidacznialiśmy właściwości Objective-C przy użyciu atrybutu
[Export("key-name")]
. - Nie zawijaliśmy zmian wartości metody dostępu w wywołaniach
WillChangeValue
metody iDidChangeValue
(określając ten sam klucz coExport
atrybut). - W narzędziu Interface Builder istnieje nieprawidłowy lub błędnie wtypowany klucz w inspektorze powiązań.
Dekodowanie awarii
Spowodujemy awarię natywną w powiązaniu danych, aby pokazać, jak ją zlokalizować i naprawić. W narzędziu Interface Builder zmieńmy nasze powiązanie pierwszej etykiety w przykładzie widoku kolekcji z Name
na Title
:
Zapiszmy zmianę, wróćmy do Visual Studio dla komputerów Mac, aby zsynchronizować się z programem Xcode i uruchomić naszą aplikację. Po wyświetleniu widoku kolekcji aplikacja chwilowo ulegnie awarii z SIGABRT
powodu błędu (jak pokazano w danych wyjściowych aplikacji w Visual Studio dla komputerów Mac), ponieważ PersonModel
właściwość nie uwidacznia właściwości z kluczem Title
:
Jeśli przewiniemy w górnej części błędu w danych wyjściowych aplikacji, zobaczymy klucz do rozwiązania problemu:
Ten wiersz informuje nas, że klucz Title
nie istnieje w obiekcie, z którymi jesteśmy powiązani. Jeśli zmienimy powiązanie z powrotem na Name
w narzędziu Interface Builder, zapiszemy, synchronizujemy, skompilujemy i uruchomimy, aplikacja będzie działać zgodnie z oczekiwaniami bez problemu.
Podsumowanie
W tym artykule szczegółowo przedstawiono pracę z powiązaniem danych i kodowaniem klucz-wartość w aplikacji platformy Xamarin.Mac. Najpierw przyjrzeliśmy się uwidacznieniu klasy Objective-C C# przy użyciu kodowania klucz-wartość (KVC) i obserwowania wartości klucz-wartość (KVO). Następnie pokazano, jak używać klasy zgodnej z KVO i powiązać je z elementami interfejsu użytkownika w narzędziu Interface Builder programu Xcode. Na koniec pokazano złożone powiązanie danych przy użyciu kontrolerów tablic i kontrolerów drzewa.
Linki powiązane
- Witaj, Mac
- Kontrolki standardowe
- Widoki tabeli
- Widoki konspektu
- Widoki kolekcji
- Przewodnik programowania kodowania klucz-wartość
- Wprowadzenie do przewodnika programowania obserwowanego przez klucz-wartość
- Wprowadzenie do tematów programowania powiązań kakaowych
- Wprowadzenie do powiązań kakao
- NSCollectionView
- Wskazówki dotyczące interfejsu człowieka dla systemu macOS