Viste tabella in Xamarin.Mac
Questo articolo illustra l'uso delle viste tabella in un'applicazione Xamarin.Mac. Descrive la creazione di viste tabella in Xcode e Interface Builder e l'interazione con esse nel codice.
Quando si lavora con C# e .NET in un'applicazione Xamarin.Mac, è possibile accedere alle stesse viste tabella in cui uno sviluppatore lavora Objective-C e Xcode . Poiché Xamarin.Mac si integra direttamente con Xcode, è possibile usare Interface Builder di Xcode per creare e gestire le viste tabella (o, facoltativamente, crearle direttamente nel codice C#).
Una vista tabella visualizza i dati in un formato tabulare contenente una o più colonne di informazioni in più righe. In base al tipo di vista tabella in fase di creazione, l'utente può ordinare in base alla colonna, riorganizzare le colonne, aggiungere colonne, rimuovere colonne o modificare i dati contenuti nella tabella.
In questo articolo verranno illustrate le nozioni di base sull'uso delle viste tabella in un'applicazione Xamarin.Mac. È consigliabile usare prima di tutto l'articolo Hello, Mac , in particolare le sezioni Introduzione a Xcode e Interface Builder e Outlet e Actions , in quanto illustra i concetti e le tecniche chiave che verranno usati in questo articolo.
È possibile esaminare anche la sezione Esposizione di classi/metodi C# al Objective-Cdocumento Internals di Xamarin.Mac, che illustra anche i Register
comandi e Export
usati per collegare le classi C# agli oggetti e agli Objective-C elementi dell'interfaccia utente.
Introduzione alle viste tabella
Una vista tabella visualizza i dati in un formato tabulare contenente una o più colonne di informazioni in più righe. Le visualizzazioni tabella vengono visualizzate all'interno di Visualizzazioni di scorrimento (NSScrollView
) e a partire da macOS 10.7, è possibile usare qualsiasi NSView
anziché celle (NSCell
) per visualizzare sia le righe che le colonne. Detto questo, è comunque possibile usare NSCell
, in genere si creeranno NSTableCellView
righe e colonne personalizzate.
Una vista tabella non archivia i propri dati, ma si basa su un'origine dati (NSTableViewDataSource
) per fornire sia le righe che le colonne necessarie, in base alle esigenze.
Il comportamento di una vista tabella può essere personalizzato fornendo una sottoclasse del delegato di visualizzazione tabella (NSTableViewDelegate
) per supportare la gestione delle colonne della tabella, digitare per selezionare funzionalità, selezione di righe e modifica, rilevamento personalizzato e visualizzazioni personalizzate per singole colonne e righe.
Quando si creano viste tabella, Apple suggerisce quanto segue:
- Consentire all'utente di ordinare la tabella facendo clic su intestazioni di colonna.
- Creare intestazioni di colonna che sono sostantivi o brevi frasi sostantive che descrivono i dati visualizzati in tale colonna.
Per altre informazioni, vedere la sezione Visualizzazioni contenuto delle linee guida sull'interfaccia umana di OS X di Apple.
Creazione e gestione di viste tabella in Xcode
Quando si crea una nuova applicazione Xamarin.Mac Cocoa, si ottiene una finestra vuota standard per impostazione predefinita. Questa finestra viene definita in un .storyboard
file incluso automaticamente nel progetto. Per modificare la progettazione delle finestre, nella Esplora soluzioni fare doppio clic sul Main.storyboard
file:
Verrà aperta la progettazione della finestra in Interface Builder di Xcode:
Digitare table
nella casella di ricerca di Controllo libreria per semplificare la ricerca dei controlli Visualizzazione tabella:
Trascinare una visualizzazione tabella nel controller di visualizzazione nell'editor dell'interfaccia, riempire l'area del contenuto del controller di visualizzazione e impostarla su dove si riduce e aumenta con la finestra nell'editor dei vincoli:
Selezionare la visualizzazione tabella nella gerarchia dell'interfaccia e le proprietà seguenti sono disponibili in Controllo attributi:
- Modalità contenuto: consente di usare visualizzazioni () o celle (
NSView
NSCell
) per visualizzare i dati nelle righe e nelle colonne. A partire da macOS 10.7, è consigliabile usare Views. - Floats Group Rows : se
true
, la vista tabella disegnare celle raggruppate come se fossero mobili. - Colonne : definisce il numero di colonne visualizzate.
- Intestazioni : se
true
, le colonne avranno intestazioni. - Riordinamento : se
true
, l'utente sarà in grado di trascinare riordinare le colonne nella tabella. - Ridimensionamento : se
true
, l'utente sarà in grado di trascinare le intestazioni di colonna per ridimensionare le colonne. - Ridimensionamento delle colonne: controlla la modalità di ridimensionamento automatico delle colonne della tabella.
- Evidenziazione : controlla il tipo di evidenziazione della tabella utilizzata quando viene selezionata una cella.
- Righe alternative: se
true
, in qualsiasi altra riga sarà presente un colore di sfondo diverso. - Griglia orizzontale: seleziona il tipo di bordo disegnato tra le celle orizzontalmente.
- Griglia verticale: seleziona il tipo di bordo disegnato tra le celle verticalmente.
- Colore griglia: imposta il colore del bordo della cella.
- Sfondo : imposta il colore di sfondo della cella.
- Selezione : consente di controllare come l'utente può selezionare le celle nella tabella come:
- Multiple : se
true
, l'utente può selezionare più righe e colonne. - Colonna: se
true
, l'utente può selezionare le colonne. - Digitare Select : se
true
, l'utente può digitare un carattere per selezionare una riga. - Vuoto : se
true
, l'utente non è necessario selezionare una riga o una colonna, la tabella non consente alcuna selezione.
- Multiple : se
- Salvataggio automatico: nome in cui viene salvato automaticamente il formato delle tabelle.
- Informazioni sulla colonna: se
true
, l'ordine e la larghezza delle colonne verranno salvati automaticamente. - Interruzioni di riga: consente di selezionare la modalità di gestione delle interruzioni di riga.
- Tronca l'ultima riga visibile: se
true
, la cella verrà troncata nei dati non può essere inserita all'interno dei limiti.
Importante
A meno che non si gestisca un'applicazione Xamarin.Mac legacy, NSView
è consigliabile usare viste tabella basate su NSCell
viste tabella basate. NSCell
è considerato legacy e potrebbe non essere supportato in futuro.
Selezionare una colonna di tabella nella gerarchia dell'interfaccia e le proprietà seguenti sono disponibili in Controllo attributi:
- Titolo : imposta il titolo della colonna.
- Allineamento : consente di impostare l'allineamento del testo all'interno delle celle.
- Titolo Carattere : seleziona il tipo di carattere per il testo Intestazione della cella.
- Chiave di ordinamento: chiave usata per ordinare i dati nella colonna. Lasciare vuoto se l'utente non è in grado di ordinare questa colonna.
- Selettore: azione usata per eseguire l'ordinamento. Lasciare vuoto se l'utente non è in grado di ordinare questa colonna.
- Order : ordinamento per i dati delle colonne.
- Ridimensionamento : seleziona il tipo di ridimensionamento per la colonna.
- Modificabile : se
true
, l'utente può modificare le celle in una tabella basata su cella. - Nascosto : se
true
, la colonna è nascosta.
È anche possibile ridimensionare la colonna trascinando il punto di manipolazione (centrato verticalmente sul lato destro della colonna) a sinistra o a destra.
Selezionare ogni colonna nella vista tabella e assegnare alla prima colonna un titolo e Product
il secondo Details
.
Selezionare una visualizzazione cella tabella (NSTableViewCell
) nella gerarchia dell'interfaccia e le proprietà seguenti sono disponibili in Controllo attributi:
Queste sono tutte le proprietà di una visualizzazione standard. È anche possibile ridimensionare le righe per questa colonna qui.
Selezionare una cella di visualizzazione tabella (per impostazione predefinita, si tratta di ) NSTextField
nella gerarchia di interfaccia e le proprietà seguenti sono disponibili in Controllo attributi:
Tutte le proprietà di un campo di testo standard verranno impostate qui. Per impostazione predefinita, viene usato un campo di testo standard per visualizzare i dati di una cella in una colonna.
Selezionare una visualizzazione cella tabella (NSTableFieldCell
) nella gerarchia dell'interfaccia e le proprietà seguenti sono disponibili in Controllo attributi:
Di seguito sono riportate le impostazioni più importanti:
- Layout : consente di selezionare la disposizione delle celle in questa colonna.
- Usa la modalità riga singola: se
true
, la cella è limitata a una singola riga. - Prima larghezza layout runtime: se
true
, la cella preferisce il set di larghezza (manualmente o automaticamente) quando viene visualizzata la prima volta che viene eseguita l'applicazione. - Azione: controlla quando viene inviata l'azione di modifica per la cella.
- Comportamento : definisce se una cella è selezionabile o modificabile.
- Rtf: se
true
, la cella può visualizzare testo formattato e in stile. - Annulla: se
true
, la cella assume la responsabilità del comportamento di annullamento.
Selezionare la vista cella tabella (NSTableFieldCell
) nella parte inferiore di una colonna tabella nella gerarchia dell'interfaccia:
In questo modo è possibile modificare la visualizzazione cella tabella usata come modello di base per tutte le celle create per la colonna specificata.
Aggiunta di azioni e punti di vendita
Proprio come qualsiasi altro controllo dell'interfaccia utente cocoa, è necessario esporre la vista tabella e le colonne e le celle al codice C# usando Azioni e outlet (in base alle funzionalità necessarie).
Il processo è lo stesso per qualsiasi elemento Table View che si vuole esporre:
Passare all'Editor assistente e verificare che il
ViewController.h
file sia selezionato:Selezionare la visualizzazione tabella dalla gerarchia dell'interfaccia, fare clic e trascinare nel
ViewController.h
file.Creare un outlet per la vista tabella denominata
ProductTable
:Creare outlet per le colonne delle tabelle denominate
ProductColumn
eDetailsColumn
:Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
Successivamente, il codice visualizzerà alcuni dati per la tabella quando viene eseguita l'applicazione.
Popolamento della vista tabella
Con la vista tabella progettata in Interface Builder ed esposta tramite un outlet, è quindi necessario creare il codice C# per popolarlo.
Creare prima di tutto una nuova Product
classe per contenere le informazioni per le singole righe. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota generale>), immettere Product
per Name (Nome) e fare clic sul pulsante New (Nuovo):
Fare in modo che il Product.cs
file sia simile al seguente:
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
}
}
Successivamente, è necessario creare una sottoclasse di NSTableDataSource
per fornire i dati per la tabella in quanto richiesto. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota Generale>), immettere ProductTableDataSource
per Name (Nome) e fare clic sul pulsante New (Nuovo).
Modificare il ProductTableDataSource.cs
file e renderlo simile al seguente:
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
}
}
Questa classe dispone di spazio di archiviazione per gli elementi della vista tabella ed esegue l'override GetRowCount
di per restituire il numero di righe nella tabella.
Infine, è necessario creare una sottoclasse di NSTableDelegate
per fornire il comportamento per la tabella. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota Generale>), immettere ProductTableDelegate
per Name (Nome) e fare clic sul pulsante New (Nuovo).
Modificare il ProductTableDelegate.cs
file e renderlo simile al seguente:
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
}
}
Quando si crea un'istanza ProductTableDelegate
di , viene passata anche un'istanza ProductTableDataSource
di che fornisce i dati per la tabella. Il GetViewForItem
metodo è responsabile della restituzione di una vista (dati) per visualizzare la cella per una colonna e una riga di tipo give. Se possibile, verrà riutilizzata una visualizzazione esistente per visualizzare la cella, se non è necessario creare una nuova visualizzazione.
Per popolare la tabella, modificare il ViewController.cs
file e fare in modo che il AwakeFromNib
metodo sia simile al seguente:
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);
}
Se si esegue l'applicazione, viene visualizzato quanto segue:
Ordinamento per colonna
Consentire all'utente di ordinare i dati nella tabella facendo clic su un'intestazione di colonna. Prima di tutto, fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder. Selezionare la Product
colonna, immettere Title
per La chiave di ordinamento, compare:
per il selettore e selezionare Ascending
per l'ordine:
Selezionare la Details
colonna, immettere Description
per La chiave di ordinamento, compare:
per il selettore e selezionare Ascending
per l'ordine:
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
A questo punto, modificare il ProductTableDataSource.cs
file e aggiungere i metodi seguenti:
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 ();
}
Il Sort
metodo consente di ordinare i dati nell'origine dati in base a un determinato Product
campo di classe in ordine crescente o decrescente. Il metodo sottoposto SortDescriptorsChanged
a override verrà chiamato ogni volta che l'utilizzo fa clic su un'intestazione di colonna. Verrà passato il valore chiave impostato in Interface Builder e l'ordinamento per tale colonna.
Se si esegue l'applicazione e si fa clic nelle intestazioni di colonna, le righe verranno ordinate in base a tale colonna:
Selezione riga
Se si desidera consentire all'utente di selezionare una singola riga, fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder. Selezionare la visualizzazione tabella nella gerarchia dell'interfaccia e deselezionare la casella di controllo Multiple (Controllo attributi):
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
Modificare quindi il ProductTableDelegate.cs
file e aggiungere il metodo seguente:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
In questo modo l'utente potrà selezionare qualsiasi singola riga nella visualizzazione tabella. Restituisce false
per qualsiasi ShouldSelectRow
riga che non si vuole che l'utente sia in grado di selezionare o false
per ogni riga se non si vuole che l'utente sia in grado di selezionare alcuna riga.
La vista tabella (NSTableView
) contiene i metodi seguenti per l'utilizzo della selezione di righe:
DeselectRow(nint)
- Deseleziona la riga specificata nella tabella.SelectRow(nint,bool)
- Seleziona la riga specificata. Passarefalse
per il secondo parametro per selezionare una sola riga alla volta.SelectedRow
: restituisce la riga corrente selezionata nella tabella.IsRowSelected(nint)
- Restituiscetrue
se la riga specificata è selezionata.
Selezione di più righe
Se si desidera consentire all'utente di selezionare più righe, fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder. Selezionare la visualizzazione tabella nella gerarchia dell'interfaccia e selezionare la casella di controllo Multipla in Controllo attributi:
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
Modificare quindi il ProductTableDelegate.cs
file e aggiungere il metodo seguente:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
In questo modo l'utente potrà selezionare qualsiasi singola riga nella visualizzazione tabella. Restituisce false
per qualsiasi ShouldSelectRow
riga che non si vuole che l'utente sia in grado di selezionare o false
per ogni riga se non si vuole che l'utente sia in grado di selezionare alcuna riga.
La vista tabella (NSTableView
) contiene i metodi seguenti per l'utilizzo della selezione di righe:
DeselectAll(NSObject)
- Deseleziona tutte le righe nella tabella. Utilizzarethis
per il primo parametro da inviare nell'oggetto eseguendo la selezione.DeselectRow(nint)
- Deseleziona la riga specificata nella tabella.SelectAll(NSobject)
- Seleziona tutte le righe nella tabella. Utilizzarethis
per il primo parametro da inviare nell'oggetto eseguendo la selezione.SelectRow(nint,bool)
- Seleziona la riga specificata. Passarefalse
per il secondo parametro deselezionare la selezione e selezionare solo una singola riga, passaretrue
per estendere la selezione e includere questa riga.SelectRows(NSIndexSet,bool)
- Seleziona il set specificato di righe. Passarefalse
per il secondo parametro deselezionare la selezione e selezionare solo una di queste righe, passaretrue
per estendere la selezione e includere queste righe.SelectedRow
: restituisce la riga corrente selezionata nella tabella.SelectedRows
: restituisce un oggettoNSIndexSet
contenente gli indici delle righe selezionate.SelectedRowCount
: restituisce il numero di righe selezionate.IsRowSelected(nint)
- Restituiscetrue
se la riga specificata è selezionata.
Digitare per selezionare riga
Se si desidera consentire all'utente di digitare un carattere con la visualizzazione tabella selezionata e selezionare la prima riga con tale carattere, fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder. Selezionare la visualizzazione tabella nella gerarchia dell'interfaccia e selezionare la casella di controllo Type Select (Seleziona tipo) in Controllo attributi:
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
A questo punto, modificare il ProductTableDelegate.cs
file e aggiungere il metodo seguente:
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;
}
Il GetNextTypeSelectMatch
metodo accetta l'oggetto specificato searchString
e restituisce la riga della prima Product
che contiene tale stringa in .Title
Se si esegue l'applicazione e si digita un carattere, viene selezionata una riga:
Riordinare le colonne
Se si desidera consentire all'utente di trascinare le colonne di riordinamento nella visualizzazione tabella, fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder. Selezionare la visualizzazione tabella nella gerarchia dell'interfaccia e selezionare la casella di controllo Riordinamento in Controllo attributi:
Se si assegna un valore per la proprietà Salvataggio automatico e si controlla il campo Informazioni colonna, le modifiche apportate al layout della tabella verranno salvate automaticamente e ripristinate al successivo esecuzione dell'applicazione.
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
A questo punto, modificare il ProductTableDelegate.cs
file e aggiungere il metodo seguente:
public override bool ShouldReorder (NSTableView tableView, nint columnIndex, nint newColumnIndex)
{
return true;
}
Il ShouldReorder
metodo deve restituire true
per qualsiasi colonna che desidera consentire il trascinamento del trascinamento nell'oggetto newColumnIndex
, altrimenti restituire false
;
Se si esegue l'applicazione, è possibile trascinare le intestazioni di colonna per riordinare le colonne:
Modifica di celle
Se si desidera consentire all'utente di modificare i valori per una determinata cella, modificare il ProductTableDelegate.cs
file e modificare il GetViewForItem
metodo come indicato di seguito:
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;
}
A questo punto, se si esegue l'applicazione, l'utente può modificare le celle nella visualizzazione Tabella:
Uso di immagini nelle viste tabella
Per includere un'immagine come parte della cella in un NSTableView
oggetto , è necessario modificare il modo in cui i dati vengono restituiti dal metodo di NSTableViewDelegate's
GetViewForItem
Visualizzazione tabella per usare un NSTableCellView
anziché il tipico NSTextField
. Ad esempio:
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;
}
Per altre informazioni, vedere la sezione Uso di immagini con viste tabella della documentazione sull'uso dell'immagine.
Aggiunta di un pulsante Elimina a una riga
In base ai requisiti dell'app, potrebbero esserci occasioni in cui è necessario specificare un pulsante di azione per ogni riga della tabella. Di seguito è riportato un esempio di visualizzazione tabella creato in precedenza per includere un pulsante Elimina in ogni riga.
Prima di tutto, modificare in Main.storyboard
Interface Builder di Xcode, selezionare la visualizzazione tabella e aumentare il numero di colonne a tre (3). Modificare quindi il titolo della nuova colonna in Action
:
Salvare le modifiche apportate allo Storyboard e tornare a Visual Studio per Mac per sincronizzare le modifiche.
Modificare quindi il ViewController.cs
file e aggiungere il metodo pubblico seguente:
public void ReloadTable ()
{
ProductTable.ReloadData ();
}
Nello stesso file modificare la creazione del nuovo delegato di visualizzazione tabella all'interno del ViewDidLoad
metodo come indicato di seguito:
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (this, DataSource);
Modificare ora il ProductTableDelegate.cs
file in modo da includere una connessione privata al controller di visualizzazione e accettare il controller come parametro durante la creazione di una nuova istanza del delegato:
#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
Aggiungere quindi il nuovo metodo privato seguente alla classe :
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;
}
Questa operazione accetta tutte le configurazioni della visualizzazione testo eseguite in precedenza nel GetViewForItem
metodo e le inserisce in un'unica posizione chiamabile (poiché l'ultima colonna della tabella non include una visualizzazione testo ma un pulsante).
Infine, modificare il GetViewForItem
metodo e renderlo simile al seguente:
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;
}
Verranno ora esaminate più dettagliatamente diverse sezioni di questo codice. In primo luogo, se viene eseguita una nuova NSTableViewCell
azione in base al nome della colonna. Per le prime due colonne (Product e Details), viene chiamato il nuovo ConfigureTextField
metodo.
Per la colonna Azione , viene creato un nuovo NSButton
oggetto e aggiunto alla cella come visualizzazione secondaria:
// 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 proprietà Button Tag
viene utilizzata per contenere il numero della riga in fase di elaborazione. Questo numero verrà usato in un secondo momento quando l'utente richiede l'eliminazione di una riga nell'evento button Activated
:
// 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 ();
}
});
};
All'inizio del gestore eventi, si ottiene il pulsante e il prodotto che si trova nella riga della tabella specificata. Viene quindi visualizzato un avviso all'utente che conferma l'eliminazione della riga. Se l'utente sceglie di eliminare la riga, la riga specificata viene rimossa dall'origine dati e la tabella viene ricaricata:
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
Infine, se la cella di visualizzazione tabella viene riutilizzata invece di essere creata nuova, il codice seguente lo configura in base all'elaborazione della colonna:
// 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;
}
Per la colonna Azione , tutte le visualizzazioni secondarie vengono analizzate fino a quando non NSButton
viene trovato, quindi la proprietà viene Tag
aggiornata in modo che punti alla riga corrente.
Con queste modifiche apportate, quando l'app viene eseguita ogni riga avrà un pulsante Elimina :
Quando l'utente fa clic su un pulsante Elimina , verrà visualizzato un avviso che chiede di eliminare la riga specificata:
Se l'utente sceglie l'eliminazione, la riga verrà rimossa e la tabella verrà ridisegnata:
Viste tabella di data binding
Usando le tecniche di codifica chiave-valore e data binding nell'applicazione Xamarin.Mac, è possibile ridurre notevolmente la quantità di codice che è necessario scrivere e gestire per popolare e usare gli elementi dell'interfaccia utente. È anche possibile separare ulteriormente i dati di backup (Modello di dati) dall'interfaccia utente front-end (Model-View-Controller), semplificando la gestione e la progettazione di applicazioni più flessibili.
Key-Value Coding (KVC) è un meccanismo per accedere indirettamente alle proprietà di un oggetto, usando chiavi (stringhe formattate appositamente) per identificare le proprietà anziché accedervi tramite variabili di istanza o metodi di accesso (get/set
). Implementando funzioni di accesso conformi a Key-Value Coding nell'applicazione Xamarin.Mac, è possibile accedere ad altre funzionalità macOS, ad esempio Key-Value Observing (KVO), Data Binding, Core Data, Binding Cocoa e scriptability.
Per altre informazioni, vedere la sezione Associazione dati vista tabella della documentazione sul data binding e sulla codifica chiave-valore.
Riepilogo
Questo articolo ha esaminato in dettaglio l'uso delle viste tabella in un'applicazione Xamarin.Mac. Sono stati illustrati i diversi tipi e usi delle viste tabella, come creare e gestire viste tabella in Interface Builder di Xcode e come usare le viste tabella nel codice C#.
Collegamenti correlati
- Hello, Mac
- Outline Views (Visualizzazioni struttura)
- Source Lists (Elenchi di risorse)
- Data binding e codifica di chiave-valore
- Linee guida dell'interfaccia umana OS X
- NSTableView
- NSTableViewDelegate
- NSTableViewDataSource