Enlace de datos y codificación de clave-valor en Xamarin.Mac
En este artículo se describe el uso de la codificación de clave-valor y la observación de clave-valor para permitir el enlace de datos a elementos de la interfaz de usuario en el Interface Builder de Xcode.
Información general
Al trabajar con C# y .NET en una aplicación de Xamarin.Mac, tiene acceso a las mismas técnicas de codificación de clave-valor y enlace de datos que un desarrollador que trabaja en Objective-CObjective-C Dado que Xamarin.Mac se integra directamente con Xcode, puede usar el Interface Builder de Xcode para enlazar datos con elementos de la interfaz de usuario en lugar de escribir código.
Mediante el uso de técnicas de codificación de clave-valor y enlace de datos en la aplicación de Xamarin.Mac, puede reducir considerablemente la cantidad de código que tiene que escribir y mantener para rellenar y trabajar con elementos de la interfaz de usuario. También tiene la ventaja de desacomantear aún más los datos de respaldo(modelode datos) de sufront-endInterfaz de usuario (controlador de vista de modelo), lo que facilita el mantenimiento y el diseño de aplicaciones más flexible.
Un ejemplo de la aplicación en
En este artículo, se tratarán los conceptos básicos de trabajar con codificación de clave-valor y enlace de datos en una aplicación de Xamarin.Mac. Se recomienda encarecidamente trabajar primero en el artículo Hola, Mac, en concreto en las secciones Introducción a Xcode y Interface Builder y Salidas y acciones, ya que trata los conceptos y técnicas clave que se usarán en este artículo.
Es posible que también quiera echar un vistazo a la sección del documento Aspectos internos de Exposing C# classes / methods to Objective-CExposing C# classes / methods to Objective-C donde se explican los atributos y que se usan para conectar las clases de C# a objetos y elementos de la interfaz RegisterExport de Objective-C usuario.
¿Qué es la codificación clave-valor?
La codificación de clave-valor (KVC) es un mecanismo para acceder indirectamente a las propiedades de un objeto, mediante claves (cadenas con formato especial) para identificar propiedades en lugar de acceder a ellas a través de variables de instancia o métodos de accessor ( get/set ). Al implementar los accessors compatibles con la codificación de clave-valor en la aplicación de Xamarin.Mac, obtendrá acceso a otras características de macOS (anteriormente conocidas como OS X), como la observación de clave-valor (KVO), el enlace de datos, los datos principales, los enlaces de Cocoa y la capacidad de script.
Mediante el uso de técnicas de codificación de clave-valor y enlace de datos en la aplicación de Xamarin.Mac, puede reducir considerablemente la cantidad de código que tiene que escribir y mantener para rellenar y trabajar con elementos de la interfaz de usuario. También tiene la ventaja de desacomantear aún más los datos de respaldo(modelode datos) de sufront-endInterfaz de usuario (controlador de vista de modelo), lo que facilita el mantenimiento y el diseño de aplicaciones más flexible.
Por ejemplo, echemos un vistazo a la siguiente definición de clase de un objeto compatible con 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 ()
{
}
}
}
En primer lugar, [Register("PersonModel")] el atributo registra la clase y la expone a Objective-C . A continuación, la clase debe heredar de (o una subclase que hereda de ), lo que agrega varios métodos base que permiten que la clase sea NSObjectNSObject compatible con KVC. A continuación, el atributo expone la propiedad y define el valor de clave que se usará más adelante para acceder a la propiedad a través de [Export("Name")]Name técnicas KVC y KVO.
Por último, para poder Key-Value cambios observados en el valor de la propiedad, el accessor debe encapsular los cambios en su valor en las llamadas al método y (especificando la misma clave que el WillChangeValueDidChangeValue atributo Export ). Por ejemplo:
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
Este paso es muy importante para el enlace de datos en el Interface Builder Xcode (como veremos más adelante en este artículo).
Para más información, consulte la Guía de programación de codificación clave-valor deApple.
Claves y rutas de acceso de clave
Una clave es una cadena que identifica una propiedad específica de un objeto . Normalmente, una clave corresponde al nombre de un método de accessor en un objeto compatible con codificación de clave-valor. Las claves deben usar codificación ASCII, normalmente comenzar con una letra minúscula y no pueden contener espacios en blanco. Por lo tanto, dado el ejemplo Name anterior, sería un valor clave Name de la propiedad de la clase PersonModel . La clave y el nombre de la propiedad que exponen no tienen que ser iguales, pero en la mayoría de los casos sí lo son.
Una ruta de acceso de clave es una cadena de claves separadas por puntos que se usa para especificar una jerarquía de propiedades de objeto para recorrer. La propiedad de la primera clave de la secuencia es relativa al receptor y cada clave posterior se evalúa con respecto al valor de la propiedad anterior. De la misma manera que se usa la notación de puntos para recorrer un objeto y sus propiedades en una clase de C#.
Por ejemplo, si expandió la PersonModel clase y agregó la Child propiedad :
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 ()
{
}
}
}
La ruta de acceso de la clave al nombre del elemento secundario sería o simplemente (en función de cómo se usara el self.Child.NameChild.Name valor de clave).
Obtención de valores mediante la codificación clave-valor
El método devuelve el valor de la clave especificada (como ), en relación con la instancia de la clase ValueForKeyNSString KVC que recibe la solicitud. Por ejemplo, si Person es una instancia de la clase definida PersonModel anteriormente:
// Read value
var name = Person.ValueForKey (new NSString("Name"));
Esto devolvería el valor de la Name propiedad para esa instancia de PersonModel .
Establecimiento de valores mediante la codificación clave-valor
Del mismo modo, establece el valor de la clave especificada (como ), en relación con la instancia de la clase SetValueForKeyNSString KVC que recibe la solicitud. De nuevo, con una instancia de la PersonModel clase , como se muestra a continuación:
// Write value
Person.SetValueForKey(new NSString("Jane Doe"), new NSString("Name"));
Cambiaría el valor de la Name propiedad a Jane Doe .
Observar los cambios de valor
Mediante la observación de clave-valor (KVO), puede adjuntar un observador a una clave específica de una clase compatible con KVC y recibir una notificación cada vez que se modifique el valor de esa clave (ya sea mediante técnicas KVC o accediendo directamente a la propiedad determinada en el código de C#). Por ejemplo:
// Watch for the name value changing
Person.AddObserver ("Name", NSKeyValueObservingOptions.New, (sender) => {
// Inform caller of selection change
Console.WriteLine("New Name: {0}", Person.Name)
});
Ahora, cada vez que se modifica la propiedad de la instancia de Name la clase , el nuevo valor se escribe en la PersonPersonModel consola.
Para obtener más información, vea Introducción a Apple para Key-Value de programación de observación.
Enlace de datos
En las secciones siguientes se muestra cómo puede usar una clase compatible con la codificación de clave-valor y la clase compatible con la observación de clave-valor para enlazar datos a elementos de la interfaz de usuario en el Interface Builder de Xcode, en lugar de leer y escribir valores mediante código de C#. De este modo, separa el modelo de datos de las vistas que se usan para mostrarlas, lo que hace que la aplicación de Xamarin.Mac sea más flexible y fácil de mantener. También reduce considerablemente la cantidad de código que se debe escribir.
Definición del modelo de datos
Para poder enlazar datos a un elemento de la interfaz de usuario en Interface Builder, debe tener una clase compatible con KVC/KVO definida en la aplicación de Xamarin.Mac para que actúe como modelo de datos para el enlace. El modelo de datos proporciona todos los datos que se mostrarán en el Interfaz de usuario y recibe cualquier modificación en los datos que el usuario realiza en la interfaz de usuario mientras ejecuta la aplicación.
Por ejemplo, si estuviera escribiendo una aplicación que administraba un grupo de empleados, podría usar la clase siguiente para definir el modelo de datos:
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 mayoría de las características de esta clase se han descrito en la sección ¿Qué es la codificación clave-valor? anterior. Sin embargo, veamos algunos elementos específicos y algunas adiciones que se realizaron para permitir que esta clase actúe como modelo de datos para controladores de matriz y controladores de árbol (que usaremos más adelante en Vistas de árbol de enlace de datos,Vistas de esquema y Vistas de colección).
En primer lugar, dado que un empleado podría ser un administrador, hemos usado un (específicamente un para que se puedan modificar los valores) para permitir que los empleados a los que han administrado se les puedan NSArrayNSMutableArray adjuntar:
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
Dos cosas que debe tener en cuenta aquí:
- Hemos usado en lugar de una matriz o colección estándar de C#, ya que se trata de un requisito para enlazar datos a controles AppKit, como vistas de tabla, vistas de esquema
NSMutableArrayy colecciones.NSMutableArray - Exponemos la matriz de empleados al convertirla en para el enlace de datos y cambiamos su nombre con formato de C#, , a uno que el enlace de datos espera, con el formato
NSArrayPeoplepersonModelArrayNSArray(tenga en cuenta que el primer carácter se ha convertido en minúsculas).
A continuación, es necesario agregar algunos métodos públicos de nombre especiales para admitir controladores de matriz ycontroladores de árbol:
[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");
}
Permiten a los controladores solicitar y modificar los datos que muestran. Al igual que los expuestos anteriormente, tienen una convención de nomenclatura muy específica (que difiere de las convenciones de NSArray nomenclatura típicas de C#):
addObject:: agrega un objeto a la matriz.insertObject:in{class_name}ArrayAtIndex:- Donde{class_name}es el nombre de la clase. Este método inserta un objeto en la matriz en un índice determinado.removeObjectFrom{class_name}ArrayAtIndex:- Donde{class_name}es el nombre de la clase. Este método quita el objeto de la matriz en un índice determinado.set{class_name}Array:- Donde{class_name}es el nombre de la clase. Este método permite reemplazar el transporte existente por uno nuevo.
Dentro de estos métodos, hemos encapsulado los cambios en la matriz en los mensajes y para WillChangeValueDidChangeValue el cumplimiento de KVO.
Por último, puesto que la propiedad se basa en el valor de la propiedad , es posible que los cambios realizados en la propiedad no se reflejen en para los elementos de interfaz de usuario enlazados a datos IconisManagerisManagerIcon (durante KVO):
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
Para corregirlo, usamos el código siguiente:
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
Tenga en cuenta que, además de su propia clave, el accessor también envía los mensajes y para la clave, por lo que también isManagerWillChangeValue verá el DidChangeValueIcon cambio.
Usaremos el modelo de PersonModel datos en el resto de este artículo.
Enlace de datos simple
Con el modelo de datos definido, echemos un vistazo a un ejemplo sencillo de enlace de datos en el Interface Builder de Xcode. Por ejemplo, vamos a agregar un formulario a nuestra aplicación de Xamarin.Mac que se puede usar para editar el que PersonModel definimos anteriormente. Agregaremos algunos campos de texto y una casilla para mostrar y editar las propiedades de nuestro modelo.
En primer lugar, vamos a agregar un nuevo controlador de vistas a nuestro archivo Main.storyboard en Interface Builder nombre a su clase :
A continuación, vuelva a Visual Studio para Mac, edite el archivo SimpleViewController.cs (que se agregó automáticamente a nuestro proyecto) y exponga una instancia de a la que se enlazará el formulario de datos. Agregue el código siguiente:
private PersonModel _person = new PersonModel();
...
[Export("Person")]
public PersonModel Person {
get {return _person; }
set {
WillChangeValue ("Person");
_person = value;
DidChangeValue ("Person");
}
}
A continuación, cuando se cargue la vista, vamos a crear una instancia de y PersonModel rellenarla con este código:
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;
}
Ahora es necesario crear el formulario, haga doble clic en el archivo Main.storyboard para abrirlo para editarlo en Interface Builder. Diseño del formulario para que sea algo parecido a lo siguiente:
Para enlazar datos al formulario que PersonModel se expone a través de la Person clave, haga lo siguiente:
Seleccione el campo de texto Employee Name (Nombre de empleado) y cambie a Bindings Inspector (Inspector de enlaces).
Active la casilla Enlazar a y seleccione Controlador de vista simple en la lista desplegable. A
self.Person.Namecontinuación, escriba para laself.Person.Name:Seleccione el campo Texto de ocupación, active la casilla Enlazar a y seleccione Controlador de vista simple en la lista desplegable. A
self.Person.Occupationcontinuación, escriba para laself.Person.Occupation:Active la casilla Employee is a Manager (Empleado es un administrador), active la casilla Enlazar a y seleccione Controlador de vista simple en la lista desplegable. A
self.Person.isManagercontinuación, escriba para laself.Person.isManager:Seleccione el campo de texto administrado Número de empleados, active la casilla Enlazar a y seleccione Controlador de vista simple en la lista desplegable. A
self.Person.NumberOfEmployeescontinuación, escriba para laself.Person.NumberOfEmployees:Si el empleado no es un administrador, queremos ocultar el campo de texto y la etiqueta administrada Número de empleados.
Seleccione la etiqueta administrada Número de empleados, expanda la lista desplegable Oculta, active la casilla Enlazar a y seleccione Controlador de vista simple en la lista desplegable. A
self.Person.isManagercontinuación, escriba para laself.Person.isManager:Seleccione
NSNegateBooleanen la lista desplegable ValueNSNegateBoolean
Selección de la transformación de claveEsto indica al enlace de datos que la etiqueta se ocultará si el valor de la
isManagerpropiedad esfalse.Repita los pasos 7 y 8 para el campo de texto administrado Número de empleados.
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Si ejecuta la aplicación, los valores de la Person propiedad rellenarán automáticamente el formulario:
Los cambios que los usuarios realicen en el formulario se escribirán de nuevo en la Person propiedad en el controlador de vistas. Por ejemplo, si se anula la selección de Empleado es un administrador, se actualiza la instancia de y la etiqueta administrada número de empleados y el campo de texto se ocultan automáticamente (a través del enlace de PersonModel datos): PersonModel
Enlace de datos de la vista de tabla
Ahora que tenemos los conceptos básicos del enlace de datos fuera del camino, echemos un vistazo a una tarea de enlace de datos más compleja mediante un controlador de matriz y un enlace de datos a una vista de tabla. Para obtener más información sobre cómo trabajar con vistas de tabla, consulte nuestra documentación de vistas de tabla.
En primer lugar, vamos a agregar un nuevo controlador de vistas a nuestro archivo Main.storyboard en Interface Builder nombre a su clase :
A continuación, vamos a editar el archivo TableViewController.cs (que se agregó automáticamente a nuestro proyecto) y a exponer una matriz ( ) de clases a las que se enlazará el PersonModel formulario. Agregue el código siguiente:
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");
}
Al igual que hicimos en la clase anterior en la sección Definición del modelo de datos, hemos expuesto cuatro métodos públicos con nombre especial para que el controlador de matriz y lean y escriban datos de nuestra PersonModel colección de PersonModelPersonModels .
A continuación, cuando se cargue la vista, es necesario rellenar la matriz con este código:
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"));
}
Ahora tenemos que crear nuestra vista de tabla, haga doble clic en el archivo Main.storyboard para abrirlo para editarlo en Interface Builder. Diseño de la tabla para que sea algo parecido a lo siguiente:
Es necesario agregar un controlador de matriz para proporcionar datos enlazados a la tabla; para ello, haga lo siguiente:
Arrastre un controlador de matriz desde el Inspector de biblioteca hasta el Editor de interfaces:

