Vistas de tabla en Xamarin.Mac
En este artículo se explica cómo trabajar con vistas de tabla en una aplicación de Xamarin.Mac. Describe cómo crear vistas de tabla en Xcode Interface Builder e interactuar con ellas en el código.
Al trabajar con C# y .NET en una aplicación de Xamarin.Mac, tiene acceso a las mismas vistas de tabla en las que trabaja un desarrollador y Objective-CObjective-C Dado que Xamarin.Mac se integra directamente con Xcode, puede usar el Interface Builder de Xcode para crear y mantener las vistas de tabla (o, opcionalmente, crearlas directamente en código de C#).
Una vista de tabla muestra los datos en un formato tabular que contiene una o varias columnas de información en varias filas. En función del tipo de vista de tabla que se crea, el usuario puede ordenar por columna, reorganizar columnas, agregar columnas, quitar columnas o editar los datos contenidos en la tabla.
En este artículo, se tratarán los conceptos básicos de trabajar con vistas de tabla en una aplicación de Xamarin.Mac. Se recomienda encarecidamente que trabaje primero en el artículo Hello, Mac, en concreto en las secciones Introduction to Xcode and Interface Builder and Outlets and Actions (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.
También puede echar un vistazo a la sección del documento Exposing C# classes / methods to Objective-CExposing C# classes / methods to Objective-C internos de Xamarin.Mac), donde se explican los comandos y que se usan para conectar las clases de C# a objetos y elementos de interfaz de RegisterExportObjective-C usuario.
Introducción a las vistas de tabla
Una vista de tabla muestra los datos en un formato tabular que contiene una o varias columnas de información en varias filas. Las vistas de tabla se muestran dentro de vistas de desplazamiento ( ) y, a partir de NSScrollView macOS 10.7, puede usar cualquier en lugar de Celdas ( ) para mostrar filas NSViewNSCell y columnas. Dicho esto, todavía puede usar, pero normalmente creará NSCell subclase NSTableCellView y creará las filas y columnas personalizadas.
Una vista de tabla no almacena sus propios datos, sino que se basa en un origen de datos ( ) para proporcionar las filas y columnas necesarias, según sea NSTableViewDataSource necesario.
El comportamiento de una vista de tabla se puede personalizar proporcionando una subclase del delegado de vista de tabla ( ) para admitir la administración de columnas de tabla, escriba para seleccionar la funcionalidad, la selección y edición de filas, el seguimiento personalizado y las vistas personalizadas para columnas y filas NSTableViewDelegate individuales.
Al crear vistas de tabla, Apple sugiere lo siguiente:
- Permita al usuario ordenar la tabla haciendo clic en encabezados de columna.
- Cree encabezados de columna que sean sustantivos o frases de nombre cortos que describan los datos que se muestran en esa columna.
Para obtener más información, consulte la sección Vistas de contenido de las directrices de interfaz humana de OS X deApple.
Creación y mantenimiento de vistas de tabla en Xcode
Cuando se crea una nueva aplicación Xamarin.Mac Cocoa, se obtiene una ventana estándar en blanco de forma predeterminada. Esta ventana se define en un .storyboard archivo incluido automáticamente en el proyecto. Para editar el diseño de windows, en la Explorador de soluciones, haga doble clic en el archivo:
Se abrirá el diseño de la ventana en la ventana de Xcode Interface Builder:
Escriba en el cuadro de búsqueda del inspector de biblioteca para facilitar table la búsqueda de los controles de vista de tabla: table
Arrastre una vista de tabla al controlador de vistas en el Editorde interfaz , haga que rellene el área de contenido del controlador de vistas y esta establezca en donde se reduce y crece con la ventana en el Editor de restricciones:
Seleccione la Vista de tabla en la jerarquía de interfaz y las siguientes propiedades están disponibles en el Inspector de atributos:
- Modo de contenido: permite usar vistas ( ) o celdas ( ) para mostrar
NSCelllos datos en las filas y columnas. A partir de macOS 10.7, debe usar Vistas. - Filas de grupo floats: si es , la vista Tabla dibujará celdas agrupadas como si hubieran estado flotantes.
- Columnas: define el número de columnas que se muestran.
- Encabezados: si es , las columnas tendrán encabezados.
- Reordenación: si es , el usuario podrá arrastrar para volver a ordenar las columnas de la tabla.
- Cambio de tamaño: si es , el usuario podrá arrastrar los encabezados de columna para cambiar el tamaño de las columnas.
- Ajuste de tamaño de columna: controla cómo la tabla dimensiona automáticamente las columnas.
- Resaltar: controla el tipo de resaltado que usa la tabla cuando se selecciona una celda.
- Filas alternativas: si es , cualquier otra fila tendrá un color de fondo diferente.
- Cuadrícula horizontal: selecciona el tipo de borde dibujado entre las celdas horizontalmente.
- Cuadrícula vertical: selecciona el tipo de borde dibujado entre celdas verticalmente.
- Color de cuadrícula: establece el color del borde de la celda.
- Fondo: establece el color de fondo de la celda.
- Selección: permite controlar cómo el usuario puede seleccionar las celdas de la tabla como:
- Varios: si es , el usuario puede seleccionar varias filas y columnas.
- Columna: si es , el usuario puede seleccionar columnas.
- Seleccionar tipo: si es , el usuario puede escribir un carácter para seleccionar una fila.
- Vacío: si , el usuario no tiene que seleccionar una fila o columna, la tabla no permite ninguna selección.
- Autoguardar: el nombre en el que se guarda automáticamente el formato de las tablas.
- Información de columna: si es , el orden y el ancho de las columnas se guardarán automáticamente.
- Saltos de línea: seleccione cómo controla la celda los saltos de línea.
- Trunca la última línea visible: si es , la celda se truncará en los datos que no caben dentro de sus límites.
Importante
A menos que mantenga una aplicación de Xamarin.Mac heredada, las vistas de tabla basadas se NSView deben usar en vistas de tabla NSCell basadas. NSCell se considera heredado y es posible que no se puedan usar en el futuro.
Seleccione una columna de tabla en la jerarquía de interfaz y las siguientes propiedades están disponibles en el Inspector de atributos:
- Título: establece el título de la columna.
- Alineación: establece la alineación del texto dentro de las celdas.
- Fuente del título: selecciona la fuente del texto de encabezado de la celda.
- Clave de ordenación: es la clave que se usa para ordenar los datos de la columna. Déjelo en blanco si el usuario no puede ordenar esta columna.
- Selector: es la acción que se usa para realizar la ordenación. Déjelo en blanco si el usuario no puede ordenar esta columna.
- Order: es el criterio de ordenación de los datos de las columnas.
- Redimensionar: selecciona el tipo de tamaño de la columna.
- Editable: si es , el usuario puede editar las celdas de una tabla basada en celdas.
- Oculto: si es , la columna está oculta.
También puede cambiar el tamaño de la columna arrastrando su identificador (centrado verticalmente en el lado derecho de la columna) a la izquierda o derecha.
Vamos a seleccionar cada columna de nuestra vista de tabla y a dar a la primera columna un título de y a la segunda. Details
Seleccione una vista de celda de tabla ( ) en la jerarquía de interfaz y NSTableViewCell las siguientes propiedades están disponibles en el Inspector de atributos: NSTableViewCell
Estas son todas las propiedades de una vista estándar. También tiene la opción de volver a tamaño de las filas de esta columna aquí.
Seleccione una celda de vista de tabla (de forma predeterminada, es ) en la jerarquía de interfaz y las siguientes propiedades están NSTextField disponibles en el Inspector de atributos: NSTextField
Tendrá todas las propiedades de un campo de texto estándar que se establecerá aquí. De forma predeterminada, se usa un campo de texto estándar para mostrar los datos de una celda de una columna.
Seleccione una vista de celda de tabla ( ) en la jerarquía de interfaz y NSTableFieldCell las siguientes propiedades están disponibles en el Inspector de atributos: NSTableFieldCell
La configuración más importante aquí es:
- Diseño: seleccione cómo se disposición de las celdas de esta columna.
- Usa el modo de línea única: si es , la celda se limita a una sola línea.
- Primer ancho de diseño en tiempo de ejecución: si es , la celda preferirá el ancho establecido para él (ya sea manualmente o automáticamente) cuando se muestre la primera vez que se ejecute la aplicación.
- Acción: controla cuándo se envía la acción editar para la celda.
- Comportamiento: define si una celda se puede seleccionar o editar.
- Texto enriquecido: si es , la celda puede mostrar texto con formato y estilo.
- Deshacer: si es , la celda asume la responsabilidad de su comportamiento de deshacer.
Seleccione la Vista de celda de tabla ( NSTableFieldCell ) en la parte inferior de una columna de tabla en la jerarquía de NSTableFieldCell:
Esto le permite editar la vista de celda de tabla que se usa como patrón base para todas las celdas creadas para la columna especificada.
Agregar acciones y salidas
Al igual que cualquier otro control de la interfaz de usuario de Cocoa, es necesario exponer nuestra vista de tabla y sus columnas y celdas en el código de C# mediante acciones y salidas (en función de la funcionalidad necesaria).
El proceso es el mismo para cualquier elemento table view que se quiera exponer:
Cambie al Editor del asistente y asegúrese de que el archivo está seleccionado:
Seleccione la Vista de tabla en la jerarquía de interfaces,haga clic con el botón derecho en el control y arrástrela al archivo.
Cree una salida para la vista de tabla denominada :
Cree salidas para las columnas de tablas también denominadas y
DetailsColumn:Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
A continuación, escribiremos el código para mostrar algunos datos de la tabla cuando se ejecute la aplicación.
Rellenar la vista de tabla
Con nuestra vista de tabla diseñada en Interface Builder y expuesta a través de una salida ,a continuación, es necesario crear el código de C# para rellenarlo.
En primer lugar, vamos a crear una nueva Product clase para contener la información de las filas individuales. En la Explorador de soluciones, haga clic con el botón derecho en el Project y seleccione Agregar nuevo archivo... Seleccione GeneralEmpty Class (Clase vacíageneral), escriba en Name (Nombre) y haga clic en el botón New (Nuevo):
Haga que Product.cs el archivo sea parecido al siguiente:
using System;
namespace MacTables
{
public class Product
{
#region Computed Properties
public string Title { get; set;} = "";
public string Description { get; set;} = "";
#endregion
#region Constructors
public Product ()
{
}
public Product (string title, string description)
{
this.Title = title;
this.Description = description;
}
#endregion
}
}
A continuación, es necesario crear una subclase de NSTableDataSource para proporcionar los datos de la tabla tal como se solicita. En la Explorador de soluciones, haga clic con el botón derecho en el Project y seleccione Agregar nuevo archivo... Seleccione GeneralEmpty Class (Clase vacíageneral), escriba en Name (Nombre) y haga clic en el botón New (Nuevo).
Edite ProductTableDataSource.cs el archivo y haga que sea parecido al siguiente:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDataSource : NSTableViewDataSource
{
#region Public Variables
public List<Product> Products = new List<Product>();
#endregion
#region Constructors
public ProductTableDataSource ()
{
}
#endregion
#region Override Methods
public override nint GetRowCount (NSTableView tableView)
{
return Products.Count;
}
#endregion
}
}
Esta clase tiene almacenamiento para los elementos de la vista de tabla e invalida para GetRowCount devolver el número de filas de la tabla.
Por último, es necesario crear una subclase de NSTableDelegate para proporcionar el comportamiento de la tabla. En la Explorador de soluciones, haga clic con el botón derecho en el Project y seleccione Agregar nuevo archivo... Seleccione GeneralEmpty Class (Clase vacíageneral), escriba en Name (Nombre) y haga clic en el botón New (Nuevo).
Edite ProductTableDelegate.cs el archivo y haga que sea parecido al siguiente:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDelegate: NSTableViewDelegate
{
#region Constants
private const string CellIdentifier = "ProdCell";
#endregion
#region Private Variables
private ProductTableDataSource DataSource;
#endregion
#region Constructors
public ProductTableDelegate (ProductTableDataSource datasource)
{
this.DataSource = datasource;
}
#endregion
#region Override Methods
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = CellIdentifier;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = false;
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
#endregion
}
}
Cuando se crea una instancia de , también se pasa una instancia ProductTableDelegate de que proporciona los datos de la ProductTableDataSource tabla. El GetViewForItem método es responsable de devolver una vista (datos) para mostrar la celda de una columna y fila de tipo give. Si es posible, se reutilizará una vista existente para mostrar la celda, si no se debe crear una nueva vista.
Para rellenar la tabla, vamos a editar el ViewController.cs archivo y hacer que el método sea parecido al AwakeFromNib siguiente:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Create the Product Table Data Source and populate it
var DataSource = new ProductTableDataSource ();
DataSource.Products.Add (new Product ("Xamarin.iOS", "Allows you to develop native iOS Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Android", "Allows you to develop native Android Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Mac", "Allows you to develop Mac native Applications in C#"));
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (DataSource);
}
Si ejecutamos la aplicación, se muestra lo siguiente:
Ordenación por columna
Vamos a permitir que el usuario ordene los datos de la tabla haciendo clic en un encabezado de columna. En primer lugar, haga doble Main.storyboard clic en el archivo para abrirlo para editarlo en Interface Builder. Seleccione la Product columna , escriba para la clave de TitleProduct, compare: para el Title y seleccione para Ascending el compare::
Seleccione la Details columna , escriba para la clave de DescriptionDetails, compare: para el Description y seleccione para Ascending el compare::
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Ahora vamos a editar el ProductTableDataSource.cs archivo y agregar los métodos siguientes:
public void Sort(string key, bool ascending) {
// Take action based on key
switch (key) {
case "Title":
if (ascending) {
Products.Sort ((x, y) => x.Title.CompareTo (y.Title));
} else {
Products.Sort ((x, y) => -1 * x.Title.CompareTo (y.Title));
}
break;
case "Description":
if (ascending) {
Products.Sort ((x, y) => x.Description.CompareTo (y.Description));
} else {
Products.Sort ((x, y) => -1 * x.Description.CompareTo (y.Description));
}
break;
}
}
public override void SortDescriptorsChanged (NSTableView tableView, NSSortDescriptor[] oldDescriptors)
{
// Sort the data
if (oldDescriptors.Length > 0) {
// Update sort
Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
} else {
// Grab current descriptors and update sort
NSSortDescriptor[] tbSort = tableView.SortDescriptors;
Sort (tbSort[0].Key, tbSort[0].Ascending);
}
// Refresh table
tableView.ReloadData ();
}
El método nos permite ordenar los datos en el origen de datos en función de un campo de clase determinado en orden ascendente SortProduct o descendente. Se llamará al SortDescriptorsChanged método invalidado cada vez que el uso haga clic en un encabezado de columna. Se le pasará el valor de clave que establecimos en Interface Builder y el criterio de ordenación de esa columna.
Si ejecutamos la aplicación y hacemos clic en los encabezados de columna, las filas se ordenarán por esa columna:
Selección de filas
Si desea permitir que el usuario seleccione una sola fila, haga doble clic en el archivo para abrirlo para editarlo Main.storyboard en Interface Builder. Seleccione la Vista de tabla en la jerarquía de interfaces y desactive la casilla Varios en el Inspector de atributos:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
A continuación, ProductTableDelegate.cs edite el archivo y agregue el método siguiente:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
Esto permitirá al usuario seleccionar cualquier fila única en la vista tabla. Vuelva para cualquier fila que no desee que el usuario pueda seleccionar o para cada fila si no desea que el usuario pueda seleccionar falseShouldSelectRow ninguna false fila.
La vista de tabla ( NSTableView ) contiene los métodos siguientes para trabajar con la selección de filas:
DeselectRow(nint): anula la selección de la fila dada en la tabla.SelectRow(nint,bool): selecciona la fila dada. Pasefalsepara que el segundo parámetro seleccione solo una fila a la vez.SelectedRow: devuelve la fila actual seleccionada en la tabla.IsRowSelected(nint): devuelvetruesi se selecciona la fila determinada.
Selección de varias filas
Si desea permitir que el usuario seleccione varias filas, haga doble clic en el archivo para abrirlo para editarlo Main.storyboard en Interface Builder. Seleccione la Vista de tabla en la jerarquía de interfaces y active la casilla Varios en el Inspector de atributos:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
A continuación, ProductTableDelegate.cs edite el archivo y agregue el método siguiente:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
Esto permitirá al usuario seleccionar cualquier fila única en la vista tabla. Vuelva para cualquier fila que no desee que el usuario pueda seleccionar o para cada fila si no desea que el usuario pueda seleccionar falseShouldSelectRow ninguna false fila.
La vista de tabla ( NSTableView ) contiene los métodos siguientes para trabajar con la selección de filas:
DeselectAll(NSObject): anula la selección de todas las filas de la tabla. Usethispara el primer parámetro que se va a enviar en el objeto que hace la selección.DeselectRow(nint): anula la selección de la fila dada en la tabla.SelectAll(NSobject): selecciona todas las filas de la tabla. Usethispara el primer parámetro que se va a enviar en el objeto que hace la selección.SelectRow(nint,bool): selecciona la fila dada. Pase para el segundo parámetro borre la selección y seleccione solo una fila, pase parafalseampliar la selección e incluya estatruefila.SelectRows(NSIndexSet,bool): selecciona el conjunto de filas determinado. Pase para el segundo parámetro borre la selección y seleccione solo una de estas filas, pase parafalseampliar la selección e incluir estastruefilas.SelectedRow: devuelve la fila actual seleccionada en la tabla.SelectedRows: devuelve unNSIndexSetobjeto que contiene los índices de las filas seleccionadas.SelectedRowCount: devuelve el número de filas seleccionadas.IsRowSelected(nint): devuelvetruesi se selecciona la fila determinada.
Tipo para seleccionar fila
Si desea permitir que el usuario escriba un carácter con la Vista de tabla seleccionada y seleccione la primera fila que tenga ese carácter, haga doble clic en el archivo para abrirlo para editarlo en Main.storyboard Interface Builder. Seleccione la Vista de tabla en la jerarquía de interfaces y active la casilla Seleccionar tipo en el Inspector de atributos:
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Ahora vamos a editar el ProductTableDelegate.cs archivo y agregar el método siguiente:
public override nint GetNextTypeSelectMatch (NSTableView tableView, nint startRow, nint endRow, string searchString)
{
nint row = 0;
foreach(Product product in DataSource.Products) {
if (product.Title.Contains(searchString)) return row;
// Increment row counter
++row;
}
// If not found select the first row
return 0;
}
El GetNextTypeSelectMatch método toma el objeto dado y devuelve la fila del primero que tiene esa cadena en su searchStringProduct . Title
Si ejecutamos la aplicación y escribemos un carácter, se selecciona una fila:
Reordenación de columnas
Si desea permitir que el usuario arrastre las columnas de reordenación en la vista tabla, haga doble clic en el archivo para abrirlo para editarlo en Main.storyboard Interface Builder. Seleccione la Vista de tabla en la jerarquía de interfaces y active la casilla Reordenar en el Inspector de atributos:
Si se proporciona un valor para la propiedad Autosave y se comprueba el campo Información de columna, los cambios que realicemos en el diseño de la tabla se guardarán automáticamente y se restaurarán la próxima vez que se ejecute la aplicación.
Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.
Ahora vamos a editar el ProductTableDelegate.cs archivo y agregar el método siguiente:
public override bool ShouldReorder (NSTableView tableView, nint columnIndex, nint newColumnIndex)
{
return true;
}
El método debe devolver para cualquier columna que quiera permitir que se arrastre ShouldReordertrue reordenada a newColumnIndex , de lo contrario, devuelve false ;
Si ejecutamos la aplicación, podemos arrastrar encabezados de columna para reordenar nuestras columnas:
Edición de celdas
Si desea permitir que el usuario edite los valores de una celda determinada, edite el archivo y cambie el ProductTableDelegate.cs método como se muestra a GetViewForItem continuación:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = tableColumn.Title;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = true;
view.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.Tag].Title = view.StringValue;
break;
case "Details":
DataSource.Products [(int)view.Tag].Description = view.StringValue;
break;
}
};
}
// Tag view
view.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Ahora, si ejecutamos la aplicación, el usuario puede editar las celdas en la vista tabla:
Usar imágenes en vistas de tabla
Para incluir una imagen como parte de la celda en , deberá cambiar la forma en que el método de la vista de tabla devuelve los datos para usar un en lugar del típico NSTableViewNSTableViewDelegate'sGetViewForItemNSTableCellViewNSTextField . Por ejemplo:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
if (tableColumn.Title == "Product") {
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
} else {
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
}
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
view.Identifier = tableColumn.Title;
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
}
// Tag view
view.TextField.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tags.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Para obtener más información, consulte la sección Uso de imágenes con vistas de tabla de nuestra documentación sobre cómo trabajar con imágenes.
Agregar un botón Eliminar a una fila
En función de los requisitos de la aplicación, puede haber ocasiones en las que necesite proporcionar un botón de acción para cada fila de la tabla. Por ejemplo, vamos a expandir el ejemplo de vista de tabla creado anteriormente para incluir un botón Eliminar en cada fila.
En primer lugar, edite en la página de Interface Builder Xcode, seleccione la Vista de tabla y aumente el número de columnas Main.storyboard a tres (3). A continuación, cambie el Título de la nueva columna a :
Guarde los cambios en el guión gráfico y vuelva a Visual Studio para Mac para sincronizar los cambios.
A continuación, ViewController.cs edite el archivo y agregue el siguiente método público:
public void ReloadTable ()
{
ProductTable.ReloadData ();
}
En el mismo archivo, modifique la creación del nuevo delegado de vista de tabla dentro del método como ViewDidLoad se muestra a continuación:
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (this, DataSource);
Ahora, edite el archivo para incluir una conexión privada al controlador de vista y tomar el controlador como parámetro al crear una nueva ProductTableDelegate.cs instancia del delegado:
#region Private Variables
private ProductTableDataSource DataSource;
private ViewController Controller;
#endregion
#region Constructors
public ProductTableDelegate (ViewController controller, ProductTableDataSource datasource)
{
this.Controller = controller;
this.DataSource = datasource;
}
#endregion
A continuación, agregue el siguiente nuevo método privado a la clase :
private void ConfigureTextField (NSTableCellView view, nint row)
{
// Add to view
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
// Configure
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
// Wireup events
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch (view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
// Tag view
view.TextField.Tag = row;
}
Esto toma todas las configuraciones de vista de texto que se estaban haciendo anteriormente en el método y las coloca en una única ubicación a la que se puede llamar (puesto que la última columna de la tabla no incluye una vista de texto, sino un GetViewForItem botón).
Por último, GetViewForItem edite el método y haga que sea parecido al siguiente:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
// Configure the view
view.Identifier = tableColumn.Title;
// Take action based on title
switch (tableColumn.Title) {
case "Product":
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Details":
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Action":
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
// Add to view
view.AddSubview (button);
break;
}
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
return view;
}
Echemos un vistazo a varias secciones de este código con más detalle. En primer lugar, si se NSTableViewCell crea una nueva acción se toma en función del nombre de la columna. Para las dos primeras columnas(Product y Details),se llama al nuevo método .
Para la columna Acción, se crea un nuevo objeto y se agrega a la celda como subconsulta:
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
...
// Add to view
view.AddSubview (button);
La propiedad button se Tag usa para contener el número de la fila que se está procesando actualmente. Este número se usará más adelante cuando el usuario solicite que se elimine una fila en el evento del Activated botón:
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
Al principio del controlador de eventos, se obtiene el botón y el producto que se encuentra en la fila de tabla determinada. A continuación, se presenta una alerta al usuario que confirma la eliminación de la fila. Si el usuario decide eliminar la fila, la fila dada se quita del origen de datos y se vuelve a cargar la tabla:
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
Por último, si la celda de vista de tabla se reutiliza en lugar de crearse como nueva, el código siguiente la configura en función de la columna que se está procesando:
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
En la columna Acción, se examinan todas las subconsidciones hasta que se encuentra y, a continuación, su propiedad se actualiza para que apunte a la fila Tag actual.
Con estos cambios en su lugar, cuando se ejecuta la aplicación, cada fila tendrá un botón Eliminar:
Cuando el usuario hace clic en un botón Eliminar, se mostrará una alerta en la que se le pedirá que elimine la fila dada:
Si el usuario elige eliminar, se quitará la fila y se volverá a dibujar la tabla:
Vistas de tabla de enlace de datos
Al usar Key-Value codificación y enlace de datos en la aplicación 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 desacomanar aún más los datos de respaldo(modelode datos) de su front-end Interfaz de usuario(modelo-vista-controlador),lo que facilita el mantenimiento y el diseño de aplicaciones más flexible.
Key-Value Coding (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 tener acceso a ellas a través de variables de instancia o métodos de accessor ( get/set ). Al implementar Key-Value de acceso compatibles con codificación en la aplicación Xamarin.Mac, se obtiene acceso a otras características de macOS, como Key-Value Observing (KVO), enlace de datos, datos principales, enlaces de Cocoa y capacidad de script.
Para obtener más información, consulte la sección Enlace de datos de la vista de tabla de nuestra documentación sobre enlace de datos Key-Value codificación.
Resumen
En este artículo se ha detallado cómo trabajar con vistas de tabla en una aplicación de Xamarin.Mac. Vimos los diferentes tipos y usos de vistas de tabla, cómo crear y mantener vistas de tabla en el Interface Builder de Xcode y cómo trabajar con vistas de tabla en código de C#.





