Seleccione Controlador de matriz en la jerarquía de interfaz y cambie al Inspector de atributos:
Escriba
PersonModelen Nombre dePersonModel, haga clic en el botón Más y agregue tres claves. Así mismo,NameOccupationdenles el nombre yisManager:
Esto indica al controlador de matriz de qué está administrando una matriz y qué propiedades debe exponer (a través de claves).
Cambie al Inspector de enlaces y, en Content Array (Matriz de contenido),seleccione Bind to (Enlazar a) y Table View Controller (Controlador de vistas de tabla). Escriba una ruta de acceso de clave de modelo de :

Esto vincula el controlador de matriz a la matriz
PersonModelsde que se expone en el controlador de vista.
Ahora tenemos que enlazar nuestra vista de tabla al controlador de matriz, haga lo siguiente:
Seleccione la Vista de tabla y el Inspector de enlace:
En la lista desplegable Contenido de la tabla, seleccione Enlazar a y Controlador de matriz. Escriba
arrangedObjectsen el campo Clave delarrangedObjects
Seleccione la celda Vista de tabla en la columna Empleado. En el Inspector de enlaces de la lista desplegable Valor, seleccione Enlazar a y Vista de celda de tabla. Escriba
objectValue.Namepara la ruta de acceso de la clave deobjectValue.NameobjectValuees el actualPersonModelde la matriz que administra el controlador de matriz.Seleccione la celda Vista de tabla en la columna Ocupación. En el Inspector de enlaces de la lista desplegable Valor, seleccione Enlazar a y Vista de celda de tabla. Escriba
objectValue.Occupationpara la ruta de acceso de la clave deobjectValue.OccupationGuarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Si ejecutamos la aplicación, la tabla se rellenará con nuestra matriz de PersonModels :
vista Esquema enlace de datos
el enlace de datos con una vista esquema es muy similar al enlace con una vista de tabla. La diferencia clave es que usaremos un controlador de árbol en lugar de un controlador de matriz para proporcionar los datos enlazados a la vista esquema. Para obtener más información sobre cómo trabajar con vistas de esquema, consulte nuestra documentación de vistas de esquema.
En primer lugar, vamos a agregar un nuevo controlador de vistas a nuestro archivo Main.storyboard en Interface Builder nombre a su clase :
A continuación, vamos a editar el archivo OutlineViewController.cs (que se agregó automáticamente a nuestro proyecto) y a exponer una matriz () de clases a las que se enlazará el PersonModel formulario. Agregue el código siguiente:
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");
}
Al igual que hicimos en la clase anterior en la sección Definición del modelo de datos, hemos expuesto cuatro métodos públicos con nombre especial para que el controlador de árbol y lean y escriban datos de nuestra PersonModel colección de PersonModelPersonModels .
A continuación, cuando se cargue la vista, es necesario rellenar la matriz con este código:
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);
}
Ahora tenemos que crear nuestra vista esquema, haga doble clic en el archivo Main.storyboard para abrirlo para editarlo en Interface Builder. Diseño de la tabla para que sea algo parecido a lo siguiente:
Es necesario agregar un controlador de árbol para proporcionar datos enlazados a nuestro esquema; haga lo siguiente:
Arrastre un controlador de árbol desde el Inspector de biblioteca hasta el Editor de interfaces:
un controlador de árbol de laSeleccione Controlador de árbol en la jerarquía de interfaz y cambie al Inspector de atributos:
Escriba
PersonModelen Nombre dePersonModel, haga clic en el botón Más y agregue tres claves. Así mismo,NameOccupationdenles el nombre yisManager:
Esto indica al controlador de árbol de qué administra una matriz y qué propiedades debe exponer (a través de claves).
En la sección Tree Controller (Controlador de árbol), escriba en Children (Secundarios),escriba en Count (Recuento) y escriba en Leaf (Hoja):
Establecer lasEsto indica al controlador de árbol dónde encontrar los nodos secundarios, cuántos nodos secundarios hay y si el nodo actual tiene nodos secundarios.
Cambie al Inspector de enlaces y, en Content Array (Matriz de contenido),seleccione Bind to (Enlazara) y File's Owner (Propietario del archivo). Escriba una ruta de acceso de clave de modelo de :
claveEsto vincula el controlador de árbol a la matriz
PersonModelsde que se expone en el controlador de vista.
Ahora tenemos que enlazar nuestra vista esquema al controlador de árbol, haga lo siguiente:
Seleccione la vista Esquema y, en el Inspector de enlace, seleccione :
En la lista desplegable Contenido de la vista esquema, seleccione Enlazar a y Controlador de árbol. Escriba
arrangedObjectsen el campo Clave delarrangedObjects
Establecimiento de la clave delSeleccione la celda Vista de tabla en la columna Empleado. En el Inspector de enlaces de la lista desplegable Valor, seleccione Enlazar a y Vista de celda de tabla. Escriba
objectValue.Namepara la ruta de acceso de la clave deobjectValue.NameobjectValuees el actualPersonModelde la matriz que administra el controlador de árbol.Seleccione la celda Vista de tabla en la columna Ocupación. En el Inspector de enlaces de la lista desplegable Valor, seleccione Enlazar a y Vista de celda de tabla. Escriba
objectValue.Occupationpara la ruta de acceso de la clave deobjectValue.OccupationGuarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Si ejecutamos la aplicación, el esquema se rellenará con nuestra matriz de PersonModels :
Enlace de datos de la vista de recopilación
El enlace de datos con una vista de colección es muy parecido al enlace con una vista de tabla, ya que se usa un controlador de matriz para proporcionar datos para la colección. Puesto que la vista de colección no tiene un formato de presentación preestablecido, se requiere más trabajo para proporcionar comentarios sobre la interacción del usuario y realizar un seguimiento de la selección del usuario.
Importante
Debido a un problema en Xcode 7 y macOS 10.11 (y superiores), las vistas de colección no se pueden usar dentro de un archivo Storyboard (.storyboard). Como resultado, deberá seguir usando archivos .xib para definir las vistas de colección para las aplicaciones de Xamarin.Mac. Consulte nuestra documentación de vistas de colección para obtener más información.
Depuración de bloqueos nativos
Si se produce un error en los enlaces de datos, se puede producir un bloqueo nativo en código no administrado y hacer que la aplicación de Xamarin.Mac no se pueda realizar completamente con un error:
Ejemplo de un cuadro de diálogo de bloqueo
Normalmente, hay cuatro causas principales de bloqueos nativos durante el enlace de datos:
- El modelo de datos no hereda de
NSObjectni de una subclase deNSObject. - No exponía la propiedad a Objective-C mediante el
[Export("key-name")]atributo . - No ha encapsulado los cambios en el valor del accessor en las llamadas al método y
WillChangeValue(especificando la misma clave que el atributoDidChangeValueExport). - Tiene una clave incorrecta o con un tipo incorrecto en el Inspector de enlace en Interface Builder.
Decoding a crash
Vamos a provocar un bloqueo nativo en el enlace de datos para que podamos mostrar cómo localizarlo y corregirlo. En Interface Builder, vamos a cambiar el enlace de la primera etiqueta en el ejemplo de la vista de colección de Name a Title :
Vamos a guardar el cambio, volver a Visual Studio para Mac sincronizar con Xcode y ejecutar la aplicación. Cuando se muestra la vista de recopilación, la aplicación se bloqueará momentáneamente con un error (como se muestra en la salida de la aplicación en Visual Studio para Mac), ya que no expone una propiedad con la SIGABRTSIGABRTPersonModel clave Title :
Si nos desplazamos hasta la parte superior del error en la salida de la aplicación, podemos ver la clave para resolver el problema:
Búsqueda del problema en el registro de
Esta línea nos dice que la clave Title no existe en el objeto al que estamos enlazando. Si cambiamos el enlace a en Interface Builder, guardar, sincronizar, recompilar y ejecutar, la aplicación se ejecutará según lo previsto Name sin problemas.
Resumen
En este artículo se ha detallado cómo trabajar con el enlace de datos y la codificación de clave-valor en una aplicación de Xamarin.Mac. En primer lugar, se ha visto la exposición de una clase de C# a mediante la codificación de clave-valor (KVC) y la observación Objective-C de clave-valor (KVO). A continuación, se mostró cómo usar una clase compatible con KVO y enlazarla a los elementos de la interfaz de usuario en el Interface Builder de Xcode. Por último, mostró un enlace de datos complejo mediante controladores de matriz y controladores de árbol.
Vínculos relacionados
- Guión gráfico macDatabinding (ejemplo)
- XIBs de MacDatabinding (ejemplo)
- Hello, Mac
- Controles estándar
- Vistas de tabla
- Vistas de esquema
- Vistas de colecciones
- Guía de programación de codificación de clave-valor
- Introducción a Key-Value de programación de observación
- Introducción a los temas de programación de enlaces de Cocoa
- Introducción a la referencia de enlaces de Cocoa
- NSCollectionView
- Directrices de la interfaz humana de macOS








no administradores
de una nueva vista de tabla)
Seleccionar el inspector de




de la vista de
Selección del inspector de




Ejemplo de un error de